import React from "react"; import { FindKineticProps, ThemeKey } from "./types"; import { Link } from "@shared/components/link"; import { Text } from "@shared/components/text"; import { NextImage } from "@shared/next"; export const FindKinetic: React.FC = ({ background = "white", description, enableHeading, image, list = [], localPathPrefix = "/local", subTitle, title, color = "dark", maxWidth = true, addTrailingSlash = false, }) => { const bgColorClasses: Record = { blue: "bg-[#07B2E2]", green: "bg-[#26B170]", yellow: "bg-[#F5FF1E]", purple: "bg-[#931D69]", white: "bg-white", navy: "bg-[#00002D]", }; // Trim leading/trailing slashes without a regex to avoid ReDoS on long // runs of "/" (CodeQL: polynomial regular expression on uncontrolled data). const trimSlashes = (value: string) => { let start = 0; let end = value.length; while (start < end && value.charCodeAt(start) === 47 /* "/" */) start += 1; while (end > start && value.charCodeAt(end - 1) === 47 /* "/" */) end -= 1; return value.slice(start, end); }; const cleanedLocalPathPrefix = trimSlashes(localPathPrefix ?? ""); const normalizedLocalPathPrefix = cleanedLocalPathPrefix ? `/${cleanedLocalPathPrefix}` : ""; const getLocationHref = (code: string) => `${normalizedLocalPathPrefix}/${code.toLowerCase()}${addTrailingSlash ? "/" : ""}`; return (
{title && ( {title} )} {subTitle && ( {subTitle} )}
{description && ( {description} )} {list.length > 0 && ( <>
    {(() => { const sortedList = [...list].sort((a, b) => a.name.localeCompare(b.name) ); const numColumns = 2; const numRows = Math.ceil(sortedList.length / numColumns); const rearranged = []; for (let row = 0; row < numRows; row++) { for (let col = 0; col < numColumns; col++) { const index = col * numRows + row; if (index < sortedList.length) { rearranged.push(sortedList[index]); } } } return rearranged.map((item, index: number) => (
  • {item.name}
  • )); })()}
    {(() => { const sortedList = [...list].sort((a, b) => a.name.localeCompare(b.name) ); const numColumns = 3; const numRows = Math.ceil(sortedList.length / numColumns); const rearranged = []; for (let row = 0; row < numRows; row++) { for (let col = 0; col < numColumns; col++) { const index = col * numRows + row; rearranged.push(index < sortedList.length ? sortedList[index] : null); // ← holds position } } return rearranged.map((item, index: number) => item ? (
  • {item.name}
  • ) : (
{!image && (
    {(() => { const sortedList = [...list].sort((a, b) => a.name.localeCompare(b.name) ); const numColumns = 4; const numRows = Math.ceil(sortedList.length / numColumns); const rearranged = []; for (let row = 0; row < numRows; row++) { for (let col = 0; col < numColumns; col++) { const index = col * numRows + row; rearranged.push(index < sortedList.length ? sortedList[index] : null); } } return rearranged.map((item, index: number) => item ? (
  • {item.name}
  • ) : (
)} )}
{image && ( )}
); }; export default FindKinetic;