@texturehq/edges 1.25.0 → 1.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{colors-Y8iUUTUP.d.ts → colors-Bw6dREwE.d.ts} +1 -1
- package/dist/{colors-B3YgFfeQ.d.cts → colors-nZbxzpnU.d.cts} +1 -1
- package/dist/components.manifest.json +2 -2
- package/dist/index.cjs +7 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js.map +1 -1
- package/dist/styles.css +5 -0
- package/dist/utilities.manifest.json +1 -1
- package/package.json +1 -1
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/Logo/Logo.tsx","../src/components/SideNav/SideNav.tsx","../src/components/Icon/IconSSR.tsx","../src/components/TopNav/TopNav.tsx","../src/components/AppShell/AppShell.tsx","../src/components/Avatar/Avatar.tsx","../src/components/Heading/Heading.tsx","../src/components/Loader/Loader.tsx","../src/components/TextLink/TextLink.tsx","../src/config/entities.ts","../src/utils/colors.ts","../src/utils/formatting/registry.ts","../src/utils/formatting/boolean.ts","../src/utils/formatting/number.ts","../src/utils/formatting/component-formatter.tsx","../src/utils/formatting/current.ts","../src/utils/formatting/date.ts","../src/utils/formatting/distance.ts","../src/utils/formatting/energy.ts","../src/utils/formatting/phone.ts","../src/utils/formatting/power.ts","../src/utils/formatting/resistance.ts","../src/utils/formatting/temperature.ts","../src/utils/formatting/text.ts","../src/utils/formatting/voltage.ts","../src/utils/formatting/index.ts","../src/utils/charts.ts"],"names":["Logo","className","showWordmark","width","fill","fillValue","fillClass","logoWidth","logoHeight","jsxs","jsx","SideNav","topItems","bottomItems","bottomContent","logo","showLogo","LinkComponent","mobileMenuId","sidebarCollapseId","isSectionFormat","items","normalizeToSections","renderSection","section","sectionIndex","totalSections","item","renderNavItem","isNested","categoryId","child","linkProps","linkContent","Fragment","index","sections","sizePresets","IconSSR","memo","name","size","color","weight","ariaLabel","props","IconComponent","PhosphorIconsSSR","resolvedSize","iconClassName","twMerge","IconSSRWithContainer","variant","shape","containerSize","containerClassName","ref","iconSize","resolvedContainerSize","containerClasses","TopNav","rightContent","centerContent","showMobileMenu","avatar","showColorModeSwitcher","toggleTheme","isDarkThemeEnabled","colorMode","actions","getThemeIcon","getAriaLabel","AppShell","sideNav","topNav","children","contentPaddingX","contentPaddingY","showSidebarBorder","mainClassName","enableJsEnhancements","Avatar","src","alt","firstName","lastName","fullName","onClick","status","bordered","sizeClasses","statusSizeClasses","statusPositionClasses","statusColors","variantColors","shapeClasses","baseClasses","initials","first","last","parts","getIcon","Users","Building2","User","renderAvatar","sizeVariants","heightVariants","Heading","Tag","height","heightClasses","Loader","TextLink","href","external","title","asButton","onPress","showArrow","externalProps","combinedClasses","content","ENTITY_CONFIG","getEntityConfig","entityType","getEntityIcon","getEntityLabel","plural","colorCache","getResolvedColor","variableName","fallback","varName","root","value","tempElement","resolvedColor","error","clearColorCache","getThemeCategoricalColors","colors","i","getDefaultColors","getDefaultChartColor","createCategoryColorMap","categories","customColors","colorMap","themeColors","category","isLightColor","rgb","g","b","getContrastingTextColor","backgroundColor","FormatRegistryClass","__publicField","key","formatter","args","FormatRegistry","toBoolean","trueText","falseText","toEnabledDisabled","toOnOff","toActiveInactive","toTrueFalse","toCheckmark","parseBoolean","lower","formatBoolean","format","boolValue","isNil","toPercentage","decimals","formatPercent","precision","toInteger","toFloat","toFormattedNumber","thousandsSeparator","options","toCompactNumber","display","toScientificNotation","toCurrency","currency","formatOptions","formatNumber","numValue","formatCurrency","formatComponentValue","emptyClassName","emptyText","formatted","formatFieldValue","toMilliamps","mA","toAmps","toKiloamps","autoScaleCurrent","absValue","formatCurrent","toDateTime","DateTime","dt","toDateString","showTime","timezone","dtWithZone","toRelativeTime","toFullDateTime","toISOString","toCustomDateFormat","formatDate","toMeters","toCentimeters","toMillimeters","toKilometers","toFeet","toInches","toMiles","toYards","milesToFeet","miles","autoScaleDistance","metric","formatDistance","isMetric","toWh","tokWh","toMWh","toGWh","autoScaleEnergy","formatEnergy","formatUSPhone","phone","cleaned","formatInternationalPhone","formatPhoneNumber","formatPhone","phoneStr","toWatts","toKilowatts","toMegawatts","toGigawatts","autoScalePower","formatPower","toMilliohms","toOhms","toKilohms","toMegohms","autoScaleResistance","formatResistance","temperatureStringToSymbol","unit","toFahrenheit","toCelsius","fromFahrenheit","toKelvin","toTemperature","formatTemperature","shouldHideValue","toUpperCase","text","toLowerCase","toSentenceCase","toTitleCase","articles","word","capitalize","ucFirst","camelCaseToWords","str","snakeCaseToWords","enumToSentenceCase","truncateMiddle","length","totalChars","leadingChars","trailingChars","truncateStart","truncateEnd","ellipsis","toSecret","lastFour","maskedLength","formatText","transform","position","toMillivolts","mV","toVolts","toKilovolts","autoScaleVoltage","formatVoltage","formatPercentage","num","customFormat","defaultMargin","getYFormatSettings","safeFormat","result","extractText","node","tickFormat","min","max","tickInterval","createXScale","data","dateExtent","extent","d","scaleTime","createYScale","formatType","yFormatSettings","dataYMin","dataYMax","yMin","yMax","scaleLinear"],"mappings":"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","file":"server.js","sourcesContent":["export interface LogoProps {\n className?: string;\n showWordmark?: boolean;\n width?: number;\n fill?: string;\n}\n\n/**\n * Logo\n *\n * Brand logo component with optional wordmark.\n * Supports customizable sizing and fill colors with theme-aware defaults.\n */\nexport const Logo = ({ className, showWordmark = true, width, fill }: LogoProps) => {\n // Support both fill prop and className for backward compatibility\n // Priority: fill prop > className > default (theme-aware text color)\n\n // Determine the fill value\n let fillValue: string | undefined;\n let fillClass: string | undefined;\n\n if (fill) {\n // If fill starts with \"fill-\", it's a Tailwind class\n if (fill.startsWith(\"fill-\")) {\n fillClass = fill;\n } else {\n // Otherwise, use it as a direct fill value\n fillValue = fill;\n }\n } else if (className) {\n // Use className if provided\n fillClass = className;\n } else {\n // Default to theme-aware text color using CSS variable\n fillValue = \"var(--color-text-body)\";\n }\n\n if (showWordmark) {\n const logoWidth = width || 270;\n const logoHeight = (logoWidth / 270) * 80; // Maintain aspect ratio\n\n return (\n <svg\n width={logoWidth}\n height={logoHeight}\n viewBox=\"0 0 270 80\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={fillClass}\n style={fillValue ? { fill: fillValue } : undefined}\n >\n <g clipPath=\"url(#clip0_796_283)\">\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M0.223654 20.2934C0.417233 19.8234 0.873598 19.517 1.37984 19.517H20.5909C21.282 19.517 21.8422 20.0798 21.8422 20.774V40.049C21.8422 40.5572 21.5375 41.0155 21.0702 41.2102C20.6028 41.405 20.0647 41.2977 19.7067 40.9385L0.495628 21.6635C0.137428 21.3041 0.030075 20.7633 0.223654 20.2934ZM4.40349 22.0311L19.3396 37.017V22.0311H4.40349Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 20.2934C38.8394 19.8234 39.2958 19.517 39.802 19.517H59.013C59.7041 19.517 60.2642 20.0798 60.2642 20.774V40.049C60.2642 40.5572 59.9597 41.0155 59.4923 41.2102C59.025 41.405 58.4867 41.2977 58.1289 40.9385L38.9178 21.6635C38.5595 21.3041 38.4522 20.7633 38.6458 20.2934ZM42.8255 22.0311L57.7618 37.017V22.0311H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M19.4347 58.8447C19.6283 58.3747 20.0847 58.0685 20.5909 58.0685H39.802C40.493 58.0685 41.0532 58.6312 41.0532 59.3255V78.6005C41.0532 79.1087 40.7486 79.567 40.2813 79.7617C39.8139 79.9562 39.2757 79.849 38.9178 79.49L19.7067 60.215C19.3485 59.8555 19.2411 59.3147 19.4347 58.8447ZM23.6146 60.5825L38.5508 75.5682V60.5825H23.6146Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 58.1643C39.79 57.9695 40.3283 58.0768 40.6861 58.436L59.8972 77.711C60.2555 78.0703 60.3628 78.6113 60.1692 79.081C59.9756 79.551 59.5192 79.8575 59.013 79.8575H39.802C39.1109 79.8575 38.5508 79.2948 38.5508 78.6005V59.3255C38.5508 58.8173 38.8554 58.359 39.3227 58.1643ZM41.0532 62.3575V77.3433H55.9893L41.0532 62.3575Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 19.6129C39.79 19.4182 40.3283 19.5254 40.6861 19.8846L59.8972 39.1595C60.2555 39.519 60.3628 40.0598 60.1692 40.5298C59.9756 40.9995 59.5192 41.306 59.013 41.306H39.802C39.1109 41.306 38.5508 40.7433 38.5508 40.049V20.7741C38.5508 20.2658 38.8554 19.8075 39.3227 19.6129ZM41.0532 23.8061V38.792H55.9893L41.0532 23.8061Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 38.8885C39.79 38.694 40.3283 38.8012 40.6861 39.1602L59.8972 58.4352C60.2555 58.7945 60.3628 59.3355 60.1692 59.8055C59.9756 60.2752 59.5192 60.5817 59.013 60.5817H39.802C39.1109 60.5817 38.5508 60.019 38.5508 59.3247V40.0497C38.5508 39.5415 38.8554 39.0832 39.3227 38.8885ZM41.0532 43.0817V58.0675H55.9893L41.0532 43.0817Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 39.569C38.8394 39.0992 39.2958 38.7927 39.802 38.7927H59.013C59.7041 38.7927 60.2642 39.3555 60.2642 40.0497V59.3247C60.2642 59.833 59.9597 60.2912 59.4923 60.486C59.025 60.6805 58.4867 60.5732 58.1289 60.2142L38.9178 40.9392C38.5595 40.5797 38.4522 40.039 38.6458 39.569ZM42.8255 41.3067L57.7618 56.2927V41.3067H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 58.8447C38.8394 58.3747 39.2958 58.0685 39.802 58.0685H59.013C59.7041 58.0685 60.2642 58.6312 60.2642 59.3255V78.6005C60.2642 79.1087 59.9597 79.567 59.4923 79.7617C59.025 79.9562 58.4867 79.849 58.1289 79.49L38.9178 60.215C38.5595 59.8555 38.4522 59.3147 38.6458 58.8447ZM42.8255 60.5825L57.7618 75.5682V60.5825H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M58.5338 19.6129C59.0011 19.4182 59.5394 19.5254 59.8972 19.8846L79.1083 39.1595C79.4666 39.519 79.5739 40.0598 79.3803 40.5298C79.1867 40.9995 78.7303 41.306 78.2241 41.306H59.013C58.322 41.306 57.7618 40.7433 57.7618 40.049V20.7741C57.7618 20.2658 58.0664 19.8075 58.5338 19.6129ZM60.2643 23.8061V38.792H75.2006L60.2643 23.8061Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M58.5338 0.338803C59.0011 0.144135 59.5394 0.251385 59.8972 0.610565L79.1083 19.8855C79.4666 20.2449 79.5739 20.7857 79.3803 21.2556C79.1867 21.7256 78.7303 22.032 78.2241 22.032H59.013C58.322 22.032 57.7618 21.4692 57.7618 20.775V1.50003C57.7618 0.99174 58.0664 0.533468 58.5338 0.338803ZM60.2643 4.53208V19.5179H75.2006L60.2643 4.53208Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M57.8569 20.2934C58.0505 19.8234 58.5069 19.517 59.013 19.517H78.2241C78.9151 19.517 79.4753 20.0798 79.4753 20.774V40.049C79.4753 40.5572 79.1707 41.0155 78.7034 41.2102C78.236 41.405 77.6978 41.2977 77.3399 40.9385L58.1289 21.6635C57.7705 21.3041 57.6633 20.7633 57.8569 20.2934ZM62.0365 22.0311L76.9729 37.017V22.0311H62.0365Z\"\n />\n <path d=\"M269.838 49.4457H249.005C249.266 51.801 250.162 53.6985 251.695 55.1377C253.225 56.577 255.134 57.2967 257.416 57.2967C259.307 57.2967 260.887 56.8715 262.159 56.021C263.463 55.1377 264.408 53.9927 264.996 52.5862H269.251C268.502 54.9415 267.084 56.937 264.996 58.5725C262.943 60.208 260.414 61.026 257.416 61.026C255.069 61.026 252.917 60.4697 250.961 59.3575C249.037 58.2127 247.504 56.6587 246.363 54.696C245.255 52.7332 244.7 50.558 244.7 48.17C244.7 45.782 245.255 43.6067 246.363 41.644C247.504 39.6812 249.037 38.1437 250.961 37.0315C252.917 35.8867 255.069 35.3142 257.416 35.3142C259.73 35.3142 261.833 35.8702 263.724 36.9825C265.615 38.0947 267.098 39.6485 268.176 41.644C269.283 43.6395 269.838 45.913 269.838 48.4645V49.4457ZM257.416 39.0432C255.263 39.0432 253.439 39.6812 251.939 40.957C250.47 42.2327 249.542 43.9337 249.152 46.06H265.583C265.192 43.9992 264.262 42.3145 262.796 41.006C261.36 39.6975 259.568 39.0432 257.416 39.0432Z\" />\n <path d=\"M228.356 60.5352V35.8049H232.219V39.7794H232.464C233.05 38.5689 233.963 37.5712 235.202 36.7862C236.474 35.9684 237.974 35.5594 239.701 35.5594H243.125V39.4359H239.701C237.517 39.4359 235.757 40.1554 234.42 41.5949C233.083 43.0342 232.414 44.9152 232.414 47.2377V60.5352H228.356Z\" />\n <path d=\"M208.607 61.0259C205.64 61.0259 203.326 60.1262 201.663 58.3272C200 56.4952 199.169 53.8947 199.169 50.5252V35.8047H203.228V49.8874C203.228 52.2427 203.766 54.0744 204.842 55.3829C205.95 56.6587 207.532 57.2967 209.586 57.2967C211.02 57.2967 212.308 56.9694 213.449 56.3152C214.623 55.6284 215.536 54.6959 216.188 53.5184C216.84 52.3407 217.166 50.9997 217.166 49.4949V35.8047H221.225V60.5352H217.313V56.5607H217.068C216.286 57.9019 215.161 58.9814 213.694 59.7992C212.226 60.6169 210.531 61.0259 208.607 61.0259Z\" />\n <path d=\"M186.736 39.534V56.806H194.756V60.5352H182.677V39.534H177.199V35.8047H182.677V29.5732H186.736V35.8047H193.24V39.534H186.736Z\" />\n <path d=\"M156.585 60.5352H151.988L158.394 48.0227L152.33 35.8047H156.976L162.062 46.0599H165.388L170.474 35.8047H175.022L168.958 48.0227L175.365 60.5352H170.67L165.29 49.7892H162.013L156.585 60.5352Z\" />\n <path d=\"M150.138 49.1315H129.304C129.565 51.4867 130.461 53.3842 131.994 54.8235C133.526 56.2627 135.433 56.9825 137.715 56.9825C139.606 56.9825 141.188 56.5572 142.459 55.7067C143.763 54.8235 144.709 53.6785 145.296 52.272H149.551C148.801 54.6272 147.382 56.6227 145.296 58.2582C143.242 59.8937 140.715 60.7118 137.715 60.7118C135.368 60.7118 133.216 60.1555 131.26 59.0432C129.336 57.8985 127.804 56.3445 126.663 54.3817C125.554 52.419 125 50.2437 125 47.8557C125 45.4677 125.554 43.2925 126.663 41.3298C127.804 39.367 129.336 37.8295 131.26 36.7173C133.216 35.5725 135.368 35 137.715 35C140.03 35 142.133 35.556 144.024 36.6682C145.915 37.7805 147.399 39.3342 148.475 41.3298C149.583 43.3252 150.138 45.5987 150.138 48.1502V49.1315ZM137.715 38.729C135.564 38.729 133.738 39.367 132.238 40.6427C130.771 41.9185 129.842 43.6195 129.45 45.7458H145.883C145.491 43.685 144.562 42.0002 143.095 40.6917C141.661 39.3832 139.867 38.729 137.715 38.729Z\" />\n <path d=\"M116.961 60.5353H112.559V30.4072H101.164V26.1875H128.307V30.4072H116.961V60.5353Z\" />\n </g>\n <defs>\n <clipPath id=\"clip0_796_283\">\n <rect width=\"270\" height=\"80\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n );\n }\n // Logo only\n const logoWidth = width || 80;\n const logoHeight = logoWidth; // Square logo maintains 1:1 aspect ratio\n\n return (\n <svg\n width={logoWidth}\n height={logoHeight}\n viewBox=\"0 0 80 80\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={fillClass}\n style={fillValue ? { fill: fillValue } : undefined}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M0.223654 20.2934C0.417233 19.8234 0.873598 19.517 1.37984 19.517H20.5909C21.282 19.517 21.8422 20.0798 21.8422 20.774V40.049C21.8422 40.5572 21.5375 41.0155 21.0702 41.2102C20.6028 41.405 20.0647 41.2977 19.7067 40.9385L0.495628 21.6635C0.137428 21.3041 0.030075 20.7633 0.223654 20.2934ZM4.40349 22.0311L19.3396 37.017V22.0311H4.40349Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 20.2934C38.8394 19.8234 39.2958 19.517 39.802 19.517H59.013C59.7041 19.517 60.2642 20.0798 60.2642 20.774V40.049C60.2642 40.5572 59.9597 41.0155 59.4923 41.2102C59.025 41.405 58.4867 41.2977 58.1289 40.9385L38.9178 21.6635C38.5595 21.3041 38.4522 20.7633 38.6458 20.2934ZM42.8255 22.0311L57.7618 37.017V22.0311H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M19.4347 58.8447C19.6283 58.3747 20.0847 58.0685 20.5909 58.0685H39.802C40.493 58.0685 41.0532 58.6312 41.0532 59.3255V78.6005C41.0532 79.1087 40.7486 79.567 40.2813 79.7617C39.8139 79.9562 39.2757 79.849 38.9178 79.49L19.7067 60.215C19.3485 59.8555 19.2411 59.3147 19.4347 58.8447ZM23.6146 60.5825L38.5508 75.5682V60.5825H23.6146Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 58.1643C39.79 57.9695 40.3283 58.0768 40.6861 58.436L59.8972 77.711C60.2555 78.0703 60.3628 78.6113 60.1692 79.081C59.9756 79.551 59.5192 79.8575 59.013 79.8575H39.802C39.1109 79.8575 38.5508 79.2948 38.5508 78.6005V59.3255C38.5508 58.8173 38.8554 58.359 39.3227 58.1643ZM41.0532 62.3575V77.3433H55.9893L41.0532 62.3575Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 19.6129C39.79 19.4182 40.3283 19.5254 40.6861 19.8846L59.8972 39.1595C60.2555 39.519 60.3628 40.0598 60.1692 40.5298C59.9756 40.9995 59.5192 41.306 59.013 41.306H39.802C39.1109 41.306 38.5508 40.7433 38.5508 40.049V20.7741C38.5508 20.2658 38.8554 19.8075 39.3227 19.6129ZM41.0532 23.8061V38.792H55.9893L41.0532 23.8061Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 38.8885C39.79 38.694 40.3283 38.8012 40.6861 39.1602L59.8972 58.4352C60.2555 58.7945 60.3628 59.3355 60.1692 59.8055C59.9756 60.2752 59.5192 60.5817 59.013 60.5817H39.802C39.1109 60.5817 38.5508 60.019 38.5508 59.3247V40.0497C38.5508 39.5415 38.8554 39.0832 39.3227 38.8885ZM41.0532 43.0817V58.0675H55.9893L41.0532 43.0817Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 39.569C38.8394 39.0992 39.2958 38.7927 39.802 38.7927H59.013C59.7041 38.7927 60.2642 39.3555 60.2642 40.0497V59.3247C60.2642 59.833 59.9597 60.2912 59.4923 60.486C59.025 60.6805 58.4867 60.5732 58.1289 60.2142L38.9178 40.9392C38.5595 40.5797 38.4522 40.039 38.6458 39.569ZM42.8255 41.3067L57.7618 56.2927V41.3067H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 58.8447C38.8394 58.3747 39.2958 58.0685 39.802 58.0685H59.013C59.7041 58.0685 60.2642 58.6312 60.2642 59.3255V78.6005C60.2642 79.1087 59.9597 79.567 59.4923 79.7617C59.025 79.9562 58.4867 79.849 58.1289 79.49L38.9178 60.215C38.5595 59.8555 38.4522 59.3147 38.6458 58.8447ZM42.8255 60.5825L57.7618 75.5682V60.5825H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M58.5338 19.6129C59.0011 19.4182 59.5394 19.5254 59.8972 19.8846L79.1083 39.1595C79.4666 39.519 79.5739 40.0598 79.3803 40.5298C79.1867 40.9995 78.7303 41.306 78.2241 41.306H59.013C58.322 41.306 57.7618 40.7433 57.7618 40.049V20.7741C57.7618 20.2658 58.0664 19.8075 58.5338 19.6129ZM60.2643 23.8061V38.792H75.2006L60.2643 23.8061Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M58.5338 0.338803C59.0011 0.144135 59.5394 0.251385 59.8972 0.610565L79.1083 19.8855C79.4666 20.2449 79.5739 20.7857 79.3803 21.2556C79.1867 21.7256 78.7303 22.032 78.2241 22.032H59.013C58.322 22.032 57.7618 21.4692 57.7618 20.775V1.50003C57.7618 0.99174 58.0664 0.533468 58.5338 0.338803ZM60.2643 4.53208V19.5179H75.2006L60.2643 4.53208Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M57.8569 20.2934C58.0505 19.8234 58.5069 19.517 59.013 19.517H78.2241C78.9151 19.517 79.4753 20.0798 79.4753 20.774V40.049C79.4753 40.5572 79.1707 41.0155 78.7034 41.2102C78.236 41.405 77.6978 41.2977 77.3399 40.9385L58.1289 21.6635C57.7705 21.3041 57.6633 20.7633 57.8569 20.2934ZM62.0365 22.0311L76.9729 37.017V22.0311H62.0365Z\"\n />\n </svg>\n );\n};\n","import * as React from \"react\";\nimport { Logo } from \"../Logo\";\n// Remove Icon import to avoid client-only code - using emoji/text placeholders for now\n// import { Icon, type IconName } from \"../Icon\";\n\nexport type SideNavItem = {\n id: string;\n label: string;\n href?: string; // Optional - if not provided and has children, becomes a category\n icon?: React.ReactNode;\n isActive?: boolean;\n isExpanded?: boolean; // For categories with children\n children?: SideNavItem[]; // If present, this becomes a category\n};\n\nexport type SideNavSection = {\n id: string;\n title?: string; // Optional section title\n items: SideNavItem[];\n};\n\nexport type SideNavProps = {\n topItems?: SideNavItem[] | SideNavSection[]; // Union type for backward compatibility\n bottomItems?: SideNavItem[];\n bottomContent?: React.ReactNode; // For app-specific content like WorkspaceSwitcher\n logo?: React.ReactNode;\n showLogo?: boolean;\n linkComponent?: React.ElementType;\n className?: string;\n mobileMenuId?: string;\n sidebarCollapseId?: string;\n};\n\n/**\n * SideNav\n *\n * Vertical navigation component for application sidebars.\n * Supports nested navigation items, sections, collapsible categories, and mobile-responsive behavior.\n */\nexport const SideNav: React.FC<SideNavProps> = ({\n topItems = [],\n bottomItems = [],\n bottomContent,\n logo,\n showLogo = true,\n linkComponent: LinkComponent = \"a\",\n className = \"\",\n mobileMenuId = \"app-mobile-menu\",\n sidebarCollapseId = \"app-sidebar-collapse\",\n}) => {\n // Helper function to determine if topItems is using the new section format\n const isSectionFormat = (items: SideNavItem[] | SideNavSection[]): items is SideNavSection[] => {\n return items.length > 0 && \"items\" in items[0];\n };\n\n // Helper function to normalize topItems to sections for consistent rendering\n const normalizeToSections = (items: SideNavItem[] | SideNavSection[]): SideNavSection[] => {\n if (isSectionFormat(items)) {\n return items;\n }\n // Convert plain items array to a single section\n return [{ id: \"default-section\", items: items }];\n };\n\n const renderSection = (\n section: SideNavSection,\n sectionIndex: number,\n totalSections: number\n ): React.ReactNode => {\n return (\n <div key={section.id} className=\"space-y-0.5\">\n {/* Optional section title */}\n {section.title && (\n <div\n className=\"px-6 py-1 text-xs font-medium text-text-subtle uppercase tracking-wider\"\n data-collapse-hide=\"\"\n >\n {section.title}\n </div>\n )}\n\n {/* Section items */}\n <div className=\"space-y-0.5\">{section.items.map((item) => renderNavItem(item))}</div>\n\n {/* Section separator - border between sections (but not after the last section) */}\n {sectionIndex < totalSections - 1 && (\n <div className=\"border-b border-border-subtle mx-6 my-2\" data-collapse-hide=\"\" />\n )}\n </div>\n );\n };\n\n const renderNavItem = (item: SideNavItem, isNested = false): React.ReactNode => {\n // If item has children, render as category\n if (item.children && item.children.length > 0) {\n const categoryId = `category-${item.id}`;\n return (\n <div key={item.id} className=\"group/category\">\n {/* Hidden checkbox for expand/collapse state */}\n <input\n type=\"checkbox\"\n id={categoryId}\n className=\"peer/category hidden\"\n defaultChecked={item.isExpanded}\n aria-hidden=\"true\"\n />\n\n {/* Category header - acts as label for checkbox */}\n <label\n htmlFor={categoryId}\n className=\"flex items-center gap-3 px-6 py-1 text-text-body hover:bg-background-hover hover:text-text-heading cursor-pointer transition-all duration-200\"\n data-collapse-center=\"\"\n >\n {item.icon && (\n <span\n className=\"flex-shrink-0 w-3.5 h-3.5 flex items-center justify-center transition-all duration-200\"\n data-collapse-icon=\"\"\n >\n {item.icon}\n </span>\n )}\n <span className=\"transition-all duration-200\" data-collapse-hide=\"\">\n {item.label}\n </span>\n {/* Spacer to push chevron to the right */}\n <span className=\"flex-1\" data-collapse-hide=\"\" />\n {/* Chevron icon for expand/collapse */}\n <svg\n className=\"w-4 h-4 transform transition-transform duration-200 peer-checked/category:rotate-180 ml-auto\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-collapse-hide=\"\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </label>\n\n {/* Category children - hidden by default, shown when checkbox is checked */}\n <div\n className=\"hidden peer-checked/category:block bg-background-subtle border-l-2 border-border-subtle ml-6\"\n data-collapse-hide-category=\"\"\n >\n {item.children.map((child) => renderNavItem(child, true))}\n </div>\n </div>\n );\n }\n\n // Otherwise render as regular link\n const linkProps = {\n href: item.href || \"#\",\n className: `flex items-center gap-3 transition-all duration-200 hover:bg-background-hover ${\n isNested ? \"pl-8 pr-6 py-1 text-sm\" : \"px-6 py-1\"\n } ${\n item.isActive\n ? `bg-action-brand/10 text-action-brand ${!isNested ? \"border-l-2 border-action-brand\" : \"\"}`\n : \"text-text-body hover:text-text-heading\"\n }`,\n \"aria-current\": item.isActive ? (\"page\" as const) : undefined,\n \"data-collapse-center\": !isNested ? \"\" : undefined,\n };\n\n const linkContent = (\n <>\n {item.icon && !isNested && (\n <span\n className=\"flex-shrink-0 w-3.5 h-3.5 flex items-center justify-center transition-all duration-200\"\n data-collapse-icon=\"\"\n >\n {item.icon}\n </span>\n )}\n <span className=\"transition-all duration-200\" data-collapse-hide=\"\">\n {item.label}\n </span>\n </>\n );\n\n if (LinkComponent === \"a\") {\n return (\n <a key={item.id} {...linkProps}>\n {linkContent}\n </a>\n );\n }\n\n return (\n <LinkComponent key={item.id} {...linkProps}>\n {linkContent}\n </LinkComponent>\n );\n };\n\n return (\n <div className={`flex flex-col h-full ${className}`}>\n {/* Header with logo and collapse button */}\n <div className=\"flex items-center justify-between h-[60px] px-6 border-b border-border-default\">\n {showLogo && (\n <div className=\"relative top-[-2px] transition-all duration-200\" data-collapse-hide=\"\">\n {logo ? (\n // If custom logo is provided, use it\n logo\n ) : (\n // Otherwise use the default Logo component\n <Logo showWordmark={true} width={120} />\n )}\n </div>\n )}\n\n {/* Desktop collapse toggle */}\n <label\n htmlFor={sidebarCollapseId}\n className=\"hidden md:flex items-center justify-center w-8 h-8 rounded hover:bg-background-hover cursor-pointer transition-all duration-200\"\n aria-label=\"Toggle sidebar\"\n data-collapse-toggle=\"\"\n >\n {/* Menu icon */}\n <svg\n className=\"w-5 h-5\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 12h16M4 18h16\"\n />\n </svg>\n </label>\n\n {/* Mobile close button */}\n <label\n htmlFor={mobileMenuId}\n className=\"md:hidden flex items-center justify-center w-8 h-8 rounded hover:bg-background-hover cursor-pointer transition-colors\"\n aria-label=\"Close menu\"\n >\n {/* Close icon */}\n <svg\n className=\"w-5 h-5\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </label>\n </div>\n\n {/* Navigation sections */}\n <nav className=\"flex-1 flex flex-col overflow-hidden\">\n {/* Top section - scrollable */}\n {topItems && topItems.length > 0 && (\n <div className=\"flex-1 overflow-y-auto py-2 scrollbar-hide\">\n {normalizeToSections(topItems).map((section, index, sections) =>\n renderSection(section, index, sections.length)\n )}\n </div>\n )}\n\n {/* Bottom section - fixed at bottom with enhanced separator */}\n {bottomItems && bottomItems.length > 0 && (\n <div className=\"flex-shrink-0 border-t bg-background-muted/30\">\n {/* Bottom navigation items with background and proper spacing */}\n <div className=\"mt-2 pb-2 space-y-0.5\">\n {bottomItems.map((item) => renderNavItem(item))}\n </div>\n </div>\n )}\n\n {/* Bottom content - for app-specific components like WorkspaceSwitcher */}\n {bottomContent && (\n <div className=\"flex-shrink-0 border-t border-border-default\">\n <div data-collapse-hide=\"\">{bottomContent}</div>\n </div>\n )}\n </nav>\n </div>\n );\n};\n","import type { IconProps as PhosphorIconProps } from \"@phosphor-icons/react\";\n// Import SSR-compatible icons\nimport * as PhosphorIconsSSR from \"@phosphor-icons/react/dist/ssr\";\nimport React, { memo } from \"react\";\nimport { twMerge } from \"tailwind-merge\";\n\n// Type for any Phosphor icon component\ntype PhosphorIconComponent = React.ComponentType<PhosphorIconProps>;\n\n// Extract all icon names from the Phosphor package\nexport type PhosphorIconName = string;\n\n// For backwards compatibility, export IconName as an alias\nexport type IconName = PhosphorIconName;\n\n// Standard size presets for the design system\nconst sizePresets = {\n xs: 16,\n sm: 20,\n md: 24,\n lg: 32,\n xl: 40,\n \"2xl\": 48,\n} as const;\n\ntype SizePreset = keyof typeof sizePresets;\n\ninterface IconSSRProps extends Omit<PhosphorIconProps, \"size\"> {\n /**\n * The name of the Phosphor icon to render\n * Any valid icon from @phosphor-icons/react\n */\n name: PhosphorIconName;\n\n /**\n * Size of the icon - can be a preset or custom number\n */\n size?: SizePreset | number;\n\n /**\n * Accessibility label (maps to aria-label)\n */\n ariaLabel?: string;\n}\n\n/**\n * IconSSR\n *\n * SSR-compatible Phosphor icon wrapper component with standardized sizing and styling.\n * Uses the SSR-compatible version of phosphor-icons for server-side rendering.\n * - TypeScript autocomplete for all icon names\n * - SSR-compatible: Uses SSR-optimized icons (no Context API dependency)\n * - Tree-shaking: Only icons you use are included in the bundle\n *\n * Usage:\n * ```tsx\n * <IconSSR name=\"House\" size=\"md\" />\n * <IconSSR name=\"User\" size={32} className=\"text-brand\" />\n * ```\n */\nexport const IconSSR = memo(\n ({\n name,\n size = \"md\",\n color,\n weight = \"regular\",\n className,\n ariaLabel,\n ...props\n }: IconSSRProps) => {\n // Get the icon component from the SSR Phosphor package\n const IconComponent = (PhosphorIconsSSR as unknown as Record<string, PhosphorIconComponent>)[\n name\n ];\n\n if (!IconComponent) {\n // Icon not found - return null silently in production\n return null;\n }\n\n // Resolve size to pixel value\n const resolvedSize: number =\n typeof size === \"string\"\n ? size in sizePresets\n ? sizePresets[size as SizePreset]\n : sizePresets.md // Fallback to md if invalid preset\n : size;\n\n // Build className with design system defaults\n const iconClassName = twMerge(\n // Default styles\n \"inline-block flex-shrink-0\",\n // Allow color inheritance from parent\n !color && \"text-current\",\n // Custom classes\n className\n );\n\n return (\n <IconComponent\n {...props}\n size={resolvedSize}\n color={color}\n weight={weight}\n className={iconClassName}\n aria-label={ariaLabel || `${name} icon`}\n data-testid={`icon-${name}`}\n />\n );\n }\n);\n\nIconSSR.displayName = \"IconSSR\";\n\n/**\n * Helper component for icons with containers (SSR version)\n */\ninterface IconSSRWithContainerProps extends IconSSRProps {\n /**\n * Container variant\n */\n variant?: \"subtle\" | \"solid\" | \"outline\";\n\n /**\n * Container shape\n */\n shape?: \"square\" | \"circle\";\n\n /**\n * Container size (adds padding around icon)\n */\n containerSize?: SizePreset | number;\n\n /**\n * Container background color\n */\n containerClassName?: string;\n}\n\nexport const IconSSRWithContainer = memo(\n ({\n variant = \"subtle\",\n shape = \"square\",\n containerSize,\n containerClassName,\n size = \"md\",\n className,\n name,\n color,\n weight,\n ariaLabel,\n ref,\n ...props\n }: IconSSRWithContainerProps & { ref?: React.Ref<HTMLDivElement> }) => {\n // Calculate container size if not specified\n const iconSize: number =\n typeof size === \"string\"\n ? size in sizePresets\n ? sizePresets[size as SizePreset]\n : sizePresets.md\n : size;\n\n const resolvedContainerSize: number = containerSize\n ? typeof containerSize === \"string\"\n ? containerSize in sizePresets\n ? sizePresets[containerSize as SizePreset]\n : iconSize * 1.75 // Fallback to default if invalid preset\n : containerSize\n : iconSize * 1.75;\n\n const containerClasses = twMerge(\n // Base styles\n \"inline-flex items-center justify-center flex-shrink-0\",\n\n // Shape\n shape === \"circle\" ? \"rounded-full\" : \"rounded-lg\",\n\n // Variant styles using Tailwind 4 CSS variables\n variant === \"subtle\" && \"bg-gray-100 dark:bg-gray-800\",\n variant === \"solid\" && \"bg-brand text-white\",\n variant === \"outline\" && \"border-2 border-current\",\n\n // Container className for overrides\n containerClassName\n );\n\n return (\n <div\n className={containerClasses}\n style={{\n width: resolvedContainerSize,\n height: resolvedContainerSize,\n }}\n >\n <IconSSR\n {...props}\n name={name}\n size={size}\n color={color}\n weight={weight}\n className={className}\n ariaLabel={ariaLabel}\n />\n </div>\n );\n }\n);\n\nIconSSRWithContainer.displayName = \"IconSSRWithContainer\";\n","import * as React from \"react\";\nimport { IconSSR } from \"../Icon/IconSSR\";\n\nexport type ColorMode = \"system\" | \"light\" | \"dark\";\n\nexport type TopNavProps = {\n /**\n * Content for the right side (avatar, actions, etc.)\n * @deprecated Use centerContent and actions instead for better layout control\n */\n rightContent?: React.ReactNode;\n /**\n * Content for the center area (typically search)\n * On mobile, this moves to rightContent position\n */\n centerContent?: React.ReactNode;\n showMobileMenu?: boolean;\n avatar?: React.ReactNode;\n showColorModeSwitcher?: boolean;\n toggleTheme?: () => void;\n isDarkThemeEnabled?: boolean;\n colorMode?: ColorMode;\n actions?: React.ReactNode;\n className?: string;\n mobileMenuId?: string;\n};\n\n/**\n * TopNav\n *\n * Horizontal navigation bar component for application headers.\n * Includes mobile menu toggle, user avatar, theme switcher, and customizable action areas.\n */\nexport const TopNav: React.FC<TopNavProps> = ({\n rightContent,\n centerContent,\n showMobileMenu = true,\n avatar,\n showColorModeSwitcher = false,\n toggleTheme,\n isDarkThemeEnabled = false,\n colorMode,\n actions,\n className = \"\",\n mobileMenuId = \"app-mobile-menu\",\n}) => {\n const getThemeIcon = () => {\n const effectiveMode = colorMode || (isDarkThemeEnabled ? \"dark\" : \"light\");\n\n switch (effectiveMode) {\n case \"system\":\n return <IconSSR name=\"Monitor\" size=\"sm\" />;\n case \"light\":\n return <IconSSR name=\"Sun\" size=\"sm\" />;\n case \"dark\":\n return <IconSSR name=\"Moon\" size=\"sm\" />;\n }\n };\n\n const getAriaLabel = () => {\n const effectiveMode = colorMode || (isDarkThemeEnabled ? \"dark\" : \"light\");\n\n switch (effectiveMode) {\n case \"system\":\n return \"Switch to light mode\";\n case \"light\":\n return \"Switch to dark mode\";\n case \"dark\":\n return \"Switch to system mode\";\n default:\n return \"Toggle theme\";\n }\n };\n return (\n <header className={`h-[60px] bg-background-surface border-b ${className}`}>\n <div className=\"relative flex h-full items-center\">\n {/* Left side - Mobile menu button */}\n <div className=\"flex items-center h-full flex-shrink-0\">\n {showMobileMenu && (\n <label\n htmlFor={mobileMenuId}\n className=\"md:hidden cursor-pointer\"\n aria-label=\"Open menu\"\n >\n <div className=\"flex h-full w-14 flex-col items-center justify-center border-r hover:bg-background-hover transition-colors\">\n <IconSSR name=\"List\" size=\"sm\" />\n </div>\n </label>\n )}\n </div>\n\n {/* Spacer for desktop */}\n <div className=\"hidden md:block flex-1\" />\n\n {/* Center content - ONE instance, positioned differently on mobile vs desktop */}\n {centerContent && (\n <div className=\"w-full md:absolute md:left-1/2 md:-translate-x-1/2 md:max-w-4xl md:px-4 flex justify-end md:justify-center\">\n {centerContent}\n </div>\n )}\n\n {/* Right side - User actions */}\n <div className=\"flex items-center gap-4 pr-4 flex-shrink-0\">\n {/* Legacy right content (deprecated) */}\n {rightContent}\n\n {/* Theme switcher */}\n {showColorModeSwitcher && toggleTheme && (\n <button\n type=\"button\"\n onClick={toggleTheme}\n className=\"flex items-center justify-center w-8 h-8 rounded hover:bg-background-hover transition-colors\"\n aria-label={getAriaLabel()}\n >\n {getThemeIcon()}\n </button>\n )}\n\n {/* Additional actions */}\n {actions}\n\n {/* Avatar */}\n {avatar && <div className=\"flex items-center\">{avatar}</div>}\n </div>\n </div>\n </header>\n );\n};\n","import React from \"react\";\nimport { SideNav, type SideNavProps } from \"../SideNav/SideNav\";\nimport { TopNav, type TopNavProps } from \"../TopNav/TopNav\";\n\n/** Layout options for the AppShell */\nexport type AppShellProps = {\n /** Structured nav for the left rail */\n sideNav: Omit<SideNavProps, \"mobileMenuId\" | \"sidebarCollapseId\">;\n /** Optional top bar slots & options */\n topNav?: Pick<\n TopNavProps,\n | \"rightContent\"\n | \"showMobileMenu\"\n | \"avatar\"\n | \"showColorModeSwitcher\"\n | \"toggleTheme\"\n | \"isDarkThemeEnabled\"\n | \"colorMode\"\n | \"actions\"\n | \"className\"\n >;\n /** Main page content */\n children: React.ReactNode;\n\n /** Layout knobs */\n contentPaddingX?: string; // e.g. \"px-4 md:px-6\"\n contentPaddingY?: string; // e.g. \"py-4 md:py-6\"\n showSidebarBorder?: boolean; // default true\n mainClassName?: string; // extra classes on <main>\n\n /** Optional: Enable JavaScript progressive enhancements */\n enableJsEnhancements?: boolean;\n};\n\n/**\n * Isomorphic AppShell component that works as both server and client component\n * Uses CSS-only interactions by default for full SSR compatibility\n * Can be progressively enhanced with JavaScript when enableJsEnhancements is true\n */\nexport function AppShell({\n sideNav,\n topNav,\n children,\n contentPaddingX,\n contentPaddingY,\n showSidebarBorder = true,\n mainClassName,\n enableJsEnhancements = false,\n}: AppShellProps) {\n // Use stable IDs for CSS selectors\n const mobileMenuId = \"app-mobile-menu\";\n const sidebarCollapseId = \"app-sidebar-collapse\";\n\n return (\n <div className=\"min-h-[100dvh] bg-background text-text-body relative\">\n {/* Hidden checkbox for desktop sidebar collapse */}\n <input\n type=\"checkbox\"\n id={sidebarCollapseId}\n className=\"sr-only peer/sidebar\"\n aria-hidden=\"true\"\n />\n\n {/* Skip link for keyboard users */}\n <a\n href=\"#app-content\"\n className=\"sr-only focus:not-sr-only focus:absolute focus:left-4 focus:top-4 z-50 rounded px-3 py-2 bg-background-surface shadow\"\n >\n Skip to content\n </a>\n\n {/* Top navigation - always visible on mobile */}\n <TopNav\n {...topNav}\n mobileMenuId={mobileMenuId}\n className={[\"sticky top-0 flex-shrink-0 z-30 md:hidden\", topNav?.className]\n .filter(Boolean)\n .join(\" \")}\n />\n\n {/* Main layout container - contains sidebar and content */}\n <div className=\"flex w-full h-[calc(100dvh-60px)] md:h-[100dvh] relative overflow-hidden\">\n {/* Hidden checkbox for mobile menu - inside container for peer selectors */}\n <input\n type=\"checkbox\"\n id={mobileMenuId}\n className=\"sr-only peer/mobile\"\n aria-hidden=\"true\"\n />\n\n {/* Mobile menu overlay - fixed to cover entire viewport including TopNav */}\n <label\n htmlFor={mobileMenuId}\n className=\"fixed inset-0 bg-black/50 z-40 opacity-0 pointer-events-none peer-checked/mobile:opacity-100 peer-checked/mobile:pointer-events-auto transition-opacity md:hidden\"\n aria-label=\"Close menu\"\n />\n\n {/* Left rail - SideNav with CSS-based responsive behavior */}\n <aside\n id=\"app-sidebar\"\n className={[\n // Base styles\n \"bg-background-surface\",\n \"border-r border-border-default\",\n \"transition-all duration-300 ease-in-out\",\n // Mobile: fixed full-screen overlay\n \"fixed md:relative\",\n \"left-0 top-0 bottom-0\",\n \"z-50\",\n \"w-80 md:w-64\",\n \"h-[100dvh] md:h-full\",\n \"-translate-x-full\",\n \"peer-checked/mobile:translate-x-0\",\n // Desktop: always visible\n \"md:translate-x-0\",\n showSidebarBorder ? \"\" : \"!border-r-0\",\n sideNav?.className || \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n <SideNav\n {...sideNav}\n mobileMenuId={mobileMenuId}\n sidebarCollapseId={sidebarCollapseId}\n className=\"h-full\"\n />\n </aside>\n\n {/* Right side: TopNav + Main content */}\n <div className=\"flex-1 flex flex-col h-full overflow-hidden\">\n {/* Top navigation - desktop only */}\n <div className=\"sticky top-0 flex-shrink-0 hidden md:block z-20\">\n <TopNav {...topNav} className={topNav?.className} />\n </div>\n\n {/* Main content - scrollable */}\n <main\n id=\"app-content\"\n className={[\n \"flex-1 overflow-y-auto overflow-x-hidden bg-background-body\",\n contentPaddingX,\n contentPaddingY,\n mainClassName || \"\",\n ].join(\" \")}\n role=\"main\"\n >\n {children}\n </main>\n </div>\n </div>\n\n {/* Minimal CSS for checkbox-based interactions */}\n <style\n dangerouslySetInnerHTML={{\n __html: `\n @media (min-width: 768px) {\n /* Collapse sidebar width */\n #${sidebarCollapseId}:checked ~ * #app-sidebar {\n width: 4rem !important;\n }\n \n /* Collapse sidebar text */\n #${sidebarCollapseId}:checked ~ * [data-collapse-hide] {\n display: none !important;\n }\n \n /* Center nav items */\n #${sidebarCollapseId}:checked ~ * [data-collapse-center] {\n justify-content: center;\n padding-left: 0;\n padding-right: 0;\n gap: 0;\n }\n \n /* Adjust icon size when collapsed */\n #${sidebarCollapseId}:checked ~ * [data-collapse-icon] {\n width: 1.25rem !important;\n height: 1.25rem !important;\n }\n \n /* Scale SVG icons inside the icon container */\n #${sidebarCollapseId}:checked ~ * [data-collapse-icon] > svg {\n width: 1.25rem !important;\n height: 1.25rem !important;\n }\n \n /* Rotate toggle icon */\n #${sidebarCollapseId}:checked ~ * [data-collapse-toggle] {\n transform: scaleX(-1);\n }\n \n /* Hide category expansions */\n #${sidebarCollapseId}:checked ~ * [data-collapse-hide-category] {\n display: none;\n }\n }\n `,\n }}\n />\n\n {/* Optional: Progressive enhancement script */}\n {enableJsEnhancements && (\n <script\n dangerouslySetInnerHTML={{\n __html: `\n (function() {\n // Close mobile menu on Escape key\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape') {\n var menuToggle = document.getElementById('${mobileMenuId}');\n if (menuToggle) menuToggle.checked = false;\n }\n });\n \n // Save sidebar collapse preference to localStorage\n var sidebarToggle = document.getElementById('${sidebarCollapseId}');\n if (sidebarToggle) {\n // Restore from localStorage\n var saved = localStorage.getItem('sidebar-collapsed');\n if (saved !== null) {\n sidebarToggle.checked = saved === 'true';\n }\n \n // Save on change\n sidebarToggle.addEventListener('change', function() {\n localStorage.setItem('sidebar-collapsed', this.checked);\n });\n }\n \n // Prevent body scroll when mobile menu is open\n var mobileToggle = document.getElementById('${mobileMenuId}');\n if (mobileToggle) {\n mobileToggle.addEventListener('change', function() {\n document.body.style.overflow = this.checked ? 'hidden' : '';\n });\n }\n \n // Close mobile menu when clicking navigation links\n var sidebar = document.getElementById('app-sidebar');\n if (sidebar && mobileToggle) {\n sidebar.addEventListener('click', function(e) {\n // Check if click target is a link (or inside a link)\n var link = e.target.closest('a');\n if (link && link.href && window.innerWidth < 768) {\n // Small delay to allow navigation to start\n setTimeout(function() {\n mobileToggle.checked = false;\n document.body.style.overflow = '';\n }, 100);\n }\n });\n }\n })();\n `,\n }}\n />\n )}\n </div>\n );\n}\n","import { Building2, User, Users } from \"lucide-react\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport interface AvatarProps {\n /**\n * URL of the avatar image\n */\n src?: string;\n /**\n * Alternative text for the image\n */\n alt?: string;\n /**\n * First name for generating initials\n */\n firstName?: string;\n /**\n * Last name for generating initials\n */\n lastName?: string;\n /**\n * Full name (used as fallback for alt text)\n */\n fullName?: string;\n /**\n * Click handler\n */\n onClick?: () => void;\n /**\n * Size of the avatar\n * @default \"md\"\n */\n size?: \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n /**\n * Shape of the avatar\n * @default \"circle\"\n */\n shape?: \"circle\" | \"square\";\n /**\n * Visual variant\n * @default \"user\"\n */\n variant?: \"user\" | \"team\" | \"organization\";\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * Status indicator\n */\n status?: \"online\" | \"offline\" | \"away\" | \"busy\";\n /**\n * Whether to show a border\n * @default false\n */\n bordered?: boolean;\n}\n\n/**\n * Avatar\n *\n * Display user, team, or organization avatars with support for images,\n * initials, and fallback icons. Includes optional status indicators.\n */\nexport function Avatar({\n src,\n alt,\n firstName,\n lastName,\n fullName,\n onClick,\n size = \"md\",\n shape = \"circle\",\n variant = \"user\",\n className,\n status,\n bordered = false,\n}: AvatarProps) {\n const sizeClasses = {\n xs: \"h-6 w-6 text-xs\",\n sm: \"h-8 w-8 text-sm\",\n md: \"h-10 w-10 text-base\",\n lg: \"h-12 w-12 text-lg\",\n xl: \"h-16 w-16 text-xl\",\n };\n\n const statusSizeClasses = {\n xs: \"h-1.5 w-1.5\",\n sm: \"h-2 w-2\",\n md: \"h-2.5 w-2.5\",\n lg: \"h-3 w-3\",\n xl: \"h-4 w-4\",\n };\n\n const statusPositionClasses = {\n xs: \"bottom-0 right-0\",\n sm: \"bottom-0 right-0\",\n md: \"bottom-0 right-0\",\n lg: \"bottom-0.5 right-0.5\",\n xl: \"bottom-1 right-1\",\n };\n\n const statusColors = {\n online: \"bg-feedback-success-background border-feedback-success-border\",\n offline: \"bg-text-muted border-border-muted\",\n away: \"bg-feedback-warning-background border-feedback-warning-border\",\n busy: \"bg-feedback-error-background border-feedback-error-border\",\n };\n\n const variantColors = {\n user: \"bg-feedback-info-background text-feedback-info-text\",\n team: \"bg-feedback-info-background text-feedback-info-text\",\n organization: \"bg-feedback-success-background text-feedback-success-text\",\n };\n\n const shapeClasses = shape === \"circle\" ? \"rounded-full\" : \"rounded-md\";\n\n const baseClasses = twMerge(\n \"relative inline-flex items-center justify-center overflow-hidden transition-opacity outline-none\",\n sizeClasses[size],\n shapeClasses,\n onClick && \"cursor-pointer hover:opacity-80\",\n bordered && \"ring-2 ring-background-surface\",\n className\n );\n\n // Generate initials from name\n const getInitials = () => {\n if (firstName || lastName) {\n const first = firstName?.[0] || \"\";\n const last = lastName?.[0] || \"\";\n return (first + last).toUpperCase();\n }\n if (fullName) {\n const parts = fullName.split(\" \");\n const first = parts[0]?.[0] || \"\";\n const last = parts[parts.length - 1]?.[0] || \"\";\n return first === last ? first.toUpperCase() : (first + last).toUpperCase();\n }\n return \"\";\n };\n\n const initials = getInitials();\n\n // Get the appropriate icon for the variant\n const getIcon = () => {\n const iconSize = {\n xs: 14,\n sm: 16,\n md: 20,\n lg: 24,\n xl: 32,\n }[size];\n\n switch (variant) {\n case \"team\":\n return <Users size={iconSize} />;\n case \"organization\":\n return <Building2 size={iconSize} />;\n default:\n return <User size={iconSize} />;\n }\n };\n\n const renderAvatar = () => {\n // If src is provided, render image with CSS fallback\n if (src) {\n return (\n <>\n <img\n src={src}\n alt={alt || fullName || \"Avatar\"}\n className=\"h-full w-full object-cover\"\n // Use CSS to hide broken images\n style={{\n // This will hide the broken image icon\n fontSize: 0,\n }}\n />\n {/* Render fallback behind the image - will show if image fails */}\n <div className=\"absolute inset-0 flex items-center justify-center -z-10\">\n {initials ? <span className=\"font-semibold\">{initials}</span> : getIcon()}\n </div>\n </>\n );\n }\n\n // Show initials if available\n if (initials) {\n return <span className=\"font-semibold\">{initials}</span>;\n }\n\n // Show icon as fallback\n return getIcon();\n };\n\n return (\n <div className=\"relative inline-block\">\n <div\n data-avatar\n className={twMerge(baseClasses, !src ? variantColors[variant] : \"\")}\n onClick={onClick}\n role={onClick ? \"button\" : undefined}\n tabIndex={onClick ? 0 : undefined}\n >\n {renderAvatar()}\n </div>\n {status && (\n <span\n className={twMerge(\n \"absolute border-2 border-background-surface\",\n shapeClasses,\n statusSizeClasses[size],\n statusPositionClasses[size],\n statusColors[status]\n )}\n aria-label={`Status: ${status}`}\n />\n )}\n </div>\n );\n}\n","import React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\n\nconst sizeVariants = {\n xs: \"text-lg font-semibold\",\n sm: \"text-xl font-semibold\",\n md: \"text-2xl font-semibold\",\n lg: \"text-3xl font-semibold\",\n xl: \"text-4xl font-semibold\",\n} as const;\n\nconst heightVariants = {\n page: \"h-16 leading-[62px]\",\n} as const;\n\nexport type HeadingSize = keyof typeof sizeVariants;\nexport type HeadingHeight = keyof typeof heightVariants;\n\n/**\n * Heading\n *\n * Typography component for page/section headings with size and height options.\n */\nexport interface HeadingProps {\n tag?: React.ElementType;\n size?: HeadingSize;\n height?: HeadingHeight;\n className?: string;\n children?: React.ReactNode;\n}\n\nexport function Heading({\n tag: Tag = \"h1\",\n size = \"lg\",\n height,\n className = \"\",\n children,\n}: HeadingProps) {\n const sizeClasses = sizeVariants[size];\n const heightClasses = height ? heightVariants[height] : \"\";\n\n return <Tag className={twMerge(sizeClasses, heightClasses, className)}>{children}</Tag>;\n}\n","import { twMerge } from \"tailwind-merge\";\n\nexport interface LoaderProps {\n /**\n * Optional className for custom styling\n */\n className?: string;\n /**\n * Size of the loader in pixels\n * @default 24\n */\n size?: number;\n /**\n * Color of the loader\n * @default \"text-action-brand\"\n */\n color?: string;\n}\n\n/**\n * Loader\n *\n * Animated loading spinner component.\n * Displays a circular spinner with customizable size and color for loading states.\n */\nexport const Loader = ({ className, size = 24, color = \"text-action-brand\" }: LoaderProps) => {\n return (\n <div\n className={twMerge(\n \"inline-block animate-spin rounded-full border-2 border-solid border-current border-r-transparent\",\n color,\n className\n )}\n style={{\n width: size,\n height: size,\n }}\n role=\"status\"\n aria-label=\"loading\"\n >\n <span className=\"sr-only\">Loading...</span>\n </div>\n );\n};\n","import { ReactNode } from \"react\";\n\nexport interface TextLinkProps {\n href?: string;\n children: ReactNode;\n className?: string;\n external?: boolean;\n title?: string;\n variant?: \"default\" | \"brand\" | \"muted\" | \"unstyled\";\n onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;\n asButton?: boolean;\n onPress?: () => void;\n showArrow?: boolean;\n}\n\n/**\n * TextLink\n *\n * Styled text link component for navigation and actions.\n * Supports internal/external links, button mode, and multiple visual variants.\n */\nexport const TextLink = ({\n href,\n children,\n className = \"\",\n external = false,\n title,\n variant = \"default\",\n onClick,\n asButton = false,\n onPress,\n showArrow = false,\n}: TextLinkProps) => {\n const externalProps = external ? { target: \"_blank\", rel: \"noopener noreferrer\" } : {};\n\n const baseClasses =\n \"hover:underline hover:decoration-1 hover:underline-offset-4 hover:decoration-current cursor-pointer\";\n\n const variantClasses = {\n default: \"text-action-primary hover:text-action-primary-hover visited:text-action-primary\",\n brand: \"text-action-brand hover:text-action-brand-hover visited:text-action-brand\",\n muted: \"text-text-muted hover:text-text-muted visited:text-text-muted\",\n unstyled: \"\", // No color styling, inherits from children\n };\n\n const combinedClasses = `${baseClasses} ${variantClasses[variant]} ${className}`;\n\n const content = (\n <>\n {children}\n {showArrow && <span>{\"\\u00A0\"}→</span>}\n </>\n );\n\n if (asButton) {\n return (\n <button type=\"button\" className={combinedClasses} onClick={onPress} title={title}>\n {content}\n </button>\n );\n }\n\n return (\n <a\n href={href || \"#\"}\n className={combinedClasses}\n {...externalProps}\n title={title}\n onClick={onClick}\n >\n {content}\n </a>\n );\n};\n\nexport default TextLink;\n","/**\n * Entity Configuration\n *\n * Centralized configuration for all platform entities including\n * display properties, icons, colors, and labels.\n *\n * Use this for consistent entity representation across the application:\n * - Navigation\n * - Page headers\n * - Breadcrumbs\n * - Empty states\n * - Related entity links\n *\n * @example\n * ```tsx\n * import { ENTITY_CONFIG } from \"@texturehq/edges/config/entities\";\n *\n * const siteConfig = ENTITY_CONFIG.site;\n * // { icon: \"Buildings\", label: { singular: \"Site\", plural: \"Sites\" }, ... }\n * ```\n */\n\nimport type { IconName } from \"../components/Icon\";\n\nexport interface EntityConfig {\n /** Phosphor icon name */\n icon: IconName;\n /** Display labels */\n label: {\n singular: string;\n plural: string;\n };\n /** Optional description */\n description?: string;\n}\n\nexport const ENTITY_CONFIG = {\n app: {\n icon: \"AppWindow\",\n label: {\n singular: \"App\",\n plural: \"Apps\",\n },\n description: \"Workspace and integration apps\",\n },\n site: {\n icon: \"MapPin\",\n label: {\n singular: \"Site\",\n plural: \"Sites\",\n },\n description: \"Physical locations with energy systems\",\n },\n device: {\n icon: \"ShareNetwork\",\n label: {\n singular: \"Device\",\n plural: \"Devices\",\n },\n description: \"Connected energy devices\",\n },\n customer: {\n icon: \"Users\",\n label: {\n singular: \"Customer\",\n plural: \"Customers\",\n },\n description: \"End customers and site owners\",\n },\n contact: {\n icon: \"Users\",\n label: {\n singular: \"Contact\",\n plural: \"Contacts\",\n },\n description: \"Contact persons\",\n },\n program: {\n icon: \"ClipboardText\",\n label: {\n singular: \"Program\",\n plural: \"Programs\",\n },\n description: \"Demand response and VPP programs\",\n },\n workflow: {\n icon: \"FlowArrow\",\n label: {\n singular: \"Workflow\",\n plural: \"Workflows\",\n },\n description: \"Automated workflows and rules\",\n },\n collection: {\n icon: \"Stack\",\n label: {\n singular: \"Collection\",\n plural: \"Collections\",\n },\n description: \"Grouped entities\",\n },\n board: {\n icon: \"SquaresFour\",\n label: {\n singular: \"Board\",\n plural: \"Boards\",\n },\n description: \"Dashboard and monitoring boards\",\n },\n report: {\n icon: \"ChartLine\",\n label: {\n singular: \"Report\",\n plural: \"Reports\",\n },\n description: \"Analytics and reports\",\n },\n event: {\n icon: \"ClockCounterClockwise\",\n label: {\n singular: \"Event\",\n plural: \"Events\",\n },\n description: \"System events and activity\",\n },\n alert: {\n icon: \"Warning\",\n label: {\n singular: \"Alert\",\n plural: \"Alerts\",\n },\n description: \"Notifications and alerts\",\n },\n command: {\n icon: \"Play\",\n label: {\n singular: \"Command\",\n plural: \"Commands\",\n },\n description: \"Device commands and control\",\n },\n} as const satisfies Record<string, EntityConfig>;\n\nexport type EntityType = keyof typeof ENTITY_CONFIG;\n\n/**\n * Get entity configuration by type\n *\n * @param entityType - The entity type key\n * @returns Entity configuration object\n *\n * @example\n * ```tsx\n * const config = getEntityConfig(\"site\");\n * // { icon: \"Buildings\", label: { singular: \"Site\", plural: \"Sites\" }, ... }\n * ```\n */\nexport function getEntityConfig(entityType: EntityType): EntityConfig {\n return ENTITY_CONFIG[entityType];\n}\n\n/**\n * Get entity icon name\n *\n * @param entityType - The entity type key\n * @returns Phosphor icon name\n *\n * @example\n * ```tsx\n * const iconName = getEntityIcon(\"site\"); // \"Buildings\"\n * ```\n */\nexport function getEntityIcon(entityType: EntityType): IconName {\n return ENTITY_CONFIG[entityType].icon;\n}\n\n/**\n * Get entity label (singular or plural)\n *\n * @param entityType - The entity type key\n * @param plural - Whether to return plural form\n * @returns Entity label string\n *\n * @example\n * ```tsx\n * getEntityLabel(\"site\", false); // \"Site\"\n * getEntityLabel(\"site\", true); // \"Sites\"\n * ```\n */\nexport function getEntityLabel(entityType: EntityType, plural: boolean = false): string {\n return plural ? ENTITY_CONFIG[entityType].label.plural : ENTITY_CONFIG[entityType].label.singular;\n}\n","/**\n * Color utilities for the edges design system\n * Provides theme-aware color resolution and management\n */\n\n// Cache for resolved CSS variable colors\nconst colorCache = new Map<string, string>();\n\n/**\n * Type for Mapbox GL JS expressions\n * Represents nested array structures used by Mapbox for data-driven styling\n */\nexport type MapboxExpression =\n | string\n | number\n | boolean\n | Array<string | number | boolean | MapboxExpression>;\n\n/**\n * Resolves a CSS variable to its computed color value\n * Supports multiple formats and automatically adds the color- prefix if needed\n *\n * @param variableName - CSS variable name in any of these formats:\n * - \"brand-primary\" → resolves to --color-brand-primary\n * - \"color-brand-primary\" → resolves to --color-brand-primary\n * - \"--color-brand-primary\" → used as-is\n * - \"var(--color-brand-primary)\" → unwrapped and used\n * @returns Resolved color value or fallback\n */\nexport const getResolvedColor = (variableName: string, fallback = \"#000000\"): string => {\n // Early return if running in non-browser environment\n if (typeof window === \"undefined\") return fallback;\n\n // Normalize the variable name\n let varName = variableName.startsWith(\"var(\")\n ? variableName.slice(4, -1)\n : variableName.startsWith(\"--\")\n ? variableName\n : `--${variableName}`;\n\n // Add color- prefix ONLY for shorthand forms without the -- prefix\n // This allows \"brand-primary\" to resolve to \"--color-brand-primary\"\n // but preserves exact variable names like \"--text-body\" or \"--neutral-white\"\n if (\n !variableName.startsWith(\"--\") &&\n !variableName.startsWith(\"var(\") &&\n !varName.startsWith(\"--color-\")\n ) {\n varName = `--color-${varName.slice(2)}`;\n }\n\n // Return cached value if available\n if (colorCache.has(varName)) {\n return colorCache.get(varName)!;\n }\n\n try {\n // Get computed style from body element (where theme classes are applied)\n // This ensures we pick up theme-specific variables like .theme-dark\n const root = document.body || document.documentElement;\n const computedStyle = getComputedStyle(root);\n const value = computedStyle.getPropertyValue(varName).trim();\n\n if (value) {\n // Cache the result\n colorCache.set(varName, value);\n return value;\n }\n\n // Try alternative method with temporary element\n const tempElement = document.createElement(\"div\");\n tempElement.style.color = `var(${varName})`;\n document.body.appendChild(tempElement);\n const resolvedColor = getComputedStyle(tempElement).color;\n document.body.removeChild(tempElement);\n\n if (resolvedColor && resolvedColor !== \"rgb(0, 0, 0)\") {\n colorCache.set(varName, resolvedColor);\n return resolvedColor;\n }\n\n return fallback;\n } catch (error) {\n console.warn(`Failed to resolve color for ${variableName}:`, error);\n return fallback;\n }\n};\n\n/**\n * Clears the color cache - useful when theme changes\n */\nexport const clearColorCache = () => {\n colorCache.clear();\n};\n\n/**\n * Gets theme colors from CSS variables\n * Returns an array of resolved color values\n */\nexport const getThemeCategoricalColors = (): string[] => {\n const colors: string[] = [];\n\n // Try to get categorical colors from CSS variables\n for (let i = 1; i <= 6; i++) {\n const color = getResolvedColor(`--color-viz-categorical-${i}`);\n if (color) {\n colors.push(color);\n }\n }\n\n // Fallback to default palette if no theme colors found\n if (colors.length === 0) {\n return getDefaultColors();\n }\n\n return colors;\n};\n\n/**\n * Default color palette matching the edges design system\n */\nexport const getDefaultColors = (): string[] => [\n \"#444ae1\", // brand-primary\n \"#10b981\", // emerald-500\n \"#f59e0b\", // amber-500\n \"#ef4444\", // red-500\n \"#8b5cf6\", // violet-500\n \"#06b6d4\", // cyan-500\n \"#ec4899\", // pink-500\n \"#f97316\", // orange-500\n \"#14b8a6\", // teal-500\n \"#6366f1\", // indigo-500\n];\n\n/**\n * Gets the default chart color from theme\n */\nexport const getDefaultChartColor = (): string => {\n return getResolvedColor(\"--color-viz-default\", \"#444ae1\");\n};\n\n/**\n * Maps categories to colors based on a color scheme\n */\nexport const createCategoryColorMap = (\n categories: string[],\n customColors?: Record<string, string>\n): Record<string, string> => {\n const colorMap: Record<string, string> = {};\n const themeColors = getThemeCategoricalColors();\n\n categories.forEach((category, index) => {\n if (customColors && customColors[category]) {\n // Use custom color if provided\n colorMap[category] = customColors[category];\n } else {\n // Use theme color based on index\n colorMap[category] = themeColors[index % themeColors.length];\n }\n });\n\n return colorMap;\n};\n\n/**\n * Automatically assigns categorical colors to Mapbox layer paint properties\n * This makes it easy for consumers to get great colors without manual assignment\n */\nexport const createAutoColorPaint = (\n dataField: string, // The field to use for color assignment (e.g., \"state\", \"category\", \"type\")\n customColorMap?: Record<string, string>\n): Record<string, unknown> => {\n const defaultColor = getResolvedColor(\"--color-viz-default\", \"#444ae1\");\n\n // Create a case expression for Mapbox\n const caseExpression: unknown[] = [\"case\"];\n\n // Add custom color mappings first if provided\n if (customColorMap) {\n Object.entries(customColorMap).forEach(([value, color]) => {\n caseExpression.push([\"==\", [\"get\", dataField], value], color);\n });\n }\n\n // Add default categorical color cycling\n // This will cycle through colors for any values not in customColorMap\n caseExpression.push(defaultColor);\n\n return {\n \"fill-color\": caseExpression,\n };\n};\n\n/**\n * Creates a complete layer configuration with automatic color assignment\n * Perfect for consumers who just want to pass data and get great colors\n */\nexport const createDataLayer = (\n id: string,\n dataField: string,\n options: {\n type?: \"fill\" | \"line\" | \"circle\";\n customColors?: Record<string, string>;\n opacity?: number;\n strokeWidth?: number;\n strokeColor?: string;\n } = {}\n) => {\n const { type = \"fill\", customColors, opacity = 0.7 } = options;\n\n const baseLayer = {\n id,\n type,\n paint: {\n ...createAutoColorPaint(dataField, customColors),\n [`${type === \"fill\" ? \"fill\" : \"circle\"}-opacity`]: opacity,\n },\n layout: {\n visibility: \"visible\",\n },\n };\n\n // Add stroke for fill layers\n if (type === \"fill\") {\n baseLayer.paint[\"fill-opacity\"] = opacity;\n }\n\n return baseLayer;\n};\n\n/**\n * Determines if a color is light or dark\n * Useful for determining text color on colored backgrounds\n */\nexport const isLightColor = (color: string): boolean => {\n // Convert to RGB\n const rgb = color.match(/\\d+/g);\n if (!rgb || rgb.length < 3) return true;\n\n // Calculate luminance\n const [r, g, b] = rgb.map(Number);\n const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n\n return luminance > 0.5;\n};\n\n/**\n * Gets contrasting text color for a background\n */\nexport const getContrastingTextColor = (backgroundColor: string): string => {\n if (isLightColor(backgroundColor)) {\n return getResolvedColor(\"--text-body\", \"#333333\");\n }\n return getResolvedColor(\"--neutral-white\", \"#ffffff\");\n};\n\n/**\n * Extracts unique values for a given property from GeoJSON FeatureCollection\n *\n * @param data - GeoJSON FeatureCollection or Feature\n * @param property - Property name to extract values from\n * @returns Array of unique values, sorted\n * @throws Warning if data structure is invalid\n */\nexport const extractUniqueValues = (\n data: GeoJSON.FeatureCollection | GeoJSON.Feature,\n property: string\n): (string | number)[] => {\n // Validate data structure\n if (!data || typeof data !== \"object\") {\n console.warn(\"[Colors] Invalid GeoJSON data provided to extractUniqueValues\");\n return [];\n }\n\n // Validate it's GeoJSON\n if (!(\"type\" in data) || (data.type !== \"FeatureCollection\" && data.type !== \"Feature\")) {\n console.warn(\"[Colors] Data is not valid GeoJSON (missing type or invalid type)\");\n return [];\n }\n\n const values = new Set<string | number>();\n\n // Get features array\n const features = \"features\" in data ? data.features : [data];\n\n // Validate features exist\n if (!Array.isArray(features) || features.length === 0) {\n console.warn(`[Colors] No features found in GeoJSON data`);\n return [];\n }\n\n // Extract values\n let propertyFoundCount = 0;\n features.forEach((feature) => {\n if (!feature || typeof feature !== \"object\") {\n return; // Skip invalid features\n }\n\n if (feature.properties && property in feature.properties) {\n propertyFoundCount++;\n const value = feature.properties[property];\n if (value !== null && value !== undefined) {\n values.add(value);\n }\n }\n });\n\n // Warn if property wasn't found on any features\n if (propertyFoundCount === 0) {\n console.warn(\n `[Colors] Property \"${property}\" not found on any features. Available properties: ${\n features[0]?.properties ? Object.keys(features[0].properties).join(\", \") : \"none\"\n }`\n );\n }\n\n return Array.from(values).sort();\n};\n\n/**\n * Maps unique values to categorical colors with looping\n *\n * @param values - Array of unique values to map\n * @returns Map of value to color (hex string)\n */\nexport const mapValuesToCategoricalColors = (\n values: (string | number)[]\n): Record<string | number, string> => {\n const colors = getThemeCategoricalColors();\n const mapping: Record<string | number, string> = {};\n\n values.forEach((value, index) => {\n // Loop through colors if we have more values than colors\n mapping[value] = colors[index % colors.length];\n });\n\n return mapping;\n};\n\n/**\n * Creates a categorical color mapping for use with vector layers or explicit mappings\n *\n * This is a helper for cases where categorical auto-assignment doesn't work:\n * - Vector tile layers (data not accessible at render time)\n * - URL-based GeoJSON layers\n * - Custom pin layers\n *\n * @param property - The property name to color by (e.g., \"type\", \"category\")\n * @param values - Array of known values for this property\n * @returns ColorSpec with explicit mapping\n *\n * @example\n * // Vector layer with categorical coloring\n * layer.vector({\n * tileset: \"mapbox://my-tileset\",\n * sourceLayer: \"buildings\",\n * style: {\n * color: createCategoricalMapping(\"type\", [\"residential\", \"commercial\", \"industrial\"])\n * }\n * })\n *\n * @example\n * // With custom colors for specific values\n * const mapping = createCategoricalMapping(\"status\", [\"active\", \"pending\", \"inactive\"]);\n * // Then override specific colors if needed:\n * mapping.mapping.inactive = { hex: \"#cccccc\" };\n */\nexport const createCategoricalMapping = (\n property: string,\n values: (string | number)[]\n): { by: string; mapping: Record<string, { hex: string }> } => {\n const colorMap = mapValuesToCategoricalColors(values);\n\n const mapping: Record<string, { hex: string }> = {};\n Object.entries(colorMap).forEach(([value, color]) => {\n mapping[value] = { hex: color };\n });\n\n return {\n by: property,\n mapping,\n };\n};\n\n// ============================================================================\n// Sequential & Diverging Palette Utilities (Phase 2)\n// ============================================================================\n\n/**\n * Extract numeric values from GeoJSON data for sequential/diverging palettes\n *\n * @param data - GeoJSON FeatureCollection or Feature\n * @param property - Property name to extract values from\n * @returns Sorted array of numeric values\n */\nexport const extractNumericValues = (\n data: GeoJSON.FeatureCollection | GeoJSON.Feature,\n property: string\n): number[] => {\n if (!data || typeof data !== \"object\") {\n console.warn(\"[Colors] Invalid GeoJSON data provided to extractNumericValues\");\n return [];\n }\n\n if (!(\"type\" in data) || (data.type !== \"FeatureCollection\" && data.type !== \"Feature\")) {\n console.warn(\"[Colors] Data is not valid GeoJSON (missing type or invalid type)\");\n return [];\n }\n\n const features = \"features\" in data ? data.features : [data];\n\n if (!Array.isArray(features) || features.length === 0) {\n console.warn(`[Colors] No features found in GeoJSON data`);\n return [];\n }\n\n const values = new Set<number>();\n let propertyFoundCount = 0;\n\n features.forEach((feature) => {\n if (!feature || typeof feature !== \"object\") {\n return;\n }\n\n if (feature.properties && property in feature.properties) {\n propertyFoundCount++;\n const value = feature.properties[property];\n\n // Only accept actual numbers\n if (typeof value === \"number\" && !isNaN(value)) {\n values.add(value);\n }\n }\n });\n\n if (propertyFoundCount === 0) {\n console.warn(\n `[Colors] Property \"${property}\" not found on any features. Available properties: ${\n features[0]?.properties ? Object.keys(features[0].properties).join(\", \") : \"none\"\n }`\n );\n }\n\n return Array.from(values).sort((a, b) => a - b);\n};\n\n/**\n * Calculate min and max bounds from numeric values\n *\n * @param values - Sorted array of numeric values\n * @returns Object with min and max, or {min: 0, max: 1} if empty\n */\nexport const calculateBounds = (values: number[]): { min: number; max: number } => {\n if (values.length === 0) {\n console.warn(\"[Colors] Cannot calculate bounds from empty array\");\n return { min: 0, max: 1 };\n }\n\n return {\n min: values[0],\n max: values[values.length - 1],\n };\n};\n\n/**\n * Calculate center point for diverging palettes\n *\n * @param values - Sorted array of numeric values\n * @param method - \"median\", \"mean\", or explicit number\n * @returns Center value\n */\nexport const calculateCenter = (values: number[], method: \"median\" | \"mean\" | number): number => {\n // Explicit number provided\n if (typeof method === \"number\") {\n return method;\n }\n\n if (values.length === 0) {\n console.warn(\"[Colors] Cannot calculate center from empty array, defaulting to 0\");\n return 0;\n }\n\n if (method === \"median\") {\n const mid = Math.floor(values.length / 2);\n return values.length % 2 === 0 ? (values[mid - 1] + values[mid]) / 2 : values[mid];\n }\n\n // method === \"mean\"\n return values.reduce((sum, v) => sum + v, 0) / values.length;\n};\n\n/**\n * Get colors for a specific sequential palette\n *\n * @param scheme - Sequential palette name (defaults to \"viridis\")\n * @returns Array of 10 hex color strings\n */\nexport const getSequentialColors = (scheme: string = \"viridis\"): string[] => {\n // Convert camelCase to kebab-case\n const paletteMap: Record<string, string> = {\n redYellowGreen: \"red-yellow-green\",\n };\n\n const kebabName = paletteMap[scheme] || scheme;\n const prefix = `viz-sequential-${kebabName}`;\n const colors: string[] = [];\n\n // Each sequential palette has 10 colors (1-10)\n for (let i = 1; i <= 10; i++) {\n const cssVar = `${prefix}-${i}`;\n const resolved = getResolvedColor(cssVar);\n colors.push(resolved);\n }\n\n return colors;\n};\n\n/**\n * Get colors for a specific diverging palette\n *\n * @param scheme - Diverging palette name (defaults to \"redYellowBlue\")\n * @returns Array of 10 hex color strings (color 5 is the center)\n */\nexport const getDivergingColors = (scheme: string = \"redYellowBlue\"): string[] => {\n // Convert camelCase to kebab-case\n const paletteMap: Record<string, string> = {\n orangeYellowSeafoam: \"orange-yellow-seafoam\",\n redYellowBlue: \"red-yellow-blue\",\n redBlue: \"red-blue\",\n };\n\n const kebabName = paletteMap[scheme] || scheme;\n const prefix = `viz-diverging-${kebabName}`;\n const colors: string[] = [];\n\n // Each diverging palette has 10 colors (1-10), with 5 being the center\n for (let i = 1; i <= 10; i++) {\n const cssVar = `${prefix}-${i}`;\n const resolved = getResolvedColor(cssVar);\n colors.push(resolved);\n }\n\n return colors;\n};\n\n/**\n * Get color from sequential scale for a given value\n * Uses existing sequential palettes to interpolate color based on value position in range\n *\n * @param value - The value to get color for\n * @param min - Minimum value in the range\n * @param max - Maximum value in the range\n * @param scheme - Sequential palette name (defaults to \"viridis\")\n * @returns Interpolated color string\n *\n * @example\n * // Get color for response time (0-5000ms range)\n * const color = getColorFromSequentialScale(2500, 0, 5000, 'viridis');\n */\nexport const getColorFromSequentialScale = (\n value: number,\n min: number,\n max: number,\n scheme: string = \"viridis\"\n): string => {\n const colors = getSequentialColors(scheme);\n\n // Handle edge cases\n if (value <= min) return colors[0];\n if (value >= max) return colors[colors.length - 1];\n if (min === max) return colors[Math.floor(colors.length / 2)];\n\n // Calculate position in range (0 to 1)\n const position = (value - min) / (max - min);\n\n // Map to color index (0 to colors.length - 1)\n const colorIndex = position * (colors.length - 1);\n const lowerIndex = Math.floor(colorIndex);\n const upperIndex = Math.ceil(colorIndex);\n\n // If exact match, return that color\n if (lowerIndex === upperIndex) {\n return colors[lowerIndex];\n }\n\n // For now, return the lower color (simple implementation)\n // Could be enhanced with actual color interpolation in the future\n return colors[lowerIndex];\n};\n\n/**\n * Get color from diverging scale for a given value\n * Uses existing diverging palettes to interpolate color based on value position relative to center\n *\n * @param value - The value to get color for\n * @param min - Minimum value in the range\n * @param max - Maximum value in the range\n * @param center - The center point of the diverging scale\n * @param scheme - Diverging palette name (defaults to \"redYellowBlue\")\n * @returns Interpolated color string\n *\n * @example\n * // Get color for temperature anomaly (-10 to +10, center at 0)\n * const color = getColorFromDivergingScale(5, -10, 10, 0, 'redYellowBlue');\n */\nexport const getColorFromDivergingScale = (\n value: number,\n min: number,\n max: number,\n center: number,\n scheme: string = \"redYellowBlue\"\n): string => {\n const colors = getDivergingColors(scheme);\n const centerIndex = 4; // 5th color (index 4) is the center\n\n // Handle edge cases\n if (value <= min) return colors[0];\n if (value >= max) return colors[colors.length - 1];\n if (value === center) return colors[centerIndex];\n if (min === max) return colors[centerIndex];\n\n // Determine which side of center we're on\n if (value < center) {\n // Left side: min to center (colors 0-4)\n const position = (value - min) / (center - min);\n const colorIndex = position * centerIndex;\n const lowerIndex = Math.floor(colorIndex);\n return colors[Math.min(lowerIndex, centerIndex)];\n } else {\n // Right side: center to max (colors 4-9)\n const position = (value - center) / (max - center);\n const colorIndex = centerIndex + position * (colors.length - 1 - centerIndex);\n const lowerIndex = Math.floor(colorIndex);\n return colors[Math.min(lowerIndex, colors.length - 1)];\n }\n};\n\n/**\n * Creates a sequential color mapping for vector layers or manual bounds\n *\n * Use this helper when categorical auto-assignment doesn't work:\n * - Vector tile layers (data not accessible at render time)\n * - URL-based GeoJSON layers\n * - When you want consistent colors across multiple maps\n *\n * @param property - The property name to color by\n * @param bounds - Min and max values for the scale\n * @param scheme - Sequential palette name (defaults to \"viridis\")\n * @returns Mapbox interpolate expression\n *\n * @example\n * // Vector layer with sequential coloring\n * layer.vector({\n * tileset: \"mapbox://my-tileset\",\n * sourceLayer: \"population\",\n * style: {\n * color: createSequentialMapping(\"density\", { min: 0, max: 100000 }, \"magma\")\n * }\n * })\n */\nexport const createSequentialMapping = (\n property: string,\n bounds: { min: number; max: number },\n scheme: string = \"viridis\"\n): MapboxExpression => {\n const colors = getSequentialColors(scheme);\n const expr: MapboxExpression = [\"interpolate\", [\"linear\"], [\"get\", property]];\n\n // Guard against collapsed range (all values the same)\n // Mapbox requires at least 2 stops for interpolate, so use same color for min and a tiny offset\n if (bounds.min === bounds.max) {\n expr.push(bounds.min, colors[0]);\n expr.push(bounds.min + 0.0001, colors[0]);\n return expr;\n }\n\n colors.forEach((color, i) => {\n const t = i / (colors.length - 1); // 0 to 1\n const value = bounds.min + t * (bounds.max - bounds.min);\n expr.push(value, color);\n });\n\n return expr;\n};\n\n/**\n * Creates a diverging color mapping for vector layers or manual bounds\n *\n * Use this helper when categorical auto-assignment doesn't work:\n * - Vector tile layers (data not accessible at render time)\n * - URL-based GeoJSON layers\n * - When you want consistent colors across multiple maps\n *\n * @param property - The property name to color by\n * @param bounds - Min and max values for the scale\n * @param center - The center point (e.g., 0 for average, sea level, break-even)\n * @param scheme - Diverging palette name (defaults to \"redYellowBlue\")\n * @returns Mapbox interpolate expression\n *\n * @example\n * // Vector layer with diverging coloring\n * layer.vector({\n * tileset: \"mapbox://my-tileset\",\n * sourceLayer: \"temperature\",\n * style: {\n * color: createDivergingMapping(\"temp_anomaly\", { min: -10, max: 10 }, 0, \"orangeYellowSeafoam\")\n * }\n * })\n */\nexport const createDivergingMapping = (\n property: string,\n bounds: { min: number; max: number },\n center: number,\n scheme: string = \"redYellowBlue\"\n): MapboxExpression => {\n const colors = getDivergingColors(scheme);\n const expr: MapboxExpression = [\"interpolate\", [\"linear\"], [\"get\", property]];\n const centerIndex = 4; // 5th color (index 4) is the center\n\n // Guard against collapsed range (all values the same)\n // Mapbox requires at least 2 stops for interpolate, so use same color for min and a tiny offset\n if (bounds.min === bounds.max) {\n expr.push(bounds.min, colors[centerIndex]);\n expr.push(bounds.min + 0.0001, colors[centerIndex]);\n return expr;\n }\n\n // Handle center at min edge\n if (center === bounds.min) {\n expr.push(center, colors[centerIndex]);\n // Only add stops from center to max\n for (let i = centerIndex + 1; i < colors.length; i++) {\n const t = (i - centerIndex) / (colors.length - 1 - centerIndex);\n const value = center + t * (bounds.max - center);\n expr.push(value, colors[i]);\n }\n return expr;\n }\n\n // Handle center at max edge\n if (center === bounds.max) {\n // Only add stops from min to center\n for (let i = 0; i < centerIndex; i++) {\n const t = i / centerIndex;\n const value = bounds.min + t * (center - bounds.min);\n expr.push(value, colors[i]);\n }\n expr.push(center, colors[centerIndex]);\n return expr;\n }\n\n // Normal case: center is between min and max\n // Colors 1-5: min → center\n for (let i = 0; i <= centerIndex; i++) {\n const t = i / centerIndex; // 0 to 1\n const value = bounds.min + t * (center - bounds.min);\n expr.push(value, colors[i]);\n }\n\n // Colors 6-10: center → max\n for (let i = centerIndex + 1; i < colors.length; i++) {\n const t = (i - centerIndex) / (colors.length - 1 - centerIndex); // 0 to 1\n const value = center + t * (bounds.max - center);\n expr.push(value, colors[i]);\n }\n\n return expr;\n};\n","/**\n * FormatRegistry - A singleton pattern for managing formatters\n * Allows registration and retrieval of formatting functions by key\n */\n\nimport type { FieldValue, FormattedValue, FormatterFunction } from \"./types\";\n\nclass FormatRegistryClass {\n private formatters: Map<string, FormatterFunction> = new Map();\n\n /**\n * Register a new formatter\n * @param key - Unique identifier for the formatter\n * @param formatter - The formatting function\n */\n register(key: string, formatter: FormatterFunction): void {\n this.formatters.set(key, formatter);\n }\n\n /**\n * Format a value using a registered formatter\n * @param key - The formatter key\n * @param value - The value to format\n * @param args - Additional arguments to pass to the formatter\n * @returns The formatted value or null\n */\n format(key: string, value: FieldValue, ...args: unknown[]): FormattedValue {\n const formatter = this.formatters.get(key);\n if (!formatter) {\n console.warn(`No formatter registered for key: ${key}`);\n return null;\n }\n return formatter(value, ...args);\n }\n\n /**\n * Check if a formatter is registered\n * @param key - The formatter key\n * @returns True if the formatter exists\n */\n has(key: string): boolean {\n return this.formatters.has(key);\n }\n\n /**\n * Get all registered formatter keys\n * @returns Array of formatter keys\n */\n keys(): string[] {\n return Array.from(this.formatters.keys());\n }\n\n /**\n * Remove a formatter\n * @param key - The formatter key to remove\n */\n unregister(key: string): void {\n this.formatters.delete(key);\n }\n\n /**\n * Clear all registered formatters\n */\n clear(): void {\n this.formatters.clear();\n }\n}\n\n// Export singleton instance\nexport const FormatRegistry = new FormatRegistryClass();\n","/**\n * Boolean formatting utilities\n */\n\nimport { FormatRegistry } from \"./registry\";\nimport type { BooleanFormat, FieldValue, FormattedValue } from \"./types\";\n\n/**\n * Format boolean value with custom text\n */\nexport const toBoolean = (\n value: boolean | null | undefined,\n trueText: string = \"Yes\",\n falseText: string = \"No\"\n): string | null => {\n if (value === null || value === undefined) return null;\n return value ? trueText : falseText;\n};\n\n/**\n * Format boolean as enabled/disabled\n */\nexport const toEnabledDisabled = (value: boolean | null | undefined): string | null => {\n return toBoolean(value, \"Enabled\", \"Disabled\");\n};\n\n/**\n * Format boolean as on/off\n */\nexport const toOnOff = (value: boolean | null | undefined): string | null => {\n return toBoolean(value, \"On\", \"Off\");\n};\n\n/**\n * Format boolean as active/inactive\n */\nexport const toActiveInactive = (value: boolean | null | undefined): string | null => {\n return toBoolean(value, \"Active\", \"Inactive\");\n};\n\n/**\n * Format boolean as true/false\n */\nexport const toTrueFalse = (value: boolean | null | undefined): string | null => {\n return toBoolean(value, \"True\", \"False\");\n};\n\n/**\n * Format boolean as checkmark/cross\n */\nexport const toCheckmark = (value: boolean | null | undefined): string | null => {\n return toBoolean(value, \"✓\", \"✗\");\n};\n\n/**\n * Parse various truthy/falsy values to boolean\n */\nexport const parseBoolean = (value: FieldValue): boolean | null => {\n if (value === null || value === undefined) return null;\n\n if (typeof value === \"boolean\") {\n return value;\n }\n\n if (typeof value === \"string\") {\n const lower = value.toLowerCase().trim();\n if (\n lower === \"true\" ||\n lower === \"yes\" ||\n lower === \"1\" ||\n lower === \"on\" ||\n lower === \"enabled\"\n ) {\n return true;\n }\n if (\n lower === \"false\" ||\n lower === \"no\" ||\n lower === \"0\" ||\n lower === \"off\" ||\n lower === \"disabled\"\n ) {\n return false;\n }\n return null;\n }\n\n if (typeof value === \"number\") {\n return value !== 0;\n }\n\n return null;\n};\n\n/**\n * Format boolean according to BooleanFormat specification\n */\nexport const formatBoolean = (value: FieldValue, format: BooleanFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (value == null) return format.nullText ?? null;\n\n const boolValue = parseBoolean(value);\n if (boolValue === null) return format.nullText ?? null;\n\n return toBoolean(boolValue, format.trueText ?? \"Yes\", format.falseText ?? \"No\");\n};\n\n// Register boolean formatters\nFormatRegistry.register(\"boolean\", (value, trueText, falseText) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toBoolean(\n boolValue,\n typeof trueText === \"string\" ? trueText : \"Yes\",\n typeof falseText === \"string\" ? falseText : \"No\"\n );\n }\n return null;\n});\n\nFormatRegistry.register(\"yesNo\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toBoolean(boolValue, \"Yes\", \"No\");\n }\n return null;\n});\n\nFormatRegistry.register(\"enabledDisabled\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toEnabledDisabled(boolValue);\n }\n return null;\n});\n\nFormatRegistry.register(\"onOff\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toOnOff(boolValue);\n }\n return null;\n});\n\nFormatRegistry.register(\"activeInactive\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toActiveInactive(boolValue);\n }\n return null;\n});\n\nFormatRegistry.register(\"trueFalse\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toTrueFalse(boolValue);\n }\n return null;\n});\n\nFormatRegistry.register(\"checkmark\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toCheckmark(boolValue);\n }\n return null;\n});\n","/**\n * Number and currency formatting utilities\n */\n\nimport { FormatRegistry } from \"./registry\";\nimport type { CurrencyFormat, FieldValue, FormattedValue, NumberFormat } from \"./types\";\n\n/**\n * Check if a value is null or undefined\n */\nexport const isNil = (value: unknown): value is null | undefined => {\n return value === null || value === undefined;\n};\n\n/**\n * Format as percentage\n */\nexport const toPercentage = (\n value: number | null | undefined,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)}%`;\n};\n\n/**\n * Format percentage (simple wrapper for consistency with other formatters)\n *\n * @param value - Numeric value (0-100 range)\n * @param precision - Number of decimal places (default: 0)\n * @returns Formatted percentage string with % symbol\n */\nexport const formatPercent = (value: number | null | undefined, precision: number = 0): string => {\n const result = toPercentage(value, precision);\n return result ?? \"—\";\n};\n\n/**\n * Format as integer\n */\nexport const toInteger = (value: number | null | undefined): string | null => {\n if (isNil(value)) return null;\n return Math.round(value).toString();\n};\n\n/**\n * Format as float with specified decimals\n */\nexport const toFloat = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return value.toFixed(decimals);\n};\n\n/**\n * Format number with thousands separator\n */\nexport const toFormattedNumber = (\n value: number | null | undefined,\n decimals?: number,\n thousandsSeparator: boolean = true\n): string | null => {\n if (isNil(value)) return null;\n\n const options: Intl.NumberFormatOptions = {\n useGrouping: thousandsSeparator,\n };\n\n if (decimals !== undefined) {\n options.minimumFractionDigits = decimals;\n options.maximumFractionDigits = decimals;\n }\n\n return new Intl.NumberFormat(\"en-US\", options).format(value);\n};\n\n/**\n * Format number with compact notation (1K, 1M, etc.)\n */\nexport const toCompactNumber = (\n value: number | null | undefined,\n display: \"short\" | \"long\" = \"short\"\n): string | null => {\n if (isNil(value)) return null;\n\n return new Intl.NumberFormat(\"en-US\", {\n notation: \"compact\",\n compactDisplay: display,\n }).format(value);\n};\n\n/**\n * Format number with scientific notation\n */\nexport const toScientificNotation = (\n value: number | null | undefined,\n decimals: number = 2\n): string | null => {\n if (isNil(value)) return null;\n return value.toExponential(decimals);\n};\n\n/**\n * Format as currency\n */\nexport const toCurrency = (\n value: number | null | undefined,\n currency: string = \"USD\",\n options?: Partial<CurrencyFormat>\n): string | null => {\n if (isNil(value)) return null;\n\n const formatOptions: Intl.NumberFormatOptions = {\n style: \"currency\",\n currency,\n currencyDisplay: options?.currencyDisplay ?? \"symbol\",\n useGrouping: options?.thousandsSeparator ?? true,\n };\n\n if (options?.minimumFractionDigits !== undefined) {\n formatOptions.minimumFractionDigits = options.minimumFractionDigits;\n }\n\n if (options?.maximumFractionDigits !== undefined) {\n formatOptions.maximumFractionDigits = options.maximumFractionDigits;\n }\n\n return new Intl.NumberFormat(\"en-US\", formatOptions).format(value);\n};\n\n/**\n * Format number according to NumberFormat specification\n */\nexport const formatNumber = (value: FieldValue, format: NumberFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const options: Intl.NumberFormatOptions = {\n useGrouping: format.thousandsSeparator ?? false,\n };\n\n if (format.decimals !== undefined) {\n options.minimumFractionDigits = format.decimals;\n options.maximumFractionDigits = format.decimals;\n }\n\n if (format.notation) {\n options.notation = format.notation;\n if (format.notation === \"compact\" && format.compactDisplay) {\n options.compactDisplay = format.compactDisplay;\n }\n }\n\n if (format.sign) {\n options.signDisplay = format.sign;\n }\n\n return new Intl.NumberFormat(\"en-US\", options).format(numValue);\n};\n\n/**\n * Format currency according to CurrencyFormat specification\n */\nexport const formatCurrency = (value: FieldValue, format: CurrencyFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n return toCurrency(numValue, format.currency, format);\n};\n\n// Register number formatters\nFormatRegistry.register(\"percentage\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toPercentage(value, typeof decimals === \"number\" ? decimals : 0);\n }\n return null;\n});\n\nFormatRegistry.register(\"integer\", (value) => {\n if (typeof value === \"number\") {\n return toInteger(value);\n }\n return null;\n});\n\nFormatRegistry.register(\"float\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toFloat(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\nFormatRegistry.register(\"number\", (value, decimals, thousandsSeparator) => {\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (!isNaN(numValue)) {\n return toFormattedNumber(\n numValue,\n typeof decimals === \"number\" ? decimals : undefined,\n typeof thousandsSeparator === \"boolean\" ? thousandsSeparator : true\n );\n }\n return null;\n});\n\nFormatRegistry.register(\"compact\", (value, display) => {\n if (typeof value === \"number\") {\n return toCompactNumber(value, display === \"long\" ? \"long\" : \"short\");\n }\n return null;\n});\n\nFormatRegistry.register(\"scientific\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toScientificNotation(value, typeof decimals === \"number\" ? decimals : 2);\n }\n return null;\n});\n\nFormatRegistry.register(\"currency\", (value, currency, options) => {\n if (typeof value === \"number\") {\n return toCurrency(\n value,\n typeof currency === \"string\" ? currency : \"USD\",\n typeof options === \"object\" && options !== null ? options : {}\n );\n }\n return null;\n});\n","/**\n * Centralized formatting utility for UI components\n * Used by Kpi, StatList, and other data display components\n */\n\nimport React from \"react\";\nimport { formatFieldValue } from \"./index\";\nimport type { FieldFormat, FieldValue } from \"./types\";\n\n/**\n * Common formatter type used by data display components\n * Can be either a custom function or a FieldFormat object\n */\nexport type ComponentFormatter = ((value: FieldValue) => React.ReactNode) | FieldFormat;\n\n/**\n * Options for formatting values in components\n */\nexport interface ComponentFormatOptions {\n /** The value to format */\n value: FieldValue;\n /** The formatter to apply */\n formatter?: ComponentFormatter;\n /** CSS class for null/empty values */\n emptyClassName?: string;\n /** Text to show for null/empty values */\n emptyText?: React.ReactNode;\n}\n\n/**\n * Format a value for display in a component\n * Centralizes the logic used by Kpi, StatList, and similar components\n *\n * @example\n * ```tsx\n * // In a component\n * const formatted = formatComponentValue({\n * value: 1500,\n * formatter: { type: \"power\" }\n * });\n * // Returns: \"1.5 kW\"\n * ```\n */\nexport function formatComponentValue({\n value,\n formatter,\n emptyClassName = \"text-text-muted\",\n emptyText = \"—\",\n}: ComponentFormatOptions): React.ReactNode {\n // Handle null/undefined early\n if (value == null) {\n return <span className={emptyClassName}>{emptyText}</span>;\n }\n\n // Custom formatter function takes precedence\n if (typeof formatter === \"function\") {\n return formatter(value);\n }\n\n // If a FieldFormat is provided, use the unified formatting system\n if (formatter && typeof formatter === \"object\") {\n const formatted = formatFieldValue(value, formatter);\n\n // Wrap dates in semantic time element for accessibility\n if (value instanceof Date && formatted) {\n return (\n <time dateTime={value.toISOString()} title={value.toISOString()}>\n {formatted}\n </time>\n );\n }\n\n return formatted || <span className={emptyClassName}>{emptyText}</span>;\n }\n\n // No formatter provided - use sensible defaults based on type\n if (!formatter) {\n // For strings, just return as-is\n if (typeof value === \"string\") {\n return value;\n }\n\n // For dates, use default date formatting\n if (value instanceof Date) {\n const formatted = formatFieldValue(value, { type: \"date\" });\n return (\n <time dateTime={value.toISOString()} title={value.toISOString()}>\n {formatted}\n </time>\n );\n }\n\n // For numbers, use default number formatting\n if (typeof value === \"number\") {\n return formatFieldValue(value, { type: \"number\" });\n }\n\n // For booleans, use default boolean formatting\n if (typeof value === \"boolean\") {\n return formatFieldValue(value, { type: \"boolean\" });\n }\n }\n\n // Fallback to string conversion\n return String(value);\n}\n\n/**\n * Hook for using the component formatter\n * Provides memoization for better performance\n *\n * @example\n * ```tsx\n * function MyComponent({ value, formatter }) {\n * const format = useComponentFormatter(formatter);\n * const formatted = format(value);\n * return <span>{formatted}</span>;\n * }\n * ```\n */\nexport function useComponentFormatter(\n formatter?: ComponentFormatter,\n emptyClassName?: string,\n emptyText?: React.ReactNode\n) {\n return React.useCallback(\n (value: FieldValue) =>\n formatComponentValue({\n value,\n formatter,\n emptyClassName,\n emptyText,\n }),\n [formatter, emptyClassName, emptyText]\n );\n}\n","/**\n * Electrical current formatting utilities (flow of electric charge)\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { CurrentFormat, FieldValue, FormattedValue } from \"./types\";\n\n/**\n * Format as milliamps\n */\nexport const toMilliamps = (\n value: number | null | undefined,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n const mA = value * 1000;\n return decimals === 0 ? `${Math.round(mA)} mA` : `${mA.toFixed(decimals)} mA`;\n};\n\n/**\n * Format as amperes\n */\nexport const toAmps = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} A`;\n};\n\n/**\n * Format as kiloamps (rarely used but included for completeness)\n */\nexport const toKiloamps = (\n value: number | null | undefined,\n decimals: number = 2\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} kA`;\n};\n\n/**\n * Auto-scale current to the most appropriate unit\n */\nexport const autoScaleCurrent = (\n value: number | null | undefined,\n decimals?: number\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (absValue >= 1000) {\n return toKiloamps(value, decimals ?? 2);\n } else if (absValue < 1) {\n return toMilliamps(value, decimals ?? 0);\n } else {\n return toAmps(value, decimals ?? 1);\n }\n};\n\n/**\n * Format current according to CurrentFormat specification\n */\nexport const formatCurrent = (value: FieldValue, format: CurrentFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals;\n\n // If a specific unit is provided, use it\n if (format.unit) {\n switch (format.unit) {\n case \"kA\":\n return toKiloamps(numValue, decimals ?? 2);\n case \"mA\":\n return toMilliamps(numValue, decimals ?? 0);\n case \"A\":\n return toAmps(numValue, decimals ?? 1);\n }\n }\n\n // Default to auto-scaling unless explicitly disabled\n if (format.autoScale !== false) {\n return autoScaleCurrent(numValue, decimals);\n }\n\n // If auto-scale is explicitly false and no unit specified, use base amps\n return toAmps(numValue, decimals ?? 1);\n};\n\n// Register the formatter\n// biome-ignore lint/suspicious/noExplicitAny: Required for FormatRegistry type compatibility\nFormatRegistry.register(\"current\", formatCurrent as any);\n\n// Convenience exports with shorter names\nexport const toMA = toMilliamps;\nexport const toA = toAmps;\nexport const toKA = toKiloamps;\n","/**\n * Date formatting utilities using Luxon\n */\n\nimport { DateTime } from \"luxon\";\nimport { FormatRegistry } from \"./registry\";\nimport type { DateFormat, FieldValue, FormattedValue } from \"./types\";\n\n/**\n * Convert a value to a Luxon DateTime object.\n * Handles Date objects, ISO strings, and timestamps.\n *\n * @param value - Value to convert (Date, string, number, or null/undefined)\n * @returns Luxon DateTime object or null if invalid\n */\nconst toDateTime = (value: FieldValue): DateTime | null => {\n if (value === null || value === undefined) return null;\n\n if (value instanceof Date) {\n return DateTime.fromJSDate(value);\n }\n\n if (typeof value === \"string\") {\n const dt = DateTime.fromISO(value);\n return dt.isValid ? dt : null;\n }\n\n if (typeof value === \"number\") {\n // Assume it's a timestamp in milliseconds\n const dt = DateTime.fromMillis(value);\n return dt.isValid ? dt : null;\n }\n\n return null;\n};\n\n/**\n * Format date to a localized string with optional time and timezone.\n *\n * @param value - Date value (string, Date object, or timestamp)\n * @param showTime - Whether to include time in the output (default: false)\n * @param timezone - Optional timezone for display (e.g., \"America/New_York\")\n * @returns Formatted date string or null\n *\n * @example\n * ```typescript\n * toDateString(new Date()); // \"12/25/2023\"\n * toDateString(new Date(), true); // \"12/25/2023, 3:30 PM\"\n * toDateString(\"2023-12-25T15:30:00Z\", true, \"America/New_York\"); // \"12/25/2023, 10:30 AM\"\n * ```\n */\nexport const toDateString = (\n value: string | Date | number | null | undefined,\n showTime: boolean = false,\n timezone?: string\n): string | null => {\n if (!value) return null;\n\n const dt = toDateTime(value);\n if (!dt) return \"Invalid Date\";\n\n const dtWithZone = timezone ? dt.setZone(timezone) : dt;\n\n return showTime\n ? dtWithZone.toLocaleString(DateTime.DATETIME_SHORT)\n : dtWithZone.toLocaleString(DateTime.DATE_SHORT);\n};\n\n/**\n * Format date to relative time (e.g., \"2 hours ago\", \"in 3 days\").\n * Automatically chooses the most appropriate unit.\n *\n * @param value - Date value (string, Date object, or timestamp)\n * @returns Relative time string or null\n *\n * @example\n * ```typescript\n * toRelativeTime(new Date(Date.now() - 3600000)); // \"1 hour ago\"\n * toRelativeTime(new Date(Date.now() + 86400000)); // \"in 1 day\"\n * toRelativeTime(new Date()); // \"now\"\n * ```\n */\nexport const toRelativeTime = (value: string | Date | number | null | undefined): string | null => {\n if (!value) return null;\n\n const dt = toDateTime(value);\n if (!dt) return \"Invalid Date\";\n\n return dt.toRelative();\n};\n\n/**\n * Format date with full date and time including weekday\n */\nexport const toFullDateTime = (\n value: string | Date | number | null | undefined,\n timezone?: string\n): string | null => {\n if (!value) return null;\n\n const dt = toDateTime(value);\n if (!dt) return \"Invalid Date\";\n\n const dtWithZone = timezone ? dt.setZone(timezone) : dt;\n return dtWithZone.toLocaleString(DateTime.DATETIME_MED_WITH_WEEKDAY);\n};\n\n/**\n * Format date to ISO string\n */\nexport const toISOString = (value: string | Date | number | null | undefined): string | null => {\n if (!value) return null;\n\n const dt = toDateTime(value);\n if (!dt) return null;\n\n return dt.toISO();\n};\n\n/**\n * Format date with custom format string\n */\nexport const toCustomDateFormat = (\n value: string | Date | number | null | undefined,\n format: string,\n timezone?: string\n): string | null => {\n if (!value) return null;\n\n const dt = toDateTime(value);\n if (!dt) return \"Invalid Date\";\n\n const dtWithZone = timezone ? dt.setZone(timezone) : dt;\n return dtWithZone.toFormat(format);\n};\n\n/**\n * Get formatted date parts\n */\nexport const getDateParts = (value: string | Date | number | null | undefined) => {\n const dt = toDateTime(value);\n if (!dt) return null;\n\n return {\n year: dt.year,\n month: dt.month,\n day: dt.day,\n weekday: dt.weekday,\n hour: dt.hour,\n minute: dt.minute,\n second: dt.second,\n millisecond: dt.millisecond,\n weekdayShort: dt.weekdayShort,\n weekdayLong: dt.weekdayLong,\n monthShort: dt.monthShort,\n monthLong: dt.monthLong,\n };\n};\n\n/**\n * Format date according to DateFormat specification\n */\nexport const formatDate = (value: FieldValue, format: DateFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (value == null) return format.nullText ?? null;\n\n const dt = toDateTime(value);\n if (!dt) return format.nullText ?? \"Invalid Date\";\n\n const dtWithZone = format.timezone ? dt.setZone(format.timezone) : dt;\n\n // Handle relative time\n if (format.relative) {\n return dtWithZone.toRelative();\n }\n\n // Handle custom format string\n if (format.format) {\n return dtWithZone.toFormat(format.format);\n }\n\n // Handle style-based formatting\n if (format.dateStyle || format.timeStyle) {\n const options: Record<string, unknown> = {};\n\n if (format.dateStyle) {\n switch (format.dateStyle) {\n case \"short\":\n options.date = DateTime.DATE_SHORT;\n break;\n case \"medium\":\n options.date = DateTime.DATE_MED;\n break;\n case \"long\":\n options.date = DateTime.DATE_FULL;\n break;\n case \"full\":\n options.date = DateTime.DATE_HUGE;\n break;\n }\n }\n\n if (format.timeStyle) {\n switch (format.timeStyle) {\n case \"short\":\n options.time = DateTime.TIME_SIMPLE;\n break;\n case \"medium\":\n options.time = DateTime.TIME_WITH_SECONDS;\n break;\n case \"long\":\n case \"full\":\n options.time = DateTime.TIME_WITH_SHORT_OFFSET;\n break;\n }\n }\n\n if (options.date && options.time) {\n return dtWithZone.toLocaleString({ ...options.date, ...options.time });\n } else if (options.date) {\n return dtWithZone.toLocaleString(options.date);\n } else if (options.time) {\n return dtWithZone.toLocaleString(options.time);\n }\n }\n\n // Default formatting\n return dtWithZone.toLocaleString(DateTime.DATETIME_SHORT);\n};\n\n// Register date formatters\nFormatRegistry.register(\"date\", (value, showTime, timezone) => {\n return toDateString(\n value as string | Date | number,\n typeof showTime === \"boolean\" ? showTime : false,\n typeof timezone === \"string\" ? timezone : undefined\n );\n});\n\nFormatRegistry.register(\"relativeTime\", (value) => {\n return toRelativeTime(value as string | Date | number);\n});\n\nFormatRegistry.register(\"fullDateTime\", (value, timezone) => {\n return toFullDateTime(\n value as string | Date | number,\n typeof timezone === \"string\" ? timezone : undefined\n );\n});\n\nFormatRegistry.register(\"isoString\", (value) => {\n return toISOString(value as string | Date | number);\n});\n\nFormatRegistry.register(\"customDateFormat\", (value, format, timezone) => {\n if (typeof format === \"string\") {\n return toCustomDateFormat(\n value as string | Date | number,\n format,\n typeof timezone === \"string\" ? timezone : undefined\n );\n }\n return null;\n});\n","/**\n * Distance and length formatting utilities\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { DistanceFormat, FieldValue, FormattedValue } from \"./types\";\n\n/**\n * Format as meters\n */\nexport const toMeters = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} m`;\n};\n\n/**\n * Format as centimeters\n */\nexport const toCentimeters = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value * 100).toFixed(decimals)} cm`;\n};\n\n/**\n * Format as millimeters\n */\nexport const toMillimeters = (\n value: number | null | undefined,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n return `${(value * 1000).toFixed(decimals)} mm`;\n};\n\n/**\n * Format as kilometers\n */\nexport const toKilometers = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} km`;\n};\n\n/**\n * Format as feet\n */\nexport const toFeet = (value: number | null | undefined, decimals: number = 0): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} ft`;\n};\n\n/**\n * Format as inches\n */\nexport const toInches = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} in`;\n};\n\n/**\n * Format as miles\n */\nexport const toMiles = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} mi`;\n};\n\n/**\n * Format as yards\n */\nexport const toYards = (value: number | null | undefined, decimals: number = 0): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} yd`;\n};\n\n/**\n * Format as nautical miles\n */\nexport const toNauticalMiles = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} nm`;\n};\n\n/**\n * Conversion utilities\n */\nexport const metersToFeet = (meters: number): number => meters * 3.28084;\nexport const feetToMeters = (feet: number): number => feet / 3.28084;\nexport const milesToKilometers = (miles: number): number => miles * 1.60934;\nexport const kilometersToMiles = (km: number): number => km / 1.60934;\nexport const feetToMiles = (feet: number): number => feet / 5280;\nexport const milesToFeet = (miles: number): number => miles * 5280;\nexport const metersToMiles = (meters: number): number => meters / 1609.34;\nexport const milesToMeters = (miles: number): number => miles * 1609.34;\nexport const yardsToMeters = (yards: number): number => yards * 0.9144;\nexport const metersToYards = (meters: number): number => meters / 0.9144;\nexport const inchesToCentimeters = (inches: number): number => inches * 2.54;\nexport const centimetersToInches = (cm: number): number => cm / 2.54;\n\n/**\n * Auto-scale distance to the most appropriate unit\n */\nexport const autoScaleDistance = (\n value: number | null | undefined,\n metric: boolean = false,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (metric) {\n // Assuming value is in meters\n if (absValue >= 1000) {\n return toKilometers(value, decimals);\n } else if (absValue < 0.01) {\n return toMillimeters(value, 0);\n } else if (absValue < 1) {\n return toCentimeters(value, decimals);\n } else {\n return toMeters(value, decimals);\n }\n } else {\n // Assuming value is in miles for imperial\n if (absValue < 0.01) {\n // Convert to feet\n return toFeet(milesToFeet(value), 0);\n } else if (absValue < 0.1) {\n // Convert to yards\n return toYards(milesToFeet(value) / 3, 0);\n } else {\n return toMiles(value, decimals);\n }\n }\n};\n\n/**\n * Format distance according to DistanceFormat specification\n */\nexport const formatDistance = (value: FieldValue, format: DistanceFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals ?? 1;\n\n if (format.autoScale) {\n const isMetric = format.unit === \"m\" || format.unit === \"km\";\n return autoScaleDistance(numValue, isMetric, decimals);\n }\n\n switch (format.unit) {\n case \"km\":\n return toKilometers(numValue, decimals);\n case \"ft\":\n return toFeet(numValue, decimals);\n case \"mi\":\n return toMiles(numValue, decimals);\n case \"yd\":\n return toYards(numValue, decimals);\n case \"m\":\n default:\n return toMeters(numValue, decimals);\n }\n};\n\n// Register distance formatters\nFormatRegistry.register(\"miles\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toMiles(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\nFormatRegistry.register(\"kilometers\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toKilometers(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\nFormatRegistry.register(\"meters\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toMeters(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\nFormatRegistry.register(\"feet\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toFeet(value, typeof decimals === \"number\" ? decimals : 0);\n }\n return null;\n});\n\nFormatRegistry.register(\"yards\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toYards(value, typeof decimals === \"number\" ? decimals : 0);\n }\n return null;\n});\n\nFormatRegistry.register(\"inches\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toInches(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\nFormatRegistry.register(\"autoScaleDistance\", (value, metric, decimals) => {\n if (typeof value === \"number\") {\n return autoScaleDistance(\n value,\n typeof metric === \"boolean\" ? metric : false,\n typeof decimals === \"number\" ? decimals : 1\n );\n }\n return null;\n});\n","/**\n * Energy formatting utilities (stored or consumed energy)\n * For power (rate of energy), use power.ts\n * For electrical units (voltage, current), use voltage.ts and current.ts\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { EnergyFormat, FieldValue, FormattedValue } from \"./types\";\n\n/**\n * Format as Watt-hours\n */\nexport const toWh = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} Wh`;\n};\n\n/**\n * Format as kilowatt-hours\n */\nexport const tokWh = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} kWh`;\n};\n\n/**\n * Format as megawatt-hours\n */\nexport const toMWh = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1_000_000).toFixed(decimals)} MWh`;\n};\n\n/**\n * Format as gigawatt-hours\n */\nexport const toGWh = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1_000_000_000).toFixed(decimals)} GWh`;\n};\n\n/**\n * Auto-scale energy to the most appropriate unit\n */\nexport const autoScaleEnergy = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (absValue >= 1_000_000_000) {\n return toGWh(value, decimals);\n } else if (absValue >= 1_000_000) {\n return toMWh(value, decimals);\n } else if (absValue >= 1000) {\n return tokWh(value, decimals);\n } else {\n return toWh(value, decimals);\n }\n};\n\n// Power formatting has been moved to power.ts\n\n/**\n * Format energy according to EnergyFormat specification\n */\nexport const formatEnergy = (value: FieldValue, format: EnergyFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals ?? 1;\n\n // If a specific unit is provided, use it\n if (format.unit) {\n switch (format.unit) {\n case \"GWh\":\n return toGWh(numValue, decimals);\n case \"MWh\":\n return toMWh(numValue, decimals);\n case \"kWh\":\n return tokWh(numValue, decimals);\n case \"Wh\":\n return toWh(numValue, decimals);\n }\n }\n\n // Default to auto-scaling unless explicitly disabled\n if (format.autoScale !== false) {\n return autoScaleEnergy(numValue, decimals);\n }\n\n // If auto-scale is explicitly false and no unit specified, use base Wh\n return toWh(numValue, decimals);\n};\n\n// Electrical units have been moved to voltage.ts and current.ts\n// Resistance units (Ohms) could be moved to a separate resistance.ts if needed\n\n// Register energy and power formatters\nFormatRegistry.register(\"kWh\", (value) => {\n if (typeof value === \"number\") return tokWh(value);\n return null;\n});\n\n// Power formatters are now in power.ts\n\nFormatRegistry.register(\"autoScaleEnergy\", (value, decimals) => {\n if (typeof value === \"number\") {\n return autoScaleEnergy(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\n// Auto-scale power is now in power.ts\n\n// Register the energy formatter\n// biome-ignore lint/suspicious/noExplicitAny: Required for FormatRegistry type compatibility\nFormatRegistry.register(\"energy\", formatEnergy as any);\n","/**\n * Phone number formatting utilities\n */\n\nimport { FormatRegistry } from \"./registry\";\nimport type { FieldValue, FormattedValue, PhoneFormat } from \"./types\";\n\n/**\n * Format US phone number\n */\nexport const formatUSPhone = (phone: string | null | undefined): string | null => {\n if (!phone) return null;\n\n // Remove all non-digits\n const cleaned = phone.replace(/\\D/g, \"\");\n\n // Check if it's a valid US phone number (10 or 11 digits)\n if (cleaned.length === 10) {\n return cleaned.replace(/(\\d{3})(\\d{3})(\\d{4})/, \"($1) $2-$3\");\n } else if (cleaned.length === 11 && cleaned.startsWith(\"1\")) {\n return cleaned.replace(/1(\\d{3})(\\d{3})(\\d{4})/, \"+1 ($1) $2-$3\");\n }\n\n // Return original if not a valid format\n return phone;\n};\n\n/**\n * Format international phone number\n */\nexport const formatInternationalPhone = (phone: string | null | undefined): string | null => {\n if (!phone) return null;\n\n // Remove all non-digits except +\n const cleaned = phone.replace(/[^\\d+]/g, \"\");\n\n // If it starts with +, format as international\n if (cleaned.startsWith(\"+\")) {\n // Try to format common patterns\n if (cleaned.length === 12 && cleaned.startsWith(\"+1\")) {\n // US/Canada\n return cleaned.replace(/\\+1(\\d{3})(\\d{3})(\\d{4})/, \"+1 ($1) $2-$3\");\n } else if (cleaned.length === 13 && cleaned.startsWith(\"+44\")) {\n // UK\n return cleaned.replace(/\\+44(\\d{2})(\\d{4})(\\d{4})/, \"+44 $1 $2 $3\");\n }\n // Add spaces every 3-4 digits for other countries\n return cleaned.replace(/(\\+\\d{1,3})(\\d{3,4})(\\d{3,4})(\\d{3,4})?/, \"$1 $2 $3 $4\").trim();\n }\n\n // Default to US format if no country code\n return formatUSPhone(phone);\n};\n\n/**\n * Format phone number with basic formatting\n */\nexport const formatPhoneNumber = (phone: string | null | undefined): string | null => {\n if (!phone) return null;\n\n // Try to detect if it's international\n if (phone.startsWith(\"+\") || phone.length > 11) {\n return formatInternationalPhone(phone);\n }\n\n return formatUSPhone(phone);\n};\n\n/**\n * Format phone according to PhoneFormat specification\n */\nexport const formatPhone = (value: FieldValue, format: PhoneFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (value == null) return format.nullText ?? null;\n\n const phoneStr = String(value);\n\n if (format.international) {\n return formatInternationalPhone(phoneStr);\n }\n\n // Handle specific country formats if needed\n switch (format.country) {\n case \"US\":\n case \"CA\":\n return formatUSPhone(phoneStr);\n default:\n return formatPhoneNumber(phoneStr);\n }\n};\n\n// Register formatters\nFormatRegistry.register(\"phoneNumber\", (value) => {\n if (typeof value === \"string\") {\n return formatPhoneNumber(value);\n }\n return null;\n});\n\nFormatRegistry.register(\"usPhone\", (value) => {\n if (typeof value === \"string\") {\n return formatUSPhone(value);\n }\n return null;\n});\n\nFormatRegistry.register(\"internationalPhone\", (value) => {\n if (typeof value === \"string\") {\n return formatInternationalPhone(value);\n }\n return null;\n});\n","/**\n * Power formatting utilities (rate of energy transfer)\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { FieldValue, FormattedValue, PowerFormat } from \"./types\";\n\n/**\n * Format as Watts\n */\nexport const toWatts = (value: number | null | undefined, decimals: number = 0): string | null => {\n if (isNil(value)) return null;\n return decimals === 0 ? `${Math.round(value)} W` : `${value.toFixed(decimals)} W`;\n};\n\n/**\n * Format as kilowatts\n */\nexport const toKilowatts = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} kW`;\n};\n\n/**\n * Format as megawatts\n */\nexport const toMegawatts = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1_000_000).toFixed(decimals)} MW`;\n};\n\n/**\n * Format as gigawatts\n */\nexport const toGigawatts = (\n value: number | null | undefined,\n decimals: number = 2\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1_000_000_000).toFixed(decimals)} GW`;\n};\n\n/**\n * Auto-scale power to the most appropriate unit\n */\nexport const autoScalePower = (\n value: number | null | undefined,\n decimals?: number\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (absValue >= 1_000_000_000) {\n return toGigawatts(value, decimals ?? 2);\n } else if (absValue >= 1_000_000) {\n return toMegawatts(value, decimals ?? 1);\n } else if (absValue >= 1000) {\n return toKilowatts(value, decimals ?? 1);\n } else {\n return toWatts(value, decimals ?? 0);\n }\n};\n\n/**\n * Format power according to PowerFormat specification\n */\nexport const formatPower = (value: FieldValue, format: PowerFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals;\n\n // If a specific unit is provided, use it\n if (format.unit) {\n switch (format.unit) {\n case \"GW\":\n return toGigawatts(numValue, decimals ?? 2);\n case \"MW\":\n return toMegawatts(numValue, decimals ?? 1);\n case \"kW\":\n return toKilowatts(numValue, decimals ?? 1);\n case \"W\":\n return toWatts(numValue, decimals ?? 0);\n }\n }\n\n // Default to auto-scaling unless explicitly disabled\n if (format.autoScale !== false) {\n return autoScalePower(numValue, decimals);\n }\n\n // If auto-scale is explicitly false and no unit specified, use base watts\n return toWatts(numValue, decimals ?? 0);\n};\n\n// Register the formatter\n// biome-ignore lint/suspicious/noExplicitAny: Required for FormatRegistry type compatibility\nFormatRegistry.register(\"power\", formatPower as any);\n\n// Convenience exports with shorter names\nexport const toW = toWatts;\nexport const toKW = toKilowatts;\nexport const toMW = toMegawatts;\nexport const toGW = toGigawatts;\n","/**\n * Electrical resistance formatting utilities\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { FieldValue, FormattedValue, ResistanceFormat } from \"./types\";\n\n/**\n * Format as milliohms\n */\nexport const toMilliohms = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n const mOhms = value * 1000;\n return `${mOhms.toFixed(decimals)} mΩ`;\n};\n\n/**\n * Format as ohms\n */\nexport const toOhms = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} Ω`;\n};\n\n/**\n * Format as kilohms\n */\nexport const toKilohms = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} kΩ`;\n};\n\n/**\n * Format as megohms\n */\nexport const toMegohms = (\n value: number | null | undefined,\n decimals: number = 2\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1_000_000).toFixed(decimals)} MΩ`;\n};\n\n/**\n * Auto-scale resistance to the most appropriate unit\n */\nexport const autoScaleResistance = (\n value: number | null | undefined,\n decimals?: number\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (absValue >= 1_000_000) {\n return toMegohms(value, decimals ?? 2);\n } else if (absValue >= 1000) {\n return toKilohms(value, decimals ?? 1);\n } else if (absValue < 1) {\n return toMilliohms(value, decimals ?? 1);\n } else {\n return toOhms(value, decimals ?? 1);\n }\n};\n\n/**\n * Format resistance according to ResistanceFormat specification\n */\nexport const formatResistance = (value: FieldValue, format: ResistanceFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals;\n\n // If a specific unit is provided, use it\n if (format.unit) {\n switch (format.unit) {\n case \"MΩ\":\n return toMegohms(numValue, decimals ?? 2);\n case \"kΩ\":\n return toKilohms(numValue, decimals ?? 1);\n case \"mΩ\":\n return toMilliohms(numValue, decimals ?? 1);\n case \"Ω\":\n return toOhms(numValue, decimals ?? 1);\n }\n }\n\n // Default to auto-scaling unless explicitly disabled\n if (format.autoScale !== false) {\n return autoScaleResistance(numValue, decimals);\n }\n\n // If auto-scale is explicitly false and no unit specified, use base ohms\n return toOhms(numValue, decimals ?? 1);\n};\n\n// Register the formatter\n// biome-ignore lint/suspicious/noExplicitAny: Required for FormatRegistry type compatibility\nFormatRegistry.register(\"resistance\", formatResistance as any);\n\n// Register legacy shortcuts\nFormatRegistry.register(\"ohms\", (value) => {\n if (typeof value === \"number\") return toOhms(value);\n return null;\n});\n\nFormatRegistry.register(\"milliohms\", (value) => {\n if (typeof value === \"number\") return toMilliohms(value);\n return null;\n});\n","/**\n * Temperature formatting utilities\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type {\n FieldValue,\n FormattedValue,\n TemperatureFormat,\n TemperatureUnit,\n TemperatureUnitString,\n} from \"./types\";\n\n/**\n * Convert temperature unit string to symbol\n */\nexport const temperatureStringToSymbol = (unit: TemperatureUnitString): TemperatureUnit => {\n switch (unit) {\n case \"FAHRENHEIT\":\n return \"F\";\n case \"CELSIUS\":\n return \"C\";\n case \"KELVIN\":\n return \"K\";\n default:\n return \"F\";\n }\n};\n\n/**\n * Format as Fahrenheit\n */\nexport const toFahrenheit = (\n value: number | null | undefined,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)}°F`;\n};\n\n/**\n * Format as Celsius\n */\nexport const toCelsius = (\n value: number | null | undefined,\n fromFahrenheit: boolean = true,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n const celsius = fromFahrenheit ? (value - 32) * (5 / 9) : value;\n return `${celsius.toFixed(decimals)}°C`;\n};\n\n/**\n * Format as Kelvin\n */\nexport const toKelvin = (\n value: number | null | undefined,\n fromFahrenheit: boolean = true,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n const kelvin = fromFahrenheit ? (value - 32) * (5 / 9) + 273.15 : value + 273.15;\n return `${kelvin.toFixed(decimals)}K`;\n};\n\n/**\n * Convert Celsius to Fahrenheit\n */\nexport const celsiusToFahrenheit = (celsius: number): number => {\n return (celsius * 9) / 5 + 32;\n};\n\n/**\n * Convert Fahrenheit to Celsius\n */\nexport const fahrenheitToCelsius = (fahrenheit: number): number => {\n return (fahrenheit - 32) * (5 / 9);\n};\n\n/**\n * Convert Celsius to Kelvin\n */\nexport const celsiusToKelvin = (celsius: number): number => {\n return celsius + 273.15;\n};\n\n/**\n * Convert Kelvin to Celsius\n */\nexport const kelvinToCelsius = (kelvin: number): number => {\n return kelvin - 273.15;\n};\n\n/**\n * Convert Fahrenheit to Kelvin\n */\nexport const fahrenheitToKelvin = (fahrenheit: number): number => {\n return fahrenheitToCelsius(fahrenheit) + 273.15;\n};\n\n/**\n * Convert Kelvin to Fahrenheit\n */\nexport const kelvinToFahrenheit = (kelvin: number): number => {\n return celsiusToFahrenheit(kelvinToCelsius(kelvin));\n};\n\n/**\n * Format temperature with specified unit\n */\nexport const toTemperature = (\n value: number | null | undefined,\n unit: TemperatureUnit | TemperatureUnitString = \"F\",\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n\n const normalizedUnit =\n typeof unit === \"string\" && unit.length > 1\n ? temperatureStringToSymbol(unit as TemperatureUnitString)\n : (unit as TemperatureUnit);\n\n switch (normalizedUnit) {\n case \"C\":\n return toCelsius(value, true, decimals);\n case \"K\":\n return toKelvin(value, true, decimals);\n case \"F\":\n default:\n return toFahrenheit(value, decimals);\n }\n};\n\n/**\n * Format temperature according to TemperatureFormat specification\n */\nexport const formatTemperature = (value: FieldValue, format: TemperatureFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals ?? 0;\n const unit = format.unit ?? \"F\";\n\n if (format.showUnit === false) {\n const normalizedUnit =\n typeof unit === \"string\" && unit.length > 1\n ? temperatureStringToSymbol(unit as TemperatureUnitString)\n : (unit as TemperatureUnit);\n\n switch (normalizedUnit) {\n case \"C\": {\n const celsius = (numValue - 32) * (5 / 9);\n return celsius.toFixed(decimals);\n }\n case \"K\": {\n const kelvin = (numValue - 32) * (5 / 9) + 273.15;\n return kelvin.toFixed(decimals);\n }\n case \"F\":\n default:\n return numValue.toFixed(decimals);\n }\n }\n\n return toTemperature(numValue, unit, decimals);\n};\n\n// Register temperature formatters\nFormatRegistry.register(\"temperature\", (value, unit, decimals) => {\n if (typeof value === \"number\") {\n return toTemperature(\n value,\n typeof unit === \"string\" ? (unit as TemperatureUnit | TemperatureUnitString) : \"F\",\n typeof decimals === \"number\" ? decimals : 0\n );\n }\n return null;\n});\n\nFormatRegistry.register(\"fahrenheit\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toFahrenheit(value, typeof decimals === \"number\" ? decimals : 0);\n }\n return null;\n});\n\nFormatRegistry.register(\"celsius\", (value, fromFahrenheit, decimals) => {\n if (typeof value === \"number\") {\n return toCelsius(\n value,\n typeof fromFahrenheit === \"boolean\" ? fromFahrenheit : true,\n typeof decimals === \"number\" ? decimals : 0\n );\n }\n return null;\n});\n\nFormatRegistry.register(\"kelvin\", (value, fromFahrenheit, decimals) => {\n if (typeof value === \"number\") {\n return toKelvin(\n value,\n typeof fromFahrenheit === \"boolean\" ? fromFahrenheit : true,\n typeof decimals === \"number\" ? decimals : 0\n );\n }\n return null;\n});\n","/**\n * Text formatting utilities\n */\n\nimport { FormatRegistry } from \"./registry\";\nimport type { FieldValue, FormattedValue, TextFormat } from \"./types\";\n\n/**\n * Check if a value should be hidden based on format rules\n */\nconst shouldHideValue = (\n value: FieldValue,\n format: { hideWhenNull?: boolean; hideWhenZero?: boolean }\n): boolean => {\n if (format.hideWhenNull && (value === null || value === undefined)) {\n return true;\n }\n if (format.hideWhenZero && value === 0) {\n return true;\n }\n return false;\n};\n\n/**\n * Convert text to uppercase\n */\nexport const toUpperCase = (text: string | null | undefined): string => {\n return text?.toUpperCase() ?? \"\";\n};\n\n/**\n * Convert text to lowercase\n */\nexport const toLowerCase = (text: string | null | undefined): string => {\n return text?.toLowerCase() ?? \"\";\n};\n\n/**\n * Convert text to sentence case (first letter capitalized, rest lowercase).\n *\n * @param text - Text to convert\n * @returns Sentence-cased text\n *\n * @example\n * ```typescript\n * toSentenceCase(\"HELLO WORLD\"); // \"Hello world\"\n * toSentenceCase(\"hello world\"); // \"Hello world\"\n * ```\n */\nexport const toSentenceCase = (text: string | null | undefined): string => {\n if (!text) return \"\";\n return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();\n};\n\n/**\n * Convert text to title case with proper handling of articles and prepositions.\n * Capitalizes the first letter of each word except common articles/prepositions\n * (unless they're the first word).\n *\n * @param text - Text to convert\n * @returns Title-cased text\n *\n * @example\n * ```typescript\n * toTitleCase(\"the quick brown fox\"); // \"The Quick Brown Fox\"\n * toTitleCase(\"war and peace\"); // \"War and Peace\"\n * toTitleCase(\"to be or not to be\"); // \"To Be or Not to Be\"\n * ```\n */\nexport const toTitleCase = (text: string | null | undefined): string => {\n if (!text) return \"\";\n const articles = new Set([\n \"a\",\n \"an\",\n \"the\",\n \"and\",\n \"but\",\n \"or\",\n \"for\",\n \"nor\",\n \"on\",\n \"at\",\n \"of\",\n \"to\",\n \"with\",\n \"in\",\n \"as\",\n \"by\",\n ]);\n\n return text\n .toLowerCase()\n .split(/\\s+/)\n .map((word, index) =>\n articles.has(word) && index !== 0 ? word : word.charAt(0).toUpperCase() + word.slice(1)\n )\n .join(\" \");\n};\n\n/**\n * Capitalize first letter of each word\n */\nexport const capitalize = (text: string | null | undefined): string => {\n if (!text) return \"\";\n return text\n .split(/\\s+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\" \");\n};\n\n/**\n * Uppercase first letter only\n */\nexport const ucFirst = (text: string | null | undefined): string => {\n if (!text) return \"\";\n return text.charAt(0).toUpperCase() + text.slice(1);\n};\n\n/**\n * Convert camelCase to words\n */\nexport const camelCaseToWords = (text: string | null | undefined): string => {\n if (!text) return \"\";\n return text\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (str) => str.toUpperCase())\n .trim();\n};\n\n/**\n * Convert snake_case to words\n */\nexport const snakeCaseToWords = (text: string | null | undefined): string => {\n if (!text) return \"\";\n return text\n .toLowerCase()\n .split(\"_\")\n .map((word) => ucFirst(word))\n .join(\" \");\n};\n\n/**\n * Convert enum-style text to sentence case\n */\nexport const enumToSentenceCase = (text: string | null | undefined): string => {\n if (!text) return \"\";\n\n // Handle snake_case\n if (text.includes(\"_\")) {\n return snakeCaseToWords(text);\n }\n\n // Handle SCREAMING_CASE\n if (text.toUpperCase() === text) {\n return ucFirst(text.toLowerCase());\n }\n\n // Handle camelCase\n return camelCaseToWords(text);\n};\n\n/**\n * Truncate text in the middle\n */\nexport const truncateMiddle = (value: string | null | undefined, length: number = 16): string => {\n if (!value) return \"\";\n\n // Handle invalid length\n if (length < 5) return value;\n\n // Handle case where specified length is longer than string\n if (value.length <= length) return value;\n\n const totalChars = length - 3; // Account for ...\n const leadingChars = Math.ceil(totalChars / 2);\n const trailingChars = Math.floor(totalChars / 2);\n\n return `${value.slice(0, leadingChars)}...${value.slice(-trailingChars)}`;\n};\n\n/**\n * Truncate text at the start\n */\nexport const truncateStart = (value: string | null | undefined, length: number = 8): string => {\n if (!value) return \"\";\n if (value.length <= length) return value;\n return `...${value.slice(-length)}`;\n};\n\n/**\n * Truncate text at the end\n */\nexport const truncateEnd = (\n value: string | null | undefined,\n length: number = 16,\n ellipsis: string = \"...\"\n): string => {\n if (!value) return \"\";\n if (value.length <= length) return value;\n return value.slice(0, length) + ellipsis;\n};\n\n/**\n * Mask sensitive text (e.g., secrets, API keys)\n */\nexport const toSecret = (value: string | null | undefined): string => {\n if (!value) return \"\";\n const str = value.toString();\n const lastFour = str.slice(-4);\n const maskedLength = str.length - 4;\n return maskedLength > 0 ? \"*\".repeat(maskedLength) + lastFour : str;\n};\n\n/**\n * Format text according to TextFormat specification\n */\nexport const formatText = (value: FieldValue, format: TextFormat): FormattedValue => {\n if (shouldHideValue(value, format)) return null;\n if (value == null) return format.nullText ?? null;\n\n let formatted = String(value);\n\n // Apply transforms\n if (format.transform) {\n const transforms = Array.isArray(format.transform) ? format.transform : [format.transform];\n\n transforms.forEach((transform) => {\n switch (transform) {\n case \"uppercase\":\n formatted = toUpperCase(formatted);\n break;\n case \"lowercase\":\n formatted = toLowerCase(formatted);\n break;\n case \"capitalize\":\n formatted = capitalize(formatted);\n break;\n case \"titleCase\":\n formatted = toTitleCase(formatted);\n break;\n case \"sentenceCase\":\n formatted = toSentenceCase(formatted);\n break;\n }\n });\n }\n\n // Apply truncation\n if (format.truncate) {\n const { length, position, ellipsis = \"...\" } = format.truncate;\n switch (position) {\n case \"start\":\n formatted = truncateStart(formatted, length);\n break;\n case \"middle\":\n formatted = truncateMiddle(formatted, length);\n break;\n case \"end\":\n formatted = truncateEnd(formatted, length, ellipsis);\n break;\n }\n }\n\n return formatted;\n};\n\n// Register text formatters\nFormatRegistry.register(\"uppercase\", (value) => toUpperCase(String(value)));\nFormatRegistry.register(\"lowercase\", (value) => toLowerCase(String(value)));\nFormatRegistry.register(\"sentenceCase\", (value) => toSentenceCase(String(value)));\nFormatRegistry.register(\"titleCase\", (value) => toTitleCase(String(value)));\nFormatRegistry.register(\"capitalize\", (value) => capitalize(String(value)));\nFormatRegistry.register(\"camelCaseToWords\", (value) => camelCaseToWords(String(value)));\nFormatRegistry.register(\"snakeCaseToWords\", (value) => snakeCaseToWords(String(value)));\nFormatRegistry.register(\"enumToSentenceCase\", (value) => enumToSentenceCase(String(value)));\nFormatRegistry.register(\"truncateMiddle\", (value, length) =>\n truncateMiddle(String(value), typeof length === \"number\" ? length : 16)\n);\nFormatRegistry.register(\"truncateStart\", (value, length) =>\n truncateStart(String(value), typeof length === \"number\" ? length : 8)\n);\nFormatRegistry.register(\"truncateEnd\", (value, length, ellipsis) =>\n truncateEnd(\n String(value),\n typeof length === \"number\" ? length : 16,\n typeof ellipsis === \"string\" ? ellipsis : \"...\"\n )\n);\nFormatRegistry.register(\"secret\", (value) => toSecret(String(value)));\n","/**\n * Voltage formatting utilities (electrical potential)\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { FieldValue, FormattedValue, VoltageFormat } from \"./types\";\n\n/**\n * Format as millivolts\n */\nexport const toMillivolts = (\n value: number | null | undefined,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n const mV = value * 1000;\n return decimals === 0 ? `${Math.round(mV)} mV` : `${mV.toFixed(decimals)} mV`;\n};\n\n/**\n * Format as volts\n */\nexport const toVolts = (value: number | null | undefined, decimals: number = 0): string | null => {\n if (isNil(value)) return null;\n return decimals === 0 ? `${Math.round(value)} V` : `${value.toFixed(decimals)} V`;\n};\n\n/**\n * Format as kilovolts\n */\nexport const toKilovolts = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} kV`;\n};\n\n/**\n * Auto-scale voltage to the most appropriate unit\n */\nexport const autoScaleVoltage = (\n value: number | null | undefined,\n decimals?: number\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (absValue >= 1000) {\n return toKilovolts(value, decimals ?? 1);\n } else if (absValue < 1) {\n return toMillivolts(value, decimals ?? 0);\n } else {\n return toVolts(value, decimals ?? 0);\n }\n};\n\n/**\n * Format voltage according to VoltageFormat specification\n */\nexport const formatVoltage = (value: FieldValue, format: VoltageFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals;\n\n // If a specific unit is provided, use it\n if (format.unit) {\n switch (format.unit) {\n case \"kV\":\n return toKilovolts(numValue, decimals ?? 1);\n case \"mV\":\n return toMillivolts(numValue, decimals ?? 0);\n case \"V\":\n return toVolts(numValue, decimals ?? 0);\n }\n }\n\n // Default to auto-scaling unless explicitly disabled\n if (format.autoScale !== false) {\n return autoScaleVoltage(numValue, decimals);\n }\n\n // If auto-scale is explicitly false and no unit specified, use base volts\n return toVolts(numValue, decimals ?? 0);\n};\n\n// Register the formatter\n// biome-ignore lint/suspicious/noExplicitAny: Required for FormatRegistry type compatibility\nFormatRegistry.register(\"voltage\", formatVoltage as any);\n\n// Convenience exports with shorter names\nexport const toMV = toMillivolts;\nexport const toV = toVolts;\nexport const toKV = toKilovolts;\n","/**\n * Comprehensive formatting utilities for the Edges design system\n *\n * This module provides a unified formatting system with support for:\n * - Text formatting (case conversion, truncation, etc.)\n * - Number formatting (decimals, thousands separators, compact notation)\n * - Currency formatting (multiple currencies and display options)\n * - Date formatting (relative time, custom formats, timezones)\n * - Boolean formatting (custom true/false text)\n * - Energy units (Wh, kWh, MWh, GWh with auto-scaling)\n * - Temperature units (Celsius, Fahrenheit, Kelvin)\n * - Distance units (meters, kilometers, miles, feet)\n * - Phone number formatting (US and international)\n * - Custom formatters via the FormatRegistry\n */\n\nexport * from \"./boolean\";\nexport * from \"./capacity\";\nexport * from \"./component-formatter\";\nexport * from \"./current\";\nexport * from \"./date\";\nexport * from \"./distance\";\nexport * from \"./energy\";\nexport * from \"./number\";\nexport * from \"./phone\";\nexport * from \"./power\";\n// Export the registry\nexport { FormatRegistry } from \"./registry\";\nexport * from \"./resistance\";\nexport * from \"./temperature\";\n// Export all formatting utilities\nexport * from \"./text\";\n// Export all types\nexport * from \"./types\";\nexport * from \"./voltage\";\n\nimport { formatBoolean } from \"./boolean\";\nimport { formatCurrent } from \"./current\";\nimport { formatDate } from \"./date\";\nimport { formatDistance } from \"./distance\";\nimport { formatEnergy } from \"./energy\";\nimport { formatCurrency, formatNumber, formatPercent } from \"./number\";\nimport { formatPhone } from \"./phone\";\nimport { formatPower } from \"./power\";\nimport { formatResistance } from \"./resistance\";\nimport { formatTemperature } from \"./temperature\";\nimport { formatText } from \"./text\";\n// Import types for the main formatting function\nimport type {\n CustomFormat,\n FieldFormat,\n FieldValue,\n FormattedValue,\n PercentageFormat,\n} from \"./types\";\nimport { formatVoltage } from \"./voltage\";\n\n/**\n * Format a value as a percentage\n * Internal helper for the percentage format type\n */\nconst formatPercentage = (value: FieldValue, format: PercentageFormat): FormattedValue => {\n if (value == null) return format.nullText ?? null;\n if (format.hideWhenNull && value === null) return null;\n\n const num = typeof value === \"number\" ? value : Number(value);\n if (Number.isNaN(num)) return format.nullText ?? null;\n\n return formatPercent(num, format.decimals ?? 0);\n};\n\n/**\n * Main formatting function that routes to the appropriate formatter\n * based on the format type\n *\n * @param value - The value to format\n * @param format - The format specification\n * @returns The formatted value or null\n *\n * @example\n * ```typescript\n * // Format as currency\n * formatFieldValue(1234.56, { type: \"currency\", currency: \"USD\" })\n * // Returns: \"$1,234.56\"\n *\n * // Format as relative time\n * formatFieldValue(new Date(), { type: \"date\", relative: true })\n * // Returns: \"just now\"\n *\n * // Format with custom formatter\n * formatFieldValue(\"hello\", {\n * type: \"custom\",\n * formatter: (val) => String(val).toUpperCase()\n * })\n * // Returns: \"HELLO\"\n * ```\n */\nexport const formatFieldValue = (value: FieldValue, format: FieldFormat): FormattedValue => {\n switch (format.type) {\n case \"text\":\n return formatText(value, format);\n case \"number\":\n return formatNumber(value, format);\n case \"percentage\":\n return formatPercentage(value, format);\n case \"currency\":\n return formatCurrency(value, format);\n case \"date\":\n return formatDate(value, format);\n case \"boolean\":\n return formatBoolean(value, format);\n case \"energy\":\n return formatEnergy(value, format);\n case \"power\":\n return formatPower(value, format);\n case \"voltage\":\n return formatVoltage(value, format);\n case \"current\":\n return formatCurrent(value, format);\n case \"resistance\":\n return formatResistance(value, format);\n case \"temperature\":\n return formatTemperature(value, format);\n case \"distance\":\n return formatDistance(value, format);\n case \"phone\":\n return formatPhone(value, format);\n case \"custom\": {\n const customFormat = format as CustomFormat;\n if (customFormat.hideWhenNull && (value === null || value === undefined)) {\n return null;\n }\n if (value == null) return customFormat.nullText ?? null;\n return customFormat.formatter(value, customFormat.options);\n }\n default:\n // Fallback to string conversion\n return value != null ? String(value) : null;\n }\n};\n\n/**\n * Convenience function to create a format object\n *\n * @example\n * ```typescript\n * const currencyFormat = createFormat(\"currency\", { currency: \"EUR\" });\n * const dateFormat = createFormat(\"date\", { relative: true });\n * ```\n */\nexport const createFormat = <T extends FieldFormat[\"type\"]>(\n type: T,\n options?: Omit<Extract<FieldFormat, { type: T }>, \"type\">\n): Extract<FieldFormat, { type: T }> => {\n return { type, ...options } as Extract<FieldFormat, { type: T }>;\n};\n","import { scaleLinear, scaleTime } from \"@visx/scale\";\nimport { extent, max, min } from \"d3-array\";\nimport type { YFormatType } from \"../context/ChartContext\";\nimport { formatComponentValue } from \"./formatting\";\n\nexport type { YFormatType };\n\nexport interface BaseDataPoint {\n xValue: Date;\n yValue: number;\n category?: string;\n}\n\nexport interface ChartMargin {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport const defaultMargin: ChartMargin = {\n top: 0,\n right: 0,\n bottom: 50,\n left: 60,\n};\n\nexport interface YFormatSettings {\n format: (value: number) => string;\n min?: number;\n max?: number;\n tickInterval?: number;\n tickFormat?: (value: number) => string;\n}\n\n/**\n * Get Y-axis format settings from a ComponentFormatter\n * Uses the main formatting system for consistency across all components\n */\nexport function getYFormatSettings(formatter: YFormatType = { type: \"number\" }): YFormatSettings {\n const safeFormat = (value: number | null | undefined): string => {\n if (value == null) return \"-\";\n const result = formatComponentValue({ value, formatter });\n // formatComponentValue returns ReactNode, convert to string\n if (result === null) return \"-\";\n if (typeof result === \"string\") return result;\n if (typeof result === \"number\") return result.toString();\n // For React elements, try to extract text content if possible\n // This handles the case where formatComponentValue returns JSX with units\n if (typeof result === \"object\" && result !== null && \"props\" in result) {\n // Extract text from React element children\n const extractText = (node: unknown): string => {\n if (node == null) return \"\";\n if (typeof node === \"string\") return node;\n if (typeof node === \"number\") return node.toString();\n if (typeof node === \"object\" && \"props\" in node) {\n const props = (node as { props?: { children?: unknown } }).props;\n if (props?.children) {\n if (Array.isArray(props.children)) {\n return props.children.map(extractText).join(\"\");\n }\n return extractText(props.children);\n }\n }\n return \"\";\n };\n const text = extractText(result);\n return text || value.toString();\n }\n // Fallback to raw value for chart axes\n return value.toString();\n };\n\n // Create a simplified tick format for axis labels (less verbose)\n const tickFormat = (value: number | null | undefined): string => {\n if (value == null) return \"-\";\n\n // Handle string shorthand formatters\n if (typeof formatter === \"string\") {\n const result = formatComponentValue({ value, formatter });\n if (result === null) return \"-\";\n return String(result);\n }\n\n // For specific format types, provide concise axis labels\n if (typeof formatter === \"object\" && formatter.type) {\n switch (formatter.type) {\n case \"energy\":\n case \"power\":\n case \"voltage\":\n case \"current\":\n case \"resistance\":\n case \"temperature\":\n case \"distance\":\n // These formatters include units, which is good for axes\n return safeFormat(value);\n\n case \"currency\":\n // For currency, just use the standard format\n return safeFormat(value);\n\n default:\n return safeFormat(value);\n }\n }\n\n return safeFormat(value);\n };\n\n // Determine min/max/intervals based on format type\n let min: number | undefined;\n let max: number | undefined;\n let tickInterval: number | undefined;\n\n if (typeof formatter === \"object\" && formatter.type) {\n switch (formatter.type) {\n case \"number\":\n if (\"min\" in formatter) min = formatter.min as number | undefined;\n if (\"max\" in formatter) max = formatter.max as number | undefined;\n break;\n }\n }\n\n return {\n format: safeFormat,\n tickFormat,\n min,\n max,\n tickInterval,\n };\n}\n\nexport const createXScale = (data: BaseDataPoint[], width: number) => {\n const dateExtent = extent(data, (d) => d.xValue) as [Date, Date];\n return scaleTime({\n range: [defaultMargin.left, width - defaultMargin.right],\n domain: dateExtent,\n nice: true,\n });\n};\n\nexport const createYScale = (data: BaseDataPoint[], height: number, formatType: YFormatType) => {\n const yFormatSettings = getYFormatSettings(formatType);\n const dataYMin = min(data, (d) => d.yValue) || 0;\n const dataYMax = max(data, (d) => d.yValue) || 0;\n const yMin =\n yFormatSettings.min !== undefined\n ? yFormatSettings.min\n : dataYMin >= 0\n ? 0 // 0 if all positive values, min is 0\n : dataYMin * 1.1; // else scale the negative values by 10% to make room for the y-axis values\n const yMax =\n yFormatSettings.max !== undefined\n ? yFormatSettings.max\n : dataYMax <= 0\n ? 0 // If all values are negative, max is 0\n : dataYMax * 1.1; // else scale the positive values by 10% to make room for the y-axis values\n return scaleLinear({\n range: [height - defaultMargin.bottom, defaultMargin.top],\n domain: [yMin, yMax],\n nice: true,\n });\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/Logo/Logo.tsx","../src/components/SideNav/SideNav.tsx","../src/components/Icon/IconSSR.tsx","../src/components/TopNav/TopNav.tsx","../src/components/AppShell/AppShell.tsx","../src/components/Avatar/Avatar.tsx","../src/components/Heading/Heading.tsx","../src/components/Loader/Loader.tsx","../src/components/TextLink/TextLink.tsx","../src/config/entities.ts","../src/utils/colors.ts","../src/utils/formatting/registry.ts","../src/utils/formatting/boolean.ts","../src/utils/formatting/number.ts","../src/utils/formatting/component-formatter.tsx","../src/utils/formatting/current.ts","../src/utils/formatting/date.ts","../src/utils/formatting/distance.ts","../src/utils/formatting/energy.ts","../src/utils/formatting/phone.ts","../src/utils/formatting/power.ts","../src/utils/formatting/resistance.ts","../src/utils/formatting/temperature.ts","../src/utils/formatting/text.ts","../src/utils/formatting/voltage.ts","../src/utils/formatting/index.ts","../src/utils/charts.ts"],"names":["Logo","className","showWordmark","width","fill","fillValue","fillClass","logoWidth","logoHeight","jsxs","jsx","SideNav","topItems","bottomItems","bottomContent","logo","showLogo","LinkComponent","mobileMenuId","sidebarCollapseId","isSectionFormat","items","normalizeToSections","renderSection","section","sectionIndex","totalSections","item","renderNavItem","isNested","categoryId","child","linkProps","linkContent","Fragment","index","sections","sizePresets","IconSSR","memo","name","size","color","weight","ariaLabel","props","IconComponent","PhosphorIconsSSR","resolvedSize","iconClassName","twMerge","IconSSRWithContainer","variant","shape","containerSize","containerClassName","ref","iconSize","resolvedContainerSize","containerClasses","TopNav","rightContent","centerContent","showMobileMenu","avatar","showColorModeSwitcher","toggleTheme","isDarkThemeEnabled","colorMode","actions","getThemeIcon","getAriaLabel","AppShell","sideNav","topNav","children","contentPaddingX","contentPaddingY","showSidebarBorder","mainClassName","enableJsEnhancements","Avatar","src","alt","firstName","lastName","fullName","onClick","status","bordered","sizeClasses","statusSizeClasses","statusPositionClasses","statusColors","variantColors","shapeClasses","baseClasses","initials","first","last","parts","getIcon","Users","Building2","User","renderAvatar","sizeVariants","heightVariants","Heading","Tag","height","heightClasses","Loader","TextLink","href","external","title","asButton","onPress","showArrow","externalProps","combinedClasses","content","ENTITY_CONFIG","getEntityConfig","entityType","getEntityIcon","getEntityLabel","plural","colorCache","getResolvedColor","variableName","fallback","varName","root","value","tempElement","resolvedColor","error","clearColorCache","getThemeCategoricalColors","colors","i","getDefaultColors","getDefaultChartColor","createCategoryColorMap","categories","customColors","colorMap","themeColors","category","isLightColor","rgb","g","b","getContrastingTextColor","backgroundColor","FormatRegistryClass","__publicField","key","formatter","args","FormatRegistry","toBoolean","trueText","falseText","toEnabledDisabled","toOnOff","toActiveInactive","toTrueFalse","toCheckmark","parseBoolean","lower","formatBoolean","format","boolValue","isNil","toPercentage","decimals","formatPercent","precision","toInteger","toFloat","toFormattedNumber","thousandsSeparator","options","toCompactNumber","display","toScientificNotation","toCurrency","currency","formatOptions","formatNumber","numValue","formatCurrency","formatComponentValue","emptyClassName","emptyText","formatted","formatFieldValue","toMilliamps","mA","toAmps","toKiloamps","autoScaleCurrent","absValue","formatCurrent","toDateTime","DateTime","dt","toDateString","showTime","timezone","dtWithZone","toRelativeTime","toFullDateTime","toISOString","toCustomDateFormat","formatDate","toMeters","toCentimeters","toMillimeters","toKilometers","toFeet","toInches","toMiles","toYards","milesToFeet","miles","autoScaleDistance","metric","formatDistance","isMetric","toWh","tokWh","toMWh","toGWh","autoScaleEnergy","formatEnergy","formatUSPhone","phone","cleaned","formatInternationalPhone","formatPhoneNumber","formatPhone","phoneStr","toWatts","toKilowatts","toMegawatts","toGigawatts","autoScalePower","formatPower","toMilliohms","toOhms","toKilohms","toMegohms","autoScaleResistance","formatResistance","temperatureStringToSymbol","unit","toFahrenheit","toCelsius","fromFahrenheit","toKelvin","toTemperature","formatTemperature","shouldHideValue","toUpperCase","text","toLowerCase","toSentenceCase","toTitleCase","articles","word","capitalize","ucFirst","camelCaseToWords","str","snakeCaseToWords","enumToSentenceCase","truncateMiddle","length","totalChars","leadingChars","trailingChars","truncateStart","truncateEnd","ellipsis","toSecret","lastFour","maskedLength","formatText","transform","position","toMillivolts","mV","toVolts","toKilovolts","autoScaleVoltage","formatVoltage","formatPercentage","num","customFormat","defaultMargin","getYFormatSettings","safeFormat","result","extractText","node","tickFormat","min","max","tickInterval","createXScale","data","dateExtent","extent","d","scaleTime","createYScale","formatType","yFormatSettings","dataYMin","dataYMax","yMin","yMax","scaleLinear"],"mappings":"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","file":"server.js","sourcesContent":["export interface LogoProps {\n className?: string;\n showWordmark?: boolean;\n width?: number;\n fill?: string;\n}\n\n/**\n * Logo\n *\n * Brand logo component with optional wordmark.\n * Supports customizable sizing and fill colors with theme-aware defaults.\n */\nexport const Logo = ({ className, showWordmark = true, width, fill }: LogoProps) => {\n // Support both fill prop and className for backward compatibility\n // Priority: fill prop > className > default (theme-aware text color)\n\n // Determine the fill value\n let fillValue: string | undefined;\n let fillClass: string | undefined;\n\n if (fill) {\n // If fill starts with \"fill-\", it's a Tailwind class\n if (fill.startsWith(\"fill-\")) {\n fillClass = fill;\n } else {\n // Otherwise, use it as a direct fill value\n fillValue = fill;\n }\n } else if (className) {\n // Use className if provided\n fillClass = className;\n } else {\n // Default to theme-aware text color using CSS variable\n fillValue = \"var(--color-text-body)\";\n }\n\n if (showWordmark) {\n const logoWidth = width || 270;\n const logoHeight = (logoWidth / 270) * 80; // Maintain aspect ratio\n\n return (\n <svg\n width={logoWidth}\n height={logoHeight}\n viewBox=\"0 0 270 80\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={fillClass}\n style={fillValue ? { fill: fillValue } : undefined}\n >\n <g clipPath=\"url(#clip0_796_283)\">\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M0.223654 20.2934C0.417233 19.8234 0.873598 19.517 1.37984 19.517H20.5909C21.282 19.517 21.8422 20.0798 21.8422 20.774V40.049C21.8422 40.5572 21.5375 41.0155 21.0702 41.2102C20.6028 41.405 20.0647 41.2977 19.7067 40.9385L0.495628 21.6635C0.137428 21.3041 0.030075 20.7633 0.223654 20.2934ZM4.40349 22.0311L19.3396 37.017V22.0311H4.40349Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 20.2934C38.8394 19.8234 39.2958 19.517 39.802 19.517H59.013C59.7041 19.517 60.2642 20.0798 60.2642 20.774V40.049C60.2642 40.5572 59.9597 41.0155 59.4923 41.2102C59.025 41.405 58.4867 41.2977 58.1289 40.9385L38.9178 21.6635C38.5595 21.3041 38.4522 20.7633 38.6458 20.2934ZM42.8255 22.0311L57.7618 37.017V22.0311H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M19.4347 58.8447C19.6283 58.3747 20.0847 58.0685 20.5909 58.0685H39.802C40.493 58.0685 41.0532 58.6312 41.0532 59.3255V78.6005C41.0532 79.1087 40.7486 79.567 40.2813 79.7617C39.8139 79.9562 39.2757 79.849 38.9178 79.49L19.7067 60.215C19.3485 59.8555 19.2411 59.3147 19.4347 58.8447ZM23.6146 60.5825L38.5508 75.5682V60.5825H23.6146Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 58.1643C39.79 57.9695 40.3283 58.0768 40.6861 58.436L59.8972 77.711C60.2555 78.0703 60.3628 78.6113 60.1692 79.081C59.9756 79.551 59.5192 79.8575 59.013 79.8575H39.802C39.1109 79.8575 38.5508 79.2948 38.5508 78.6005V59.3255C38.5508 58.8173 38.8554 58.359 39.3227 58.1643ZM41.0532 62.3575V77.3433H55.9893L41.0532 62.3575Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 19.6129C39.79 19.4182 40.3283 19.5254 40.6861 19.8846L59.8972 39.1595C60.2555 39.519 60.3628 40.0598 60.1692 40.5298C59.9756 40.9995 59.5192 41.306 59.013 41.306H39.802C39.1109 41.306 38.5508 40.7433 38.5508 40.049V20.7741C38.5508 20.2658 38.8554 19.8075 39.3227 19.6129ZM41.0532 23.8061V38.792H55.9893L41.0532 23.8061Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 38.8885C39.79 38.694 40.3283 38.8012 40.6861 39.1602L59.8972 58.4352C60.2555 58.7945 60.3628 59.3355 60.1692 59.8055C59.9756 60.2752 59.5192 60.5817 59.013 60.5817H39.802C39.1109 60.5817 38.5508 60.019 38.5508 59.3247V40.0497C38.5508 39.5415 38.8554 39.0832 39.3227 38.8885ZM41.0532 43.0817V58.0675H55.9893L41.0532 43.0817Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 39.569C38.8394 39.0992 39.2958 38.7927 39.802 38.7927H59.013C59.7041 38.7927 60.2642 39.3555 60.2642 40.0497V59.3247C60.2642 59.833 59.9597 60.2912 59.4923 60.486C59.025 60.6805 58.4867 60.5732 58.1289 60.2142L38.9178 40.9392C38.5595 40.5797 38.4522 40.039 38.6458 39.569ZM42.8255 41.3067L57.7618 56.2927V41.3067H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 58.8447C38.8394 58.3747 39.2958 58.0685 39.802 58.0685H59.013C59.7041 58.0685 60.2642 58.6312 60.2642 59.3255V78.6005C60.2642 79.1087 59.9597 79.567 59.4923 79.7617C59.025 79.9562 58.4867 79.849 58.1289 79.49L38.9178 60.215C38.5595 59.8555 38.4522 59.3147 38.6458 58.8447ZM42.8255 60.5825L57.7618 75.5682V60.5825H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M58.5338 19.6129C59.0011 19.4182 59.5394 19.5254 59.8972 19.8846L79.1083 39.1595C79.4666 39.519 79.5739 40.0598 79.3803 40.5298C79.1867 40.9995 78.7303 41.306 78.2241 41.306H59.013C58.322 41.306 57.7618 40.7433 57.7618 40.049V20.7741C57.7618 20.2658 58.0664 19.8075 58.5338 19.6129ZM60.2643 23.8061V38.792H75.2006L60.2643 23.8061Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M58.5338 0.338803C59.0011 0.144135 59.5394 0.251385 59.8972 0.610565L79.1083 19.8855C79.4666 20.2449 79.5739 20.7857 79.3803 21.2556C79.1867 21.7256 78.7303 22.032 78.2241 22.032H59.013C58.322 22.032 57.7618 21.4692 57.7618 20.775V1.50003C57.7618 0.99174 58.0664 0.533468 58.5338 0.338803ZM60.2643 4.53208V19.5179H75.2006L60.2643 4.53208Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M57.8569 20.2934C58.0505 19.8234 58.5069 19.517 59.013 19.517H78.2241C78.9151 19.517 79.4753 20.0798 79.4753 20.774V40.049C79.4753 40.5572 79.1707 41.0155 78.7034 41.2102C78.236 41.405 77.6978 41.2977 77.3399 40.9385L58.1289 21.6635C57.7705 21.3041 57.6633 20.7633 57.8569 20.2934ZM62.0365 22.0311L76.9729 37.017V22.0311H62.0365Z\"\n />\n <path d=\"M269.838 49.4457H249.005C249.266 51.801 250.162 53.6985 251.695 55.1377C253.225 56.577 255.134 57.2967 257.416 57.2967C259.307 57.2967 260.887 56.8715 262.159 56.021C263.463 55.1377 264.408 53.9927 264.996 52.5862H269.251C268.502 54.9415 267.084 56.937 264.996 58.5725C262.943 60.208 260.414 61.026 257.416 61.026C255.069 61.026 252.917 60.4697 250.961 59.3575C249.037 58.2127 247.504 56.6587 246.363 54.696C245.255 52.7332 244.7 50.558 244.7 48.17C244.7 45.782 245.255 43.6067 246.363 41.644C247.504 39.6812 249.037 38.1437 250.961 37.0315C252.917 35.8867 255.069 35.3142 257.416 35.3142C259.73 35.3142 261.833 35.8702 263.724 36.9825C265.615 38.0947 267.098 39.6485 268.176 41.644C269.283 43.6395 269.838 45.913 269.838 48.4645V49.4457ZM257.416 39.0432C255.263 39.0432 253.439 39.6812 251.939 40.957C250.47 42.2327 249.542 43.9337 249.152 46.06H265.583C265.192 43.9992 264.262 42.3145 262.796 41.006C261.36 39.6975 259.568 39.0432 257.416 39.0432Z\" />\n <path d=\"M228.356 60.5352V35.8049H232.219V39.7794H232.464C233.05 38.5689 233.963 37.5712 235.202 36.7862C236.474 35.9684 237.974 35.5594 239.701 35.5594H243.125V39.4359H239.701C237.517 39.4359 235.757 40.1554 234.42 41.5949C233.083 43.0342 232.414 44.9152 232.414 47.2377V60.5352H228.356Z\" />\n <path d=\"M208.607 61.0259C205.64 61.0259 203.326 60.1262 201.663 58.3272C200 56.4952 199.169 53.8947 199.169 50.5252V35.8047H203.228V49.8874C203.228 52.2427 203.766 54.0744 204.842 55.3829C205.95 56.6587 207.532 57.2967 209.586 57.2967C211.02 57.2967 212.308 56.9694 213.449 56.3152C214.623 55.6284 215.536 54.6959 216.188 53.5184C216.84 52.3407 217.166 50.9997 217.166 49.4949V35.8047H221.225V60.5352H217.313V56.5607H217.068C216.286 57.9019 215.161 58.9814 213.694 59.7992C212.226 60.6169 210.531 61.0259 208.607 61.0259Z\" />\n <path d=\"M186.736 39.534V56.806H194.756V60.5352H182.677V39.534H177.199V35.8047H182.677V29.5732H186.736V35.8047H193.24V39.534H186.736Z\" />\n <path d=\"M156.585 60.5352H151.988L158.394 48.0227L152.33 35.8047H156.976L162.062 46.0599H165.388L170.474 35.8047H175.022L168.958 48.0227L175.365 60.5352H170.67L165.29 49.7892H162.013L156.585 60.5352Z\" />\n <path d=\"M150.138 49.1315H129.304C129.565 51.4867 130.461 53.3842 131.994 54.8235C133.526 56.2627 135.433 56.9825 137.715 56.9825C139.606 56.9825 141.188 56.5572 142.459 55.7067C143.763 54.8235 144.709 53.6785 145.296 52.272H149.551C148.801 54.6272 147.382 56.6227 145.296 58.2582C143.242 59.8937 140.715 60.7118 137.715 60.7118C135.368 60.7118 133.216 60.1555 131.26 59.0432C129.336 57.8985 127.804 56.3445 126.663 54.3817C125.554 52.419 125 50.2437 125 47.8557C125 45.4677 125.554 43.2925 126.663 41.3298C127.804 39.367 129.336 37.8295 131.26 36.7173C133.216 35.5725 135.368 35 137.715 35C140.03 35 142.133 35.556 144.024 36.6682C145.915 37.7805 147.399 39.3342 148.475 41.3298C149.583 43.3252 150.138 45.5987 150.138 48.1502V49.1315ZM137.715 38.729C135.564 38.729 133.738 39.367 132.238 40.6427C130.771 41.9185 129.842 43.6195 129.45 45.7458H145.883C145.491 43.685 144.562 42.0002 143.095 40.6917C141.661 39.3832 139.867 38.729 137.715 38.729Z\" />\n <path d=\"M116.961 60.5353H112.559V30.4072H101.164V26.1875H128.307V30.4072H116.961V60.5353Z\" />\n </g>\n <defs>\n <clipPath id=\"clip0_796_283\">\n <rect width=\"270\" height=\"80\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n );\n }\n // Logo only\n const logoWidth = width || 80;\n const logoHeight = logoWidth; // Square logo maintains 1:1 aspect ratio\n\n return (\n <svg\n width={logoWidth}\n height={logoHeight}\n viewBox=\"0 0 80 80\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={fillClass}\n style={fillValue ? { fill: fillValue } : undefined}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M0.223654 20.2934C0.417233 19.8234 0.873598 19.517 1.37984 19.517H20.5909C21.282 19.517 21.8422 20.0798 21.8422 20.774V40.049C21.8422 40.5572 21.5375 41.0155 21.0702 41.2102C20.6028 41.405 20.0647 41.2977 19.7067 40.9385L0.495628 21.6635C0.137428 21.3041 0.030075 20.7633 0.223654 20.2934ZM4.40349 22.0311L19.3396 37.017V22.0311H4.40349Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 20.2934C38.8394 19.8234 39.2958 19.517 39.802 19.517H59.013C59.7041 19.517 60.2642 20.0798 60.2642 20.774V40.049C60.2642 40.5572 59.9597 41.0155 59.4923 41.2102C59.025 41.405 58.4867 41.2977 58.1289 40.9385L38.9178 21.6635C38.5595 21.3041 38.4522 20.7633 38.6458 20.2934ZM42.8255 22.0311L57.7618 37.017V22.0311H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M19.4347 58.8447C19.6283 58.3747 20.0847 58.0685 20.5909 58.0685H39.802C40.493 58.0685 41.0532 58.6312 41.0532 59.3255V78.6005C41.0532 79.1087 40.7486 79.567 40.2813 79.7617C39.8139 79.9562 39.2757 79.849 38.9178 79.49L19.7067 60.215C19.3485 59.8555 19.2411 59.3147 19.4347 58.8447ZM23.6146 60.5825L38.5508 75.5682V60.5825H23.6146Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 58.1643C39.79 57.9695 40.3283 58.0768 40.6861 58.436L59.8972 77.711C60.2555 78.0703 60.3628 78.6113 60.1692 79.081C59.9756 79.551 59.5192 79.8575 59.013 79.8575H39.802C39.1109 79.8575 38.5508 79.2948 38.5508 78.6005V59.3255C38.5508 58.8173 38.8554 58.359 39.3227 58.1643ZM41.0532 62.3575V77.3433H55.9893L41.0532 62.3575Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 19.6129C39.79 19.4182 40.3283 19.5254 40.6861 19.8846L59.8972 39.1595C60.2555 39.519 60.3628 40.0598 60.1692 40.5298C59.9756 40.9995 59.5192 41.306 59.013 41.306H39.802C39.1109 41.306 38.5508 40.7433 38.5508 40.049V20.7741C38.5508 20.2658 38.8554 19.8075 39.3227 19.6129ZM41.0532 23.8061V38.792H55.9893L41.0532 23.8061Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M39.3227 38.8885C39.79 38.694 40.3283 38.8012 40.6861 39.1602L59.8972 58.4352C60.2555 58.7945 60.3628 59.3355 60.1692 59.8055C59.9756 60.2752 59.5192 60.5817 59.013 60.5817H39.802C39.1109 60.5817 38.5508 60.019 38.5508 59.3247V40.0497C38.5508 39.5415 38.8554 39.0832 39.3227 38.8885ZM41.0532 43.0817V58.0675H55.9893L41.0532 43.0817Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 39.569C38.8394 39.0992 39.2958 38.7927 39.802 38.7927H59.013C59.7041 38.7927 60.2642 39.3555 60.2642 40.0497V59.3247C60.2642 59.833 59.9597 60.2912 59.4923 60.486C59.025 60.6805 58.4867 60.5732 58.1289 60.2142L38.9178 40.9392C38.5595 40.5797 38.4522 40.039 38.6458 39.569ZM42.8255 41.3067L57.7618 56.2927V41.3067H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M38.6458 58.8447C38.8394 58.3747 39.2958 58.0685 39.802 58.0685H59.013C59.7041 58.0685 60.2642 58.6312 60.2642 59.3255V78.6005C60.2642 79.1087 59.9597 79.567 59.4923 79.7617C59.025 79.9562 58.4867 79.849 58.1289 79.49L38.9178 60.215C38.5595 59.8555 38.4522 59.3147 38.6458 58.8447ZM42.8255 60.5825L57.7618 75.5682V60.5825H42.8255Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M58.5338 19.6129C59.0011 19.4182 59.5394 19.5254 59.8972 19.8846L79.1083 39.1595C79.4666 39.519 79.5739 40.0598 79.3803 40.5298C79.1867 40.9995 78.7303 41.306 78.2241 41.306H59.013C58.322 41.306 57.7618 40.7433 57.7618 40.049V20.7741C57.7618 20.2658 58.0664 19.8075 58.5338 19.6129ZM60.2643 23.8061V38.792H75.2006L60.2643 23.8061Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M58.5338 0.338803C59.0011 0.144135 59.5394 0.251385 59.8972 0.610565L79.1083 19.8855C79.4666 20.2449 79.5739 20.7857 79.3803 21.2556C79.1867 21.7256 78.7303 22.032 78.2241 22.032H59.013C58.322 22.032 57.7618 21.4692 57.7618 20.775V1.50003C57.7618 0.99174 58.0664 0.533468 58.5338 0.338803ZM60.2643 4.53208V19.5179H75.2006L60.2643 4.53208Z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M57.8569 20.2934C58.0505 19.8234 58.5069 19.517 59.013 19.517H78.2241C78.9151 19.517 79.4753 20.0798 79.4753 20.774V40.049C79.4753 40.5572 79.1707 41.0155 78.7034 41.2102C78.236 41.405 77.6978 41.2977 77.3399 40.9385L58.1289 21.6635C57.7705 21.3041 57.6633 20.7633 57.8569 20.2934ZM62.0365 22.0311L76.9729 37.017V22.0311H62.0365Z\"\n />\n </svg>\n );\n};\n","import * as React from \"react\";\nimport { Logo } from \"../Logo\";\n// Remove Icon import to avoid client-only code - using emoji/text placeholders for now\n// import { Icon, type IconName } from \"../Icon\";\n\nexport type SideNavItem = {\n id: string;\n label: string;\n href?: string; // Optional - if not provided and has children, becomes a category\n icon?: React.ReactNode;\n isActive?: boolean;\n isExpanded?: boolean; // For categories with children\n children?: SideNavItem[]; // If present, this becomes a category\n};\n\nexport type SideNavSection = {\n id: string;\n title?: string; // Optional section title\n items: SideNavItem[];\n};\n\nexport type SideNavProps = {\n topItems?: SideNavItem[] | SideNavSection[]; // Union type for backward compatibility\n bottomItems?: SideNavItem[];\n bottomContent?: React.ReactNode; // For app-specific content like WorkspaceSwitcher\n logo?: React.ReactNode;\n showLogo?: boolean;\n linkComponent?: React.ElementType;\n className?: string;\n mobileMenuId?: string;\n sidebarCollapseId?: string;\n};\n\n/**\n * SideNav\n *\n * Vertical navigation component for application sidebars.\n * Supports nested navigation items, sections, collapsible categories, and mobile-responsive behavior.\n */\nexport const SideNav: React.FC<SideNavProps> = ({\n topItems = [],\n bottomItems = [],\n bottomContent,\n logo,\n showLogo = true,\n linkComponent: LinkComponent = \"a\",\n className = \"\",\n mobileMenuId = \"app-mobile-menu\",\n sidebarCollapseId = \"app-sidebar-collapse\",\n}) => {\n // Helper function to determine if topItems is using the new section format\n const isSectionFormat = (items: SideNavItem[] | SideNavSection[]): items is SideNavSection[] => {\n return items.length > 0 && \"items\" in items[0];\n };\n\n // Helper function to normalize topItems to sections for consistent rendering\n const normalizeToSections = (items: SideNavItem[] | SideNavSection[]): SideNavSection[] => {\n if (isSectionFormat(items)) {\n return items;\n }\n // Convert plain items array to a single section\n return [{ id: \"default-section\", items: items }];\n };\n\n const renderSection = (\n section: SideNavSection,\n sectionIndex: number,\n totalSections: number\n ): React.ReactNode => {\n return (\n <div key={section.id} className=\"space-y-0.5\">\n {/* Optional section title */}\n {section.title && (\n <div\n className=\"px-6 py-1 text-xs font-medium text-text-subtle uppercase tracking-wider\"\n data-collapse-hide=\"\"\n >\n {section.title}\n </div>\n )}\n\n {/* Section items */}\n <div className=\"space-y-0.5\">{section.items.map((item) => renderNavItem(item))}</div>\n\n {/* Section separator - border between sections (but not after the last section) */}\n {sectionIndex < totalSections - 1 && (\n <div className=\"border-b border-border-subtle mx-6 my-2\" data-collapse-hide=\"\" />\n )}\n </div>\n );\n };\n\n const renderNavItem = (item: SideNavItem, isNested = false): React.ReactNode => {\n // If item has children, render as category\n if (item.children && item.children.length > 0) {\n const categoryId = `category-${item.id}`;\n return (\n <div key={item.id} className=\"group/category\">\n {/* Hidden checkbox for expand/collapse state */}\n <input\n type=\"checkbox\"\n id={categoryId}\n className=\"peer/category hidden\"\n defaultChecked={item.isExpanded}\n aria-hidden=\"true\"\n />\n\n {/* Category header - acts as label for checkbox */}\n <label\n htmlFor={categoryId}\n className=\"flex items-center gap-3 px-6 py-1 text-text-body hover:bg-background-hover hover:text-text-heading cursor-pointer transition-all duration-200\"\n data-collapse-center=\"\"\n >\n {item.icon && (\n <span\n className=\"flex-shrink-0 w-3.5 h-3.5 flex items-center justify-center transition-all duration-200\"\n data-collapse-icon=\"\"\n >\n {item.icon}\n </span>\n )}\n <span className=\"transition-all duration-200\" data-collapse-hide=\"\">\n {item.label}\n </span>\n {/* Spacer to push chevron to the right */}\n <span className=\"flex-1\" data-collapse-hide=\"\" />\n {/* Chevron icon for expand/collapse */}\n <svg\n className=\"w-4 h-4 transform transition-transform duration-200 peer-checked/category:rotate-180 ml-auto\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-collapse-hide=\"\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </label>\n\n {/* Category children - hidden by default, shown when checkbox is checked */}\n <div\n className=\"hidden peer-checked/category:block bg-background-subtle border-l-2 border-border-subtle ml-6\"\n data-collapse-hide-category=\"\"\n >\n {item.children.map((child) => renderNavItem(child, true))}\n </div>\n </div>\n );\n }\n\n // Otherwise render as regular link\n const linkProps = {\n href: item.href || \"#\",\n className: `flex items-center gap-3 transition-all duration-200 hover:bg-background-hover ${\n isNested ? \"pl-8 pr-6 py-1 text-sm\" : \"px-6 py-1\"\n } ${\n item.isActive\n ? `bg-action-brand/10 text-action-brand ${!isNested ? \"border-l-2 border-action-brand\" : \"\"}`\n : \"text-text-body hover:text-text-heading\"\n }`,\n \"aria-current\": item.isActive ? (\"page\" as const) : undefined,\n \"data-collapse-center\": !isNested ? \"\" : undefined,\n };\n\n const linkContent = (\n <>\n {item.icon && !isNested && (\n <span\n className=\"flex-shrink-0 w-3.5 h-3.5 flex items-center justify-center transition-all duration-200\"\n data-collapse-icon=\"\"\n >\n {item.icon}\n </span>\n )}\n <span className=\"transition-all duration-200\" data-collapse-hide=\"\">\n {item.label}\n </span>\n </>\n );\n\n if (LinkComponent === \"a\") {\n return (\n <a key={item.id} {...linkProps}>\n {linkContent}\n </a>\n );\n }\n\n return (\n <LinkComponent key={item.id} {...linkProps}>\n {linkContent}\n </LinkComponent>\n );\n };\n\n return (\n <div className={`flex flex-col h-full ${className}`}>\n {/* Header with logo and collapse button */}\n <div className=\"flex items-center justify-between h-[60px] px-6 border-b border-border-default\">\n {showLogo && (\n <div className=\"relative top-[-2px] transition-all duration-200\" data-collapse-hide=\"\">\n {logo ? (\n // If custom logo is provided, use it\n logo\n ) : (\n // Otherwise use the default Logo component\n <Logo showWordmark={true} width={120} />\n )}\n </div>\n )}\n\n {/* Desktop collapse toggle */}\n <label\n htmlFor={sidebarCollapseId}\n className=\"hidden md:flex items-center justify-center w-8 h-8 rounded hover:bg-background-hover cursor-pointer transition-all duration-200\"\n aria-label=\"Toggle sidebar\"\n data-collapse-toggle=\"\"\n >\n {/* Menu icon */}\n <svg\n className=\"w-5 h-5\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 12h16M4 18h16\"\n />\n </svg>\n </label>\n\n {/* Mobile close button */}\n <label\n htmlFor={mobileMenuId}\n className=\"md:hidden flex items-center justify-center w-8 h-8 rounded hover:bg-background-hover cursor-pointer transition-colors\"\n aria-label=\"Close menu\"\n >\n {/* Close icon */}\n <svg\n className=\"w-5 h-5\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </label>\n </div>\n\n {/* Navigation sections */}\n <nav className=\"flex-1 flex flex-col overflow-hidden\">\n {/* Top section - scrollable */}\n {topItems && topItems.length > 0 && (\n <div className=\"flex-1 overflow-y-auto py-2 scrollbar-hide\">\n {normalizeToSections(topItems).map((section, index, sections) =>\n renderSection(section, index, sections.length)\n )}\n </div>\n )}\n\n {/* Bottom section - fixed at bottom with enhanced separator */}\n {bottomItems && bottomItems.length > 0 && (\n <div className=\"flex-shrink-0 border-t bg-background-muted/30\">\n {/* Bottom navigation items with background and proper spacing */}\n <div className=\"mt-2 pb-2 space-y-0.5\">\n {bottomItems.map((item) => renderNavItem(item))}\n </div>\n </div>\n )}\n\n {/* Bottom content - for app-specific components like WorkspaceSwitcher */}\n {bottomContent && (\n <div className=\"flex-shrink-0 border-t border-border-default\">\n <div data-collapse-hide=\"\">{bottomContent}</div>\n </div>\n )}\n </nav>\n </div>\n );\n};\n","import type { IconProps as PhosphorIconProps } from \"@phosphor-icons/react\";\n// Import SSR-compatible icons\nimport * as PhosphorIconsSSR from \"@phosphor-icons/react/dist/ssr\";\nimport React, { memo } from \"react\";\nimport { twMerge } from \"tailwind-merge\";\n\n// Type for any Phosphor icon component\ntype PhosphorIconComponent = React.ComponentType<PhosphorIconProps>;\n\n// Extract all icon names from the Phosphor package\nexport type PhosphorIconName = string;\n\n// For backwards compatibility, export IconName as an alias\nexport type IconName = PhosphorIconName;\n\n// Standard size presets for the design system\nconst sizePresets = {\n xs: 16,\n sm: 20,\n md: 24,\n lg: 32,\n xl: 40,\n \"2xl\": 48,\n} as const;\n\ntype SizePreset = keyof typeof sizePresets;\n\ninterface IconSSRProps extends Omit<PhosphorIconProps, \"size\"> {\n /**\n * The name of the Phosphor icon to render\n * Any valid icon from @phosphor-icons/react\n */\n name: PhosphorIconName;\n\n /**\n * Size of the icon - can be a preset or custom number\n */\n size?: SizePreset | number;\n\n /**\n * Accessibility label (maps to aria-label)\n */\n ariaLabel?: string;\n}\n\n/**\n * IconSSR\n *\n * SSR-compatible Phosphor icon wrapper component with standardized sizing and styling.\n * Uses the SSR-compatible version of phosphor-icons for server-side rendering.\n * - TypeScript autocomplete for all icon names\n * - SSR-compatible: Uses SSR-optimized icons (no Context API dependency)\n * - Tree-shaking: Only icons you use are included in the bundle\n *\n * Usage:\n * ```tsx\n * <IconSSR name=\"House\" size=\"md\" />\n * <IconSSR name=\"User\" size={32} className=\"text-brand\" />\n * ```\n */\nexport const IconSSR = memo(\n ({\n name,\n size = \"md\",\n color,\n weight = \"regular\",\n className,\n ariaLabel,\n ...props\n }: IconSSRProps) => {\n // Get the icon component from the SSR Phosphor package\n const IconComponent = (PhosphorIconsSSR as unknown as Record<string, PhosphorIconComponent>)[\n name\n ];\n\n if (!IconComponent) {\n // Icon not found - return null silently in production\n return null;\n }\n\n // Resolve size to pixel value\n const resolvedSize: number =\n typeof size === \"string\"\n ? size in sizePresets\n ? sizePresets[size as SizePreset]\n : sizePresets.md // Fallback to md if invalid preset\n : size;\n\n // Build className with design system defaults\n const iconClassName = twMerge(\n // Default styles\n \"inline-block flex-shrink-0\",\n // Allow color inheritance from parent\n !color && \"text-current\",\n // Custom classes\n className\n );\n\n return (\n <IconComponent\n {...props}\n size={resolvedSize}\n color={color}\n weight={weight}\n className={iconClassName}\n aria-label={ariaLabel || `${name} icon`}\n data-testid={`icon-${name}`}\n />\n );\n }\n);\n\nIconSSR.displayName = \"IconSSR\";\n\n/**\n * Helper component for icons with containers (SSR version)\n */\ninterface IconSSRWithContainerProps extends IconSSRProps {\n /**\n * Container variant\n */\n variant?: \"subtle\" | \"solid\" | \"outline\";\n\n /**\n * Container shape\n */\n shape?: \"square\" | \"circle\";\n\n /**\n * Container size (adds padding around icon)\n */\n containerSize?: SizePreset | number;\n\n /**\n * Container background color\n */\n containerClassName?: string;\n}\n\nexport const IconSSRWithContainer = memo(\n ({\n variant = \"subtle\",\n shape = \"square\",\n containerSize,\n containerClassName,\n size = \"md\",\n className,\n name,\n color,\n weight,\n ariaLabel,\n ref,\n ...props\n }: IconSSRWithContainerProps & { ref?: React.Ref<HTMLDivElement> }) => {\n // Calculate container size if not specified\n const iconSize: number =\n typeof size === \"string\"\n ? size in sizePresets\n ? sizePresets[size as SizePreset]\n : sizePresets.md\n : size;\n\n const resolvedContainerSize: number = containerSize\n ? typeof containerSize === \"string\"\n ? containerSize in sizePresets\n ? sizePresets[containerSize as SizePreset]\n : iconSize * 1.75 // Fallback to default if invalid preset\n : containerSize\n : iconSize * 1.75;\n\n const containerClasses = twMerge(\n // Base styles\n \"inline-flex items-center justify-center flex-shrink-0\",\n\n // Shape\n shape === \"circle\" ? \"rounded-full\" : \"rounded-lg\",\n\n // Variant styles using Tailwind 4 CSS variables\n variant === \"subtle\" && \"bg-gray-100 dark:bg-gray-800\",\n variant === \"solid\" && \"bg-brand text-white\",\n variant === \"outline\" && \"border-2 border-current\",\n\n // Container className for overrides\n containerClassName\n );\n\n return (\n <div\n className={containerClasses}\n style={{\n width: resolvedContainerSize,\n height: resolvedContainerSize,\n }}\n >\n <IconSSR\n {...props}\n name={name}\n size={size}\n color={color}\n weight={weight}\n className={className}\n ariaLabel={ariaLabel}\n />\n </div>\n );\n }\n);\n\nIconSSRWithContainer.displayName = \"IconSSRWithContainer\";\n","import * as React from \"react\";\nimport { IconSSR } from \"../Icon/IconSSR\";\n\nexport type ColorMode = \"system\" | \"light\" | \"dark\";\n\nexport type TopNavProps = {\n /**\n * Content for the right side (avatar, actions, etc.)\n * @deprecated Use centerContent and actions instead for better layout control\n */\n rightContent?: React.ReactNode;\n /**\n * Content for the center area (typically search)\n * On mobile, this moves to rightContent position\n */\n centerContent?: React.ReactNode;\n showMobileMenu?: boolean;\n avatar?: React.ReactNode;\n showColorModeSwitcher?: boolean;\n toggleTheme?: () => void;\n isDarkThemeEnabled?: boolean;\n colorMode?: ColorMode;\n actions?: React.ReactNode;\n className?: string;\n mobileMenuId?: string;\n};\n\n/**\n * TopNav\n *\n * Horizontal navigation bar component for application headers.\n * Includes mobile menu toggle, user avatar, theme switcher, and customizable action areas.\n */\nexport const TopNav: React.FC<TopNavProps> = ({\n rightContent,\n centerContent,\n showMobileMenu = true,\n avatar,\n showColorModeSwitcher = false,\n toggleTheme,\n isDarkThemeEnabled = false,\n colorMode,\n actions,\n className = \"\",\n mobileMenuId = \"app-mobile-menu\",\n}) => {\n const getThemeIcon = () => {\n const effectiveMode = colorMode || (isDarkThemeEnabled ? \"dark\" : \"light\");\n\n switch (effectiveMode) {\n case \"system\":\n return <IconSSR name=\"Monitor\" size=\"sm\" />;\n case \"light\":\n return <IconSSR name=\"Sun\" size=\"sm\" />;\n case \"dark\":\n return <IconSSR name=\"Moon\" size=\"sm\" />;\n }\n };\n\n const getAriaLabel = () => {\n const effectiveMode = colorMode || (isDarkThemeEnabled ? \"dark\" : \"light\");\n\n switch (effectiveMode) {\n case \"system\":\n return \"Switch to light mode\";\n case \"light\":\n return \"Switch to dark mode\";\n case \"dark\":\n return \"Switch to system mode\";\n default:\n return \"Toggle theme\";\n }\n };\n return (\n <header className={`h-[60px] bg-background-surface border-b ${className}`}>\n <div className=\"relative flex h-full items-center\">\n {/* Left side - Mobile menu button */}\n <div className=\"flex items-center h-full flex-shrink-0\">\n {showMobileMenu && (\n <label\n htmlFor={mobileMenuId}\n className=\"md:hidden cursor-pointer\"\n aria-label=\"Open menu\"\n >\n <div className=\"flex h-full w-14 flex-col items-center justify-center border-r hover:bg-background-hover transition-colors\">\n <IconSSR name=\"List\" size=\"sm\" />\n </div>\n </label>\n )}\n </div>\n\n {/* Spacer for desktop */}\n <div className=\"hidden md:block flex-1\" />\n\n {/* Center content - ONE instance, positioned differently on mobile vs desktop */}\n {centerContent && (\n <div className=\"w-full md:absolute md:left-1/2 md:-translate-x-1/2 md:max-w-4xl md:px-4 flex justify-end md:justify-center\">\n {centerContent}\n </div>\n )}\n\n {/* Right side - User actions */}\n <div className=\"flex items-center gap-4 pr-4 flex-shrink-0\">\n {/* Legacy right content (deprecated) */}\n {rightContent}\n\n {/* Theme switcher */}\n {showColorModeSwitcher && toggleTheme && (\n <button\n type=\"button\"\n onClick={toggleTheme}\n className=\"flex items-center justify-center w-8 h-8 rounded hover:bg-background-hover transition-colors\"\n aria-label={getAriaLabel()}\n >\n {getThemeIcon()}\n </button>\n )}\n\n {/* Additional actions */}\n {actions}\n\n {/* Avatar */}\n {avatar && <div className=\"flex items-center\">{avatar}</div>}\n </div>\n </div>\n </header>\n );\n};\n","import React from \"react\";\nimport { SideNav, type SideNavProps } from \"../SideNav/SideNav\";\nimport { TopNav, type TopNavProps } from \"../TopNav/TopNav\";\n\n/** Layout options for the AppShell */\nexport type AppShellProps = {\n /** Structured nav for the left rail */\n sideNav: Omit<SideNavProps, \"mobileMenuId\" | \"sidebarCollapseId\">;\n /** Optional top bar slots & options */\n topNav?: Pick<\n TopNavProps,\n | \"rightContent\"\n | \"centerContent\"\n | \"showMobileMenu\"\n | \"avatar\"\n | \"showColorModeSwitcher\"\n | \"toggleTheme\"\n | \"isDarkThemeEnabled\"\n | \"colorMode\"\n | \"actions\"\n | \"className\"\n >;\n /** Main page content */\n children: React.ReactNode;\n\n /** Layout knobs */\n contentPaddingX?: string; // e.g. \"px-4 md:px-6\"\n contentPaddingY?: string; // e.g. \"py-4 md:py-6\"\n showSidebarBorder?: boolean; // default true\n mainClassName?: string; // extra classes on <main>\n\n /** Optional: Enable JavaScript progressive enhancements */\n enableJsEnhancements?: boolean;\n};\n\n/**\n * Isomorphic AppShell component that works as both server and client component\n * Uses CSS-only interactions by default for full SSR compatibility\n * Can be progressively enhanced with JavaScript when enableJsEnhancements is true\n */\nexport function AppShell({\n sideNav,\n topNav,\n children,\n contentPaddingX,\n contentPaddingY,\n showSidebarBorder = true,\n mainClassName,\n enableJsEnhancements = false,\n}: AppShellProps) {\n // Use stable IDs for CSS selectors\n const mobileMenuId = \"app-mobile-menu\";\n const sidebarCollapseId = \"app-sidebar-collapse\";\n\n return (\n <div className=\"min-h-[100dvh] bg-background text-text-body relative\">\n {/* Hidden checkbox for desktop sidebar collapse */}\n <input\n type=\"checkbox\"\n id={sidebarCollapseId}\n className=\"sr-only peer/sidebar\"\n aria-hidden=\"true\"\n />\n\n {/* Skip link for keyboard users */}\n <a\n href=\"#app-content\"\n className=\"sr-only focus:not-sr-only focus:absolute focus:left-4 focus:top-4 z-50 rounded px-3 py-2 bg-background-surface shadow\"\n >\n Skip to content\n </a>\n\n {/* Top navigation - always visible on mobile */}\n <TopNav\n {...topNav}\n mobileMenuId={mobileMenuId}\n className={[\"sticky top-0 flex-shrink-0 z-30 md:hidden\", topNav?.className]\n .filter(Boolean)\n .join(\" \")}\n />\n\n {/* Main layout container - contains sidebar and content */}\n <div className=\"flex w-full h-[calc(100dvh-60px)] md:h-[100dvh] relative overflow-hidden\">\n {/* Hidden checkbox for mobile menu - inside container for peer selectors */}\n <input\n type=\"checkbox\"\n id={mobileMenuId}\n className=\"sr-only peer/mobile\"\n aria-hidden=\"true\"\n />\n\n {/* Mobile menu overlay - fixed to cover entire viewport including TopNav */}\n <label\n htmlFor={mobileMenuId}\n className=\"fixed inset-0 bg-black/50 z-40 opacity-0 pointer-events-none peer-checked/mobile:opacity-100 peer-checked/mobile:pointer-events-auto transition-opacity md:hidden\"\n aria-label=\"Close menu\"\n />\n\n {/* Left rail - SideNav with CSS-based responsive behavior */}\n <aside\n id=\"app-sidebar\"\n className={[\n // Base styles\n \"bg-background-surface\",\n \"border-r border-border-default\",\n \"transition-all duration-300 ease-in-out\",\n // Mobile: fixed full-screen overlay\n \"fixed md:relative\",\n \"left-0 top-0 bottom-0\",\n \"z-50\",\n \"w-80 md:w-64\",\n \"h-[100dvh] md:h-full\",\n \"-translate-x-full\",\n \"peer-checked/mobile:translate-x-0\",\n // Desktop: always visible\n \"md:translate-x-0\",\n showSidebarBorder ? \"\" : \"!border-r-0\",\n sideNav?.className || \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n <SideNav\n {...sideNav}\n mobileMenuId={mobileMenuId}\n sidebarCollapseId={sidebarCollapseId}\n className=\"h-full\"\n />\n </aside>\n\n {/* Right side: TopNav + Main content */}\n <div className=\"flex-1 flex flex-col h-full overflow-hidden\">\n {/* Top navigation - desktop only */}\n <div className=\"sticky top-0 flex-shrink-0 hidden md:block z-20\">\n <TopNav {...topNav} className={topNav?.className} />\n </div>\n\n {/* Main content - scrollable */}\n <main\n id=\"app-content\"\n className={[\n \"flex-1 overflow-y-auto overflow-x-hidden bg-background-body\",\n contentPaddingX,\n contentPaddingY,\n mainClassName || \"\",\n ].join(\" \")}\n role=\"main\"\n >\n {children}\n </main>\n </div>\n </div>\n\n {/* Minimal CSS for checkbox-based interactions */}\n <style\n dangerouslySetInnerHTML={{\n __html: `\n @media (min-width: 768px) {\n /* Collapse sidebar width */\n #${sidebarCollapseId}:checked ~ * #app-sidebar {\n width: 4rem !important;\n }\n \n /* Collapse sidebar text */\n #${sidebarCollapseId}:checked ~ * [data-collapse-hide] {\n display: none !important;\n }\n \n /* Center nav items */\n #${sidebarCollapseId}:checked ~ * [data-collapse-center] {\n justify-content: center;\n padding-left: 0;\n padding-right: 0;\n gap: 0;\n }\n \n /* Adjust icon size when collapsed */\n #${sidebarCollapseId}:checked ~ * [data-collapse-icon] {\n width: 1.25rem !important;\n height: 1.25rem !important;\n }\n \n /* Scale SVG icons inside the icon container */\n #${sidebarCollapseId}:checked ~ * [data-collapse-icon] > svg {\n width: 1.25rem !important;\n height: 1.25rem !important;\n }\n \n /* Rotate toggle icon */\n #${sidebarCollapseId}:checked ~ * [data-collapse-toggle] {\n transform: scaleX(-1);\n }\n \n /* Hide category expansions */\n #${sidebarCollapseId}:checked ~ * [data-collapse-hide-category] {\n display: none;\n }\n }\n `,\n }}\n />\n\n {/* Optional: Progressive enhancement script */}\n {enableJsEnhancements && (\n <script\n dangerouslySetInnerHTML={{\n __html: `\n (function() {\n // Close mobile menu on Escape key\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape') {\n var menuToggle = document.getElementById('${mobileMenuId}');\n if (menuToggle) menuToggle.checked = false;\n }\n });\n \n // Save sidebar collapse preference to localStorage\n var sidebarToggle = document.getElementById('${sidebarCollapseId}');\n if (sidebarToggle) {\n // Restore from localStorage\n var saved = localStorage.getItem('sidebar-collapsed');\n if (saved !== null) {\n sidebarToggle.checked = saved === 'true';\n }\n \n // Save on change\n sidebarToggle.addEventListener('change', function() {\n localStorage.setItem('sidebar-collapsed', this.checked);\n });\n }\n \n // Prevent body scroll when mobile menu is open\n var mobileToggle = document.getElementById('${mobileMenuId}');\n if (mobileToggle) {\n mobileToggle.addEventListener('change', function() {\n document.body.style.overflow = this.checked ? 'hidden' : '';\n });\n }\n \n // Close mobile menu when clicking navigation links\n var sidebar = document.getElementById('app-sidebar');\n if (sidebar && mobileToggle) {\n sidebar.addEventListener('click', function(e) {\n // Check if click target is a link (or inside a link)\n var link = e.target.closest('a');\n if (link && link.href && window.innerWidth < 768) {\n // Small delay to allow navigation to start\n setTimeout(function() {\n mobileToggle.checked = false;\n document.body.style.overflow = '';\n }, 100);\n }\n });\n }\n })();\n `,\n }}\n />\n )}\n </div>\n );\n}\n","import { Building2, User, Users } from \"lucide-react\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport interface AvatarProps {\n /**\n * URL of the avatar image\n */\n src?: string;\n /**\n * Alternative text for the image\n */\n alt?: string;\n /**\n * First name for generating initials\n */\n firstName?: string;\n /**\n * Last name for generating initials\n */\n lastName?: string;\n /**\n * Full name (used as fallback for alt text)\n */\n fullName?: string;\n /**\n * Click handler\n */\n onClick?: () => void;\n /**\n * Size of the avatar\n * @default \"md\"\n */\n size?: \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n /**\n * Shape of the avatar\n * @default \"circle\"\n */\n shape?: \"circle\" | \"square\";\n /**\n * Visual variant\n * @default \"user\"\n */\n variant?: \"user\" | \"team\" | \"organization\";\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * Status indicator\n */\n status?: \"online\" | \"offline\" | \"away\" | \"busy\";\n /**\n * Whether to show a border\n * @default false\n */\n bordered?: boolean;\n}\n\n/**\n * Avatar\n *\n * Display user, team, or organization avatars with support for images,\n * initials, and fallback icons. Includes optional status indicators.\n */\nexport function Avatar({\n src,\n alt,\n firstName,\n lastName,\n fullName,\n onClick,\n size = \"md\",\n shape = \"circle\",\n variant = \"user\",\n className,\n status,\n bordered = false,\n}: AvatarProps) {\n const sizeClasses = {\n xs: \"h-6 w-6 text-xs\",\n sm: \"h-8 w-8 text-sm\",\n md: \"h-10 w-10 text-base\",\n lg: \"h-12 w-12 text-lg\",\n xl: \"h-16 w-16 text-xl\",\n };\n\n const statusSizeClasses = {\n xs: \"h-1.5 w-1.5\",\n sm: \"h-2 w-2\",\n md: \"h-2.5 w-2.5\",\n lg: \"h-3 w-3\",\n xl: \"h-4 w-4\",\n };\n\n const statusPositionClasses = {\n xs: \"bottom-0 right-0\",\n sm: \"bottom-0 right-0\",\n md: \"bottom-0 right-0\",\n lg: \"bottom-0.5 right-0.5\",\n xl: \"bottom-1 right-1\",\n };\n\n const statusColors = {\n online: \"bg-feedback-success-background border-feedback-success-border\",\n offline: \"bg-text-muted border-border-muted\",\n away: \"bg-feedback-warning-background border-feedback-warning-border\",\n busy: \"bg-feedback-error-background border-feedback-error-border\",\n };\n\n const variantColors = {\n user: \"bg-feedback-info-background text-feedback-info-text\",\n team: \"bg-feedback-info-background text-feedback-info-text\",\n organization: \"bg-feedback-success-background text-feedback-success-text\",\n };\n\n const shapeClasses = shape === \"circle\" ? \"rounded-full\" : \"rounded-md\";\n\n const baseClasses = twMerge(\n \"relative inline-flex items-center justify-center overflow-hidden transition-opacity outline-none\",\n sizeClasses[size],\n shapeClasses,\n onClick && \"cursor-pointer hover:opacity-80\",\n bordered && \"ring-2 ring-background-surface\",\n className\n );\n\n // Generate initials from name\n const getInitials = () => {\n if (firstName || lastName) {\n const first = firstName?.[0] || \"\";\n const last = lastName?.[0] || \"\";\n return (first + last).toUpperCase();\n }\n if (fullName) {\n const parts = fullName.split(\" \");\n const first = parts[0]?.[0] || \"\";\n const last = parts[parts.length - 1]?.[0] || \"\";\n return first === last ? first.toUpperCase() : (first + last).toUpperCase();\n }\n return \"\";\n };\n\n const initials = getInitials();\n\n // Get the appropriate icon for the variant\n const getIcon = () => {\n const iconSize = {\n xs: 14,\n sm: 16,\n md: 20,\n lg: 24,\n xl: 32,\n }[size];\n\n switch (variant) {\n case \"team\":\n return <Users size={iconSize} />;\n case \"organization\":\n return <Building2 size={iconSize} />;\n default:\n return <User size={iconSize} />;\n }\n };\n\n const renderAvatar = () => {\n // If src is provided, render image with CSS fallback\n if (src) {\n return (\n <>\n <img\n src={src}\n alt={alt || fullName || \"Avatar\"}\n className=\"h-full w-full object-cover\"\n // Use CSS to hide broken images\n style={{\n // This will hide the broken image icon\n fontSize: 0,\n }}\n />\n {/* Render fallback behind the image - will show if image fails */}\n <div className=\"absolute inset-0 flex items-center justify-center -z-10\">\n {initials ? <span className=\"font-semibold\">{initials}</span> : getIcon()}\n </div>\n </>\n );\n }\n\n // Show initials if available\n if (initials) {\n return <span className=\"font-semibold\">{initials}</span>;\n }\n\n // Show icon as fallback\n return getIcon();\n };\n\n return (\n <div className=\"relative inline-block\">\n <div\n data-avatar\n className={twMerge(baseClasses, !src ? variantColors[variant] : \"\")}\n onClick={onClick}\n role={onClick ? \"button\" : undefined}\n tabIndex={onClick ? 0 : undefined}\n >\n {renderAvatar()}\n </div>\n {status && (\n <span\n className={twMerge(\n \"absolute border-2 border-background-surface\",\n shapeClasses,\n statusSizeClasses[size],\n statusPositionClasses[size],\n statusColors[status]\n )}\n aria-label={`Status: ${status}`}\n />\n )}\n </div>\n );\n}\n","import React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\n\nconst sizeVariants = {\n xs: \"text-lg font-semibold\",\n sm: \"text-xl font-semibold\",\n md: \"text-2xl font-semibold\",\n lg: \"text-3xl font-semibold\",\n xl: \"text-4xl font-semibold\",\n} as const;\n\nconst heightVariants = {\n page: \"h-16 leading-[62px]\",\n} as const;\n\nexport type HeadingSize = keyof typeof sizeVariants;\nexport type HeadingHeight = keyof typeof heightVariants;\n\n/**\n * Heading\n *\n * Typography component for page/section headings with size and height options.\n */\nexport interface HeadingProps {\n tag?: React.ElementType;\n size?: HeadingSize;\n height?: HeadingHeight;\n className?: string;\n children?: React.ReactNode;\n}\n\nexport function Heading({\n tag: Tag = \"h1\",\n size = \"lg\",\n height,\n className = \"\",\n children,\n}: HeadingProps) {\n const sizeClasses = sizeVariants[size];\n const heightClasses = height ? heightVariants[height] : \"\";\n\n return <Tag className={twMerge(sizeClasses, heightClasses, className)}>{children}</Tag>;\n}\n","import { twMerge } from \"tailwind-merge\";\n\nexport interface LoaderProps {\n /**\n * Optional className for custom styling\n */\n className?: string;\n /**\n * Size of the loader in pixels\n * @default 24\n */\n size?: number;\n /**\n * Color of the loader\n * @default \"text-action-brand\"\n */\n color?: string;\n}\n\n/**\n * Loader\n *\n * Animated loading spinner component.\n * Displays a circular spinner with customizable size and color for loading states.\n */\nexport const Loader = ({ className, size = 24, color = \"text-action-brand\" }: LoaderProps) => {\n return (\n <div\n className={twMerge(\n \"inline-block animate-spin rounded-full border-2 border-solid border-current border-r-transparent\",\n color,\n className\n )}\n style={{\n width: size,\n height: size,\n }}\n role=\"status\"\n aria-label=\"loading\"\n >\n <span className=\"sr-only\">Loading...</span>\n </div>\n );\n};\n","import { ReactNode } from \"react\";\n\nexport interface TextLinkProps {\n href?: string;\n children: ReactNode;\n className?: string;\n external?: boolean;\n title?: string;\n variant?: \"default\" | \"brand\" | \"muted\" | \"unstyled\";\n onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;\n asButton?: boolean;\n onPress?: () => void;\n showArrow?: boolean;\n}\n\n/**\n * TextLink\n *\n * Styled text link component for navigation and actions.\n * Supports internal/external links, button mode, and multiple visual variants.\n */\nexport const TextLink = ({\n href,\n children,\n className = \"\",\n external = false,\n title,\n variant = \"default\",\n onClick,\n asButton = false,\n onPress,\n showArrow = false,\n}: TextLinkProps) => {\n const externalProps = external ? { target: \"_blank\", rel: \"noopener noreferrer\" } : {};\n\n const baseClasses =\n \"hover:underline hover:decoration-1 hover:underline-offset-4 hover:decoration-current cursor-pointer\";\n\n const variantClasses = {\n default: \"text-action-primary hover:text-action-primary-hover visited:text-action-primary\",\n brand: \"text-action-brand hover:text-action-brand-hover visited:text-action-brand\",\n muted: \"text-text-muted hover:text-text-muted visited:text-text-muted\",\n unstyled: \"\", // No color styling, inherits from children\n };\n\n const combinedClasses = `${baseClasses} ${variantClasses[variant]} ${className}`;\n\n const content = (\n <>\n {children}\n {showArrow && <span>{\"\\u00A0\"}→</span>}\n </>\n );\n\n if (asButton) {\n return (\n <button type=\"button\" className={combinedClasses} onClick={onPress} title={title}>\n {content}\n </button>\n );\n }\n\n return (\n <a\n href={href || \"#\"}\n className={combinedClasses}\n {...externalProps}\n title={title}\n onClick={onClick}\n >\n {content}\n </a>\n );\n};\n\nexport default TextLink;\n","/**\n * Entity Configuration\n *\n * Centralized configuration for all platform entities including\n * display properties, icons, colors, and labels.\n *\n * Use this for consistent entity representation across the application:\n * - Navigation\n * - Page headers\n * - Breadcrumbs\n * - Empty states\n * - Related entity links\n *\n * @example\n * ```tsx\n * import { ENTITY_CONFIG } from \"@texturehq/edges/config/entities\";\n *\n * const siteConfig = ENTITY_CONFIG.site;\n * // { icon: \"Buildings\", label: { singular: \"Site\", plural: \"Sites\" }, ... }\n * ```\n */\n\nimport type { IconName } from \"../components/Icon\";\n\nexport interface EntityConfig {\n /** Phosphor icon name */\n icon: IconName;\n /** Display labels */\n label: {\n singular: string;\n plural: string;\n };\n /** Optional description */\n description?: string;\n}\n\nexport const ENTITY_CONFIG = {\n app: {\n icon: \"AppWindow\",\n label: {\n singular: \"App\",\n plural: \"Apps\",\n },\n description: \"Workspace and integration apps\",\n },\n site: {\n icon: \"MapPin\",\n label: {\n singular: \"Site\",\n plural: \"Sites\",\n },\n description: \"Physical locations with energy systems\",\n },\n device: {\n icon: \"ShareNetwork\",\n label: {\n singular: \"Device\",\n plural: \"Devices\",\n },\n description: \"Connected energy devices\",\n },\n customer: {\n icon: \"Users\",\n label: {\n singular: \"Customer\",\n plural: \"Customers\",\n },\n description: \"End customers and site owners\",\n },\n contact: {\n icon: \"Users\",\n label: {\n singular: \"Contact\",\n plural: \"Contacts\",\n },\n description: \"Contact persons\",\n },\n program: {\n icon: \"ClipboardText\",\n label: {\n singular: \"Program\",\n plural: \"Programs\",\n },\n description: \"Demand response and VPP programs\",\n },\n workflow: {\n icon: \"FlowArrow\",\n label: {\n singular: \"Workflow\",\n plural: \"Workflows\",\n },\n description: \"Automated workflows and rules\",\n },\n collection: {\n icon: \"Stack\",\n label: {\n singular: \"Collection\",\n plural: \"Collections\",\n },\n description: \"Grouped entities\",\n },\n board: {\n icon: \"SquaresFour\",\n label: {\n singular: \"Board\",\n plural: \"Boards\",\n },\n description: \"Dashboard and monitoring boards\",\n },\n report: {\n icon: \"ChartLine\",\n label: {\n singular: \"Report\",\n plural: \"Reports\",\n },\n description: \"Analytics and reports\",\n },\n event: {\n icon: \"ClockCounterClockwise\",\n label: {\n singular: \"Event\",\n plural: \"Events\",\n },\n description: \"System events and activity\",\n },\n alert: {\n icon: \"Warning\",\n label: {\n singular: \"Alert\",\n plural: \"Alerts\",\n },\n description: \"Notifications and alerts\",\n },\n command: {\n icon: \"Play\",\n label: {\n singular: \"Command\",\n plural: \"Commands\",\n },\n description: \"Device commands and control\",\n },\n} as const satisfies Record<string, EntityConfig>;\n\nexport type EntityType = keyof typeof ENTITY_CONFIG;\n\n/**\n * Get entity configuration by type\n *\n * @param entityType - The entity type key\n * @returns Entity configuration object\n *\n * @example\n * ```tsx\n * const config = getEntityConfig(\"site\");\n * // { icon: \"Buildings\", label: { singular: \"Site\", plural: \"Sites\" }, ... }\n * ```\n */\nexport function getEntityConfig(entityType: EntityType): EntityConfig {\n return ENTITY_CONFIG[entityType];\n}\n\n/**\n * Get entity icon name\n *\n * @param entityType - The entity type key\n * @returns Phosphor icon name\n *\n * @example\n * ```tsx\n * const iconName = getEntityIcon(\"site\"); // \"Buildings\"\n * ```\n */\nexport function getEntityIcon(entityType: EntityType): IconName {\n return ENTITY_CONFIG[entityType].icon;\n}\n\n/**\n * Get entity label (singular or plural)\n *\n * @param entityType - The entity type key\n * @param plural - Whether to return plural form\n * @returns Entity label string\n *\n * @example\n * ```tsx\n * getEntityLabel(\"site\", false); // \"Site\"\n * getEntityLabel(\"site\", true); // \"Sites\"\n * ```\n */\nexport function getEntityLabel(entityType: EntityType, plural: boolean = false): string {\n return plural ? ENTITY_CONFIG[entityType].label.plural : ENTITY_CONFIG[entityType].label.singular;\n}\n","/**\n * Color utilities for the edges design system\n * Provides theme-aware color resolution and management\n */\n\n// Cache for resolved CSS variable colors\nconst colorCache = new Map<string, string>();\n\n/**\n * Type for Mapbox GL JS expressions\n * Represents nested array structures used by Mapbox for data-driven styling\n */\nexport type MapboxExpression =\n | string\n | number\n | boolean\n | Array<string | number | boolean | MapboxExpression>;\n\n/**\n * Resolves a CSS variable to its computed color value\n * Supports multiple formats and automatically adds the color- prefix if needed\n *\n * @param variableName - CSS variable name in any of these formats:\n * - \"brand-primary\" → resolves to --color-brand-primary\n * - \"color-brand-primary\" → resolves to --color-brand-primary\n * - \"--color-brand-primary\" → used as-is\n * - \"var(--color-brand-primary)\" → unwrapped and used\n * @returns Resolved color value or fallback\n */\nexport const getResolvedColor = (variableName: string, fallback = \"#000000\"): string => {\n // Early return if running in non-browser environment\n if (typeof window === \"undefined\") return fallback;\n\n // Normalize the variable name\n let varName = variableName.startsWith(\"var(\")\n ? variableName.slice(4, -1)\n : variableName.startsWith(\"--\")\n ? variableName\n : `--${variableName}`;\n\n // Add color- prefix ONLY for shorthand forms without the -- prefix\n // This allows \"brand-primary\" to resolve to \"--color-brand-primary\"\n // but preserves exact variable names like \"--text-body\" or \"--neutral-white\"\n if (\n !variableName.startsWith(\"--\") &&\n !variableName.startsWith(\"var(\") &&\n !varName.startsWith(\"--color-\")\n ) {\n varName = `--color-${varName.slice(2)}`;\n }\n\n // Return cached value if available\n if (colorCache.has(varName)) {\n return colorCache.get(varName)!;\n }\n\n try {\n // Get computed style from body element (where theme classes are applied)\n // This ensures we pick up theme-specific variables like .theme-dark\n const root = document.body || document.documentElement;\n const computedStyle = getComputedStyle(root);\n const value = computedStyle.getPropertyValue(varName).trim();\n\n if (value) {\n // Cache the result\n colorCache.set(varName, value);\n return value;\n }\n\n // Try alternative method with temporary element\n const tempElement = document.createElement(\"div\");\n tempElement.style.color = `var(${varName})`;\n document.body.appendChild(tempElement);\n const resolvedColor = getComputedStyle(tempElement).color;\n document.body.removeChild(tempElement);\n\n if (resolvedColor && resolvedColor !== \"rgb(0, 0, 0)\") {\n colorCache.set(varName, resolvedColor);\n return resolvedColor;\n }\n\n return fallback;\n } catch (error) {\n console.warn(`Failed to resolve color for ${variableName}:`, error);\n return fallback;\n }\n};\n\n/**\n * Clears the color cache - useful when theme changes\n */\nexport const clearColorCache = () => {\n colorCache.clear();\n};\n\n/**\n * Gets theme colors from CSS variables\n * Returns an array of resolved color values\n */\nexport const getThemeCategoricalColors = (): string[] => {\n const colors: string[] = [];\n\n // Try to get categorical colors from CSS variables\n for (let i = 1; i <= 6; i++) {\n const color = getResolvedColor(`--color-viz-categorical-${i}`);\n if (color) {\n colors.push(color);\n }\n }\n\n // Fallback to default palette if no theme colors found\n if (colors.length === 0) {\n return getDefaultColors();\n }\n\n return colors;\n};\n\n/**\n * Default color palette matching the edges design system\n */\nexport const getDefaultColors = (): string[] => [\n \"#444ae1\", // brand-primary\n \"#10b981\", // emerald-500\n \"#f59e0b\", // amber-500\n \"#ef4444\", // red-500\n \"#8b5cf6\", // violet-500\n \"#06b6d4\", // cyan-500\n \"#ec4899\", // pink-500\n \"#f97316\", // orange-500\n \"#14b8a6\", // teal-500\n \"#6366f1\", // indigo-500\n];\n\n/**\n * Gets the default chart color from theme\n */\nexport const getDefaultChartColor = (): string => {\n return getResolvedColor(\"--color-viz-default\", \"#444ae1\");\n};\n\n/**\n * Maps categories to colors based on a color scheme\n */\nexport const createCategoryColorMap = (\n categories: string[],\n customColors?: Record<string, string>\n): Record<string, string> => {\n const colorMap: Record<string, string> = {};\n const themeColors = getThemeCategoricalColors();\n\n categories.forEach((category, index) => {\n if (customColors && customColors[category]) {\n // Use custom color if provided\n colorMap[category] = customColors[category];\n } else {\n // Use theme color based on index\n colorMap[category] = themeColors[index % themeColors.length];\n }\n });\n\n return colorMap;\n};\n\n/**\n * Automatically assigns categorical colors to Mapbox layer paint properties\n * This makes it easy for consumers to get great colors without manual assignment\n */\nexport const createAutoColorPaint = (\n dataField: string, // The field to use for color assignment (e.g., \"state\", \"category\", \"type\")\n customColorMap?: Record<string, string>\n): Record<string, unknown> => {\n const defaultColor = getResolvedColor(\"--color-viz-default\", \"#444ae1\");\n\n // Create a case expression for Mapbox\n const caseExpression: unknown[] = [\"case\"];\n\n // Add custom color mappings first if provided\n if (customColorMap) {\n Object.entries(customColorMap).forEach(([value, color]) => {\n caseExpression.push([\"==\", [\"get\", dataField], value], color);\n });\n }\n\n // Add default categorical color cycling\n // This will cycle through colors for any values not in customColorMap\n caseExpression.push(defaultColor);\n\n return {\n \"fill-color\": caseExpression,\n };\n};\n\n/**\n * Creates a complete layer configuration with automatic color assignment\n * Perfect for consumers who just want to pass data and get great colors\n */\nexport const createDataLayer = (\n id: string,\n dataField: string,\n options: {\n type?: \"fill\" | \"line\" | \"circle\";\n customColors?: Record<string, string>;\n opacity?: number;\n strokeWidth?: number;\n strokeColor?: string;\n } = {}\n) => {\n const { type = \"fill\", customColors, opacity = 0.7 } = options;\n\n const baseLayer = {\n id,\n type,\n paint: {\n ...createAutoColorPaint(dataField, customColors),\n [`${type === \"fill\" ? \"fill\" : \"circle\"}-opacity`]: opacity,\n },\n layout: {\n visibility: \"visible\",\n },\n };\n\n // Add stroke for fill layers\n if (type === \"fill\") {\n baseLayer.paint[\"fill-opacity\"] = opacity;\n }\n\n return baseLayer;\n};\n\n/**\n * Determines if a color is light or dark\n * Useful for determining text color on colored backgrounds\n */\nexport const isLightColor = (color: string): boolean => {\n // Convert to RGB\n const rgb = color.match(/\\d+/g);\n if (!rgb || rgb.length < 3) return true;\n\n // Calculate luminance\n const [r, g, b] = rgb.map(Number);\n const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n\n return luminance > 0.5;\n};\n\n/**\n * Gets contrasting text color for a background\n */\nexport const getContrastingTextColor = (backgroundColor: string): string => {\n if (isLightColor(backgroundColor)) {\n return getResolvedColor(\"--text-body\", \"#333333\");\n }\n return getResolvedColor(\"--neutral-white\", \"#ffffff\");\n};\n\n/**\n * Extracts unique values for a given property from GeoJSON FeatureCollection\n *\n * @param data - GeoJSON FeatureCollection or Feature\n * @param property - Property name to extract values from\n * @returns Array of unique values, sorted\n * @throws Warning if data structure is invalid\n */\nexport const extractUniqueValues = (\n data: GeoJSON.FeatureCollection | GeoJSON.Feature,\n property: string\n): (string | number)[] => {\n // Validate data structure\n if (!data || typeof data !== \"object\") {\n console.warn(\"[Colors] Invalid GeoJSON data provided to extractUniqueValues\");\n return [];\n }\n\n // Validate it's GeoJSON\n if (!(\"type\" in data) || (data.type !== \"FeatureCollection\" && data.type !== \"Feature\")) {\n console.warn(\"[Colors] Data is not valid GeoJSON (missing type or invalid type)\");\n return [];\n }\n\n const values = new Set<string | number>();\n\n // Get features array\n const features = \"features\" in data ? data.features : [data];\n\n // Validate features exist\n if (!Array.isArray(features) || features.length === 0) {\n console.warn(`[Colors] No features found in GeoJSON data`);\n return [];\n }\n\n // Extract values\n let propertyFoundCount = 0;\n features.forEach((feature) => {\n if (!feature || typeof feature !== \"object\") {\n return; // Skip invalid features\n }\n\n if (feature.properties && property in feature.properties) {\n propertyFoundCount++;\n const value = feature.properties[property];\n if (value !== null && value !== undefined) {\n values.add(value);\n }\n }\n });\n\n // Warn if property wasn't found on any features\n if (propertyFoundCount === 0) {\n console.warn(\n `[Colors] Property \"${property}\" not found on any features. Available properties: ${\n features[0]?.properties ? Object.keys(features[0].properties).join(\", \") : \"none\"\n }`\n );\n }\n\n return Array.from(values).sort();\n};\n\n/**\n * Maps unique values to categorical colors with looping\n *\n * @param values - Array of unique values to map\n * @returns Map of value to color (hex string)\n */\nexport const mapValuesToCategoricalColors = (\n values: (string | number)[]\n): Record<string | number, string> => {\n const colors = getThemeCategoricalColors();\n const mapping: Record<string | number, string> = {};\n\n values.forEach((value, index) => {\n // Loop through colors if we have more values than colors\n mapping[value] = colors[index % colors.length];\n });\n\n return mapping;\n};\n\n/**\n * Creates a categorical color mapping for use with vector layers or explicit mappings\n *\n * This is a helper for cases where categorical auto-assignment doesn't work:\n * - Vector tile layers (data not accessible at render time)\n * - URL-based GeoJSON layers\n * - Custom pin layers\n *\n * @param property - The property name to color by (e.g., \"type\", \"category\")\n * @param values - Array of known values for this property\n * @returns ColorSpec with explicit mapping\n *\n * @example\n * // Vector layer with categorical coloring\n * layer.vector({\n * tileset: \"mapbox://my-tileset\",\n * sourceLayer: \"buildings\",\n * style: {\n * color: createCategoricalMapping(\"type\", [\"residential\", \"commercial\", \"industrial\"])\n * }\n * })\n *\n * @example\n * // With custom colors for specific values\n * const mapping = createCategoricalMapping(\"status\", [\"active\", \"pending\", \"inactive\"]);\n * // Then override specific colors if needed:\n * mapping.mapping.inactive = { hex: \"#cccccc\" };\n */\nexport const createCategoricalMapping = (\n property: string,\n values: (string | number)[]\n): { by: string; mapping: Record<string, { hex: string }> } => {\n const colorMap = mapValuesToCategoricalColors(values);\n\n const mapping: Record<string, { hex: string }> = {};\n Object.entries(colorMap).forEach(([value, color]) => {\n mapping[value] = { hex: color };\n });\n\n return {\n by: property,\n mapping,\n };\n};\n\n// ============================================================================\n// Sequential & Diverging Palette Utilities (Phase 2)\n// ============================================================================\n\n/**\n * Extract numeric values from GeoJSON data for sequential/diverging palettes\n *\n * @param data - GeoJSON FeatureCollection or Feature\n * @param property - Property name to extract values from\n * @returns Sorted array of numeric values\n */\nexport const extractNumericValues = (\n data: GeoJSON.FeatureCollection | GeoJSON.Feature,\n property: string\n): number[] => {\n if (!data || typeof data !== \"object\") {\n console.warn(\"[Colors] Invalid GeoJSON data provided to extractNumericValues\");\n return [];\n }\n\n if (!(\"type\" in data) || (data.type !== \"FeatureCollection\" && data.type !== \"Feature\")) {\n console.warn(\"[Colors] Data is not valid GeoJSON (missing type or invalid type)\");\n return [];\n }\n\n const features = \"features\" in data ? data.features : [data];\n\n if (!Array.isArray(features) || features.length === 0) {\n console.warn(`[Colors] No features found in GeoJSON data`);\n return [];\n }\n\n const values = new Set<number>();\n let propertyFoundCount = 0;\n\n features.forEach((feature) => {\n if (!feature || typeof feature !== \"object\") {\n return;\n }\n\n if (feature.properties && property in feature.properties) {\n propertyFoundCount++;\n const value = feature.properties[property];\n\n // Only accept actual numbers\n if (typeof value === \"number\" && !isNaN(value)) {\n values.add(value);\n }\n }\n });\n\n if (propertyFoundCount === 0) {\n console.warn(\n `[Colors] Property \"${property}\" not found on any features. Available properties: ${\n features[0]?.properties ? Object.keys(features[0].properties).join(\", \") : \"none\"\n }`\n );\n }\n\n return Array.from(values).sort((a, b) => a - b);\n};\n\n/**\n * Calculate min and max bounds from numeric values\n *\n * @param values - Sorted array of numeric values\n * @returns Object with min and max, or {min: 0, max: 1} if empty\n */\nexport const calculateBounds = (values: number[]): { min: number; max: number } => {\n if (values.length === 0) {\n console.warn(\"[Colors] Cannot calculate bounds from empty array\");\n return { min: 0, max: 1 };\n }\n\n return {\n min: values[0],\n max: values[values.length - 1],\n };\n};\n\n/**\n * Calculate center point for diverging palettes\n *\n * @param values - Sorted array of numeric values\n * @param method - \"median\", \"mean\", or explicit number\n * @returns Center value\n */\nexport const calculateCenter = (values: number[], method: \"median\" | \"mean\" | number): number => {\n // Explicit number provided\n if (typeof method === \"number\") {\n return method;\n }\n\n if (values.length === 0) {\n console.warn(\"[Colors] Cannot calculate center from empty array, defaulting to 0\");\n return 0;\n }\n\n if (method === \"median\") {\n const mid = Math.floor(values.length / 2);\n return values.length % 2 === 0 ? (values[mid - 1] + values[mid]) / 2 : values[mid];\n }\n\n // method === \"mean\"\n return values.reduce((sum, v) => sum + v, 0) / values.length;\n};\n\n/**\n * Get colors for a specific sequential palette\n *\n * @param scheme - Sequential palette name (defaults to \"viridis\")\n * @returns Array of 10 hex color strings\n */\nexport const getSequentialColors = (scheme: string = \"viridis\"): string[] => {\n // Convert camelCase to kebab-case\n const paletteMap: Record<string, string> = {\n redYellowGreen: \"red-yellow-green\",\n };\n\n const kebabName = paletteMap[scheme] || scheme;\n const prefix = `viz-sequential-${kebabName}`;\n const colors: string[] = [];\n\n // Each sequential palette has 10 colors (1-10)\n for (let i = 1; i <= 10; i++) {\n const cssVar = `${prefix}-${i}`;\n const resolved = getResolvedColor(cssVar);\n colors.push(resolved);\n }\n\n return colors;\n};\n\n/**\n * Get colors for a specific diverging palette\n *\n * @param scheme - Diverging palette name (defaults to \"redYellowBlue\")\n * @returns Array of 10 hex color strings (color 5 is the center)\n */\nexport const getDivergingColors = (scheme: string = \"redYellowBlue\"): string[] => {\n // Convert camelCase to kebab-case\n const paletteMap: Record<string, string> = {\n orangeYellowSeafoam: \"orange-yellow-seafoam\",\n redYellowBlue: \"red-yellow-blue\",\n redBlue: \"red-blue\",\n };\n\n const kebabName = paletteMap[scheme] || scheme;\n const prefix = `viz-diverging-${kebabName}`;\n const colors: string[] = [];\n\n // Each diverging palette has 10 colors (1-10), with 5 being the center\n for (let i = 1; i <= 10; i++) {\n const cssVar = `${prefix}-${i}`;\n const resolved = getResolvedColor(cssVar);\n colors.push(resolved);\n }\n\n return colors;\n};\n\n/**\n * Get color from sequential scale for a given value\n * Uses existing sequential palettes to interpolate color based on value position in range\n *\n * @param value - The value to get color for\n * @param min - Minimum value in the range\n * @param max - Maximum value in the range\n * @param scheme - Sequential palette name (defaults to \"viridis\")\n * @returns Interpolated color string\n *\n * @example\n * // Get color for response time (0-5000ms range)\n * const color = getColorFromSequentialScale(2500, 0, 5000, 'viridis');\n */\nexport const getColorFromSequentialScale = (\n value: number,\n min: number,\n max: number,\n scheme: string = \"viridis\"\n): string => {\n const colors = getSequentialColors(scheme);\n\n // Handle edge cases\n if (value <= min) return colors[0];\n if (value >= max) return colors[colors.length - 1];\n if (min === max) return colors[Math.floor(colors.length / 2)];\n\n // Calculate position in range (0 to 1)\n const position = (value - min) / (max - min);\n\n // Map to color index (0 to colors.length - 1)\n const colorIndex = position * (colors.length - 1);\n const lowerIndex = Math.floor(colorIndex);\n const upperIndex = Math.ceil(colorIndex);\n\n // If exact match, return that color\n if (lowerIndex === upperIndex) {\n return colors[lowerIndex];\n }\n\n // For now, return the lower color (simple implementation)\n // Could be enhanced with actual color interpolation in the future\n return colors[lowerIndex];\n};\n\n/**\n * Get color from diverging scale for a given value\n * Uses existing diverging palettes to interpolate color based on value position relative to center\n *\n * @param value - The value to get color for\n * @param min - Minimum value in the range\n * @param max - Maximum value in the range\n * @param center - The center point of the diverging scale\n * @param scheme - Diverging palette name (defaults to \"redYellowBlue\")\n * @returns Interpolated color string\n *\n * @example\n * // Get color for temperature anomaly (-10 to +10, center at 0)\n * const color = getColorFromDivergingScale(5, -10, 10, 0, 'redYellowBlue');\n */\nexport const getColorFromDivergingScale = (\n value: number,\n min: number,\n max: number,\n center: number,\n scheme: string = \"redYellowBlue\"\n): string => {\n const colors = getDivergingColors(scheme);\n const centerIndex = 4; // 5th color (index 4) is the center\n\n // Handle edge cases\n if (value <= min) return colors[0];\n if (value >= max) return colors[colors.length - 1];\n if (value === center) return colors[centerIndex];\n if (min === max) return colors[centerIndex];\n\n // Determine which side of center we're on\n if (value < center) {\n // Left side: min to center (colors 0-4)\n const position = (value - min) / (center - min);\n const colorIndex = position * centerIndex;\n const lowerIndex = Math.floor(colorIndex);\n return colors[Math.min(lowerIndex, centerIndex)];\n } else {\n // Right side: center to max (colors 4-9)\n const position = (value - center) / (max - center);\n const colorIndex = centerIndex + position * (colors.length - 1 - centerIndex);\n const lowerIndex = Math.floor(colorIndex);\n return colors[Math.min(lowerIndex, colors.length - 1)];\n }\n};\n\n/**\n * Creates a sequential color mapping for vector layers or manual bounds\n *\n * Use this helper when categorical auto-assignment doesn't work:\n * - Vector tile layers (data not accessible at render time)\n * - URL-based GeoJSON layers\n * - When you want consistent colors across multiple maps\n *\n * @param property - The property name to color by\n * @param bounds - Min and max values for the scale\n * @param scheme - Sequential palette name (defaults to \"viridis\")\n * @returns Mapbox interpolate expression\n *\n * @example\n * // Vector layer with sequential coloring\n * layer.vector({\n * tileset: \"mapbox://my-tileset\",\n * sourceLayer: \"population\",\n * style: {\n * color: createSequentialMapping(\"density\", { min: 0, max: 100000 }, \"magma\")\n * }\n * })\n */\nexport const createSequentialMapping = (\n property: string,\n bounds: { min: number; max: number },\n scheme: string = \"viridis\"\n): MapboxExpression => {\n const colors = getSequentialColors(scheme);\n const expr: MapboxExpression = [\"interpolate\", [\"linear\"], [\"get\", property]];\n\n // Guard against collapsed range (all values the same)\n // Mapbox requires at least 2 stops for interpolate, so use same color for min and a tiny offset\n if (bounds.min === bounds.max) {\n expr.push(bounds.min, colors[0]);\n expr.push(bounds.min + 0.0001, colors[0]);\n return expr;\n }\n\n colors.forEach((color, i) => {\n const t = i / (colors.length - 1); // 0 to 1\n const value = bounds.min + t * (bounds.max - bounds.min);\n expr.push(value, color);\n });\n\n return expr;\n};\n\n/**\n * Creates a diverging color mapping for vector layers or manual bounds\n *\n * Use this helper when categorical auto-assignment doesn't work:\n * - Vector tile layers (data not accessible at render time)\n * - URL-based GeoJSON layers\n * - When you want consistent colors across multiple maps\n *\n * @param property - The property name to color by\n * @param bounds - Min and max values for the scale\n * @param center - The center point (e.g., 0 for average, sea level, break-even)\n * @param scheme - Diverging palette name (defaults to \"redYellowBlue\")\n * @returns Mapbox interpolate expression\n *\n * @example\n * // Vector layer with diverging coloring\n * layer.vector({\n * tileset: \"mapbox://my-tileset\",\n * sourceLayer: \"temperature\",\n * style: {\n * color: createDivergingMapping(\"temp_anomaly\", { min: -10, max: 10 }, 0, \"orangeYellowSeafoam\")\n * }\n * })\n */\nexport const createDivergingMapping = (\n property: string,\n bounds: { min: number; max: number },\n center: number,\n scheme: string = \"redYellowBlue\"\n): MapboxExpression => {\n const colors = getDivergingColors(scheme);\n const expr: MapboxExpression = [\"interpolate\", [\"linear\"], [\"get\", property]];\n const centerIndex = 4; // 5th color (index 4) is the center\n\n // Guard against collapsed range (all values the same)\n // Mapbox requires at least 2 stops for interpolate, so use same color for min and a tiny offset\n if (bounds.min === bounds.max) {\n expr.push(bounds.min, colors[centerIndex]);\n expr.push(bounds.min + 0.0001, colors[centerIndex]);\n return expr;\n }\n\n // Handle center at min edge\n if (center === bounds.min) {\n expr.push(center, colors[centerIndex]);\n // Only add stops from center to max\n for (let i = centerIndex + 1; i < colors.length; i++) {\n const t = (i - centerIndex) / (colors.length - 1 - centerIndex);\n const value = center + t * (bounds.max - center);\n expr.push(value, colors[i]);\n }\n return expr;\n }\n\n // Handle center at max edge\n if (center === bounds.max) {\n // Only add stops from min to center\n for (let i = 0; i < centerIndex; i++) {\n const t = i / centerIndex;\n const value = bounds.min + t * (center - bounds.min);\n expr.push(value, colors[i]);\n }\n expr.push(center, colors[centerIndex]);\n return expr;\n }\n\n // Normal case: center is between min and max\n // Colors 1-5: min → center\n for (let i = 0; i <= centerIndex; i++) {\n const t = i / centerIndex; // 0 to 1\n const value = bounds.min + t * (center - bounds.min);\n expr.push(value, colors[i]);\n }\n\n // Colors 6-10: center → max\n for (let i = centerIndex + 1; i < colors.length; i++) {\n const t = (i - centerIndex) / (colors.length - 1 - centerIndex); // 0 to 1\n const value = center + t * (bounds.max - center);\n expr.push(value, colors[i]);\n }\n\n return expr;\n};\n","/**\n * FormatRegistry - A singleton pattern for managing formatters\n * Allows registration and retrieval of formatting functions by key\n */\n\nimport type { FieldValue, FormattedValue, FormatterFunction } from \"./types\";\n\nclass FormatRegistryClass {\n private formatters: Map<string, FormatterFunction> = new Map();\n\n /**\n * Register a new formatter\n * @param key - Unique identifier for the formatter\n * @param formatter - The formatting function\n */\n register(key: string, formatter: FormatterFunction): void {\n this.formatters.set(key, formatter);\n }\n\n /**\n * Format a value using a registered formatter\n * @param key - The formatter key\n * @param value - The value to format\n * @param args - Additional arguments to pass to the formatter\n * @returns The formatted value or null\n */\n format(key: string, value: FieldValue, ...args: unknown[]): FormattedValue {\n const formatter = this.formatters.get(key);\n if (!formatter) {\n console.warn(`No formatter registered for key: ${key}`);\n return null;\n }\n return formatter(value, ...args);\n }\n\n /**\n * Check if a formatter is registered\n * @param key - The formatter key\n * @returns True if the formatter exists\n */\n has(key: string): boolean {\n return this.formatters.has(key);\n }\n\n /**\n * Get all registered formatter keys\n * @returns Array of formatter keys\n */\n keys(): string[] {\n return Array.from(this.formatters.keys());\n }\n\n /**\n * Remove a formatter\n * @param key - The formatter key to remove\n */\n unregister(key: string): void {\n this.formatters.delete(key);\n }\n\n /**\n * Clear all registered formatters\n */\n clear(): void {\n this.formatters.clear();\n }\n}\n\n// Export singleton instance\nexport const FormatRegistry = new FormatRegistryClass();\n","/**\n * Boolean formatting utilities\n */\n\nimport { FormatRegistry } from \"./registry\";\nimport type { BooleanFormat, FieldValue, FormattedValue } from \"./types\";\n\n/**\n * Format boolean value with custom text\n */\nexport const toBoolean = (\n value: boolean | null | undefined,\n trueText: string = \"Yes\",\n falseText: string = \"No\"\n): string | null => {\n if (value === null || value === undefined) return null;\n return value ? trueText : falseText;\n};\n\n/**\n * Format boolean as enabled/disabled\n */\nexport const toEnabledDisabled = (value: boolean | null | undefined): string | null => {\n return toBoolean(value, \"Enabled\", \"Disabled\");\n};\n\n/**\n * Format boolean as on/off\n */\nexport const toOnOff = (value: boolean | null | undefined): string | null => {\n return toBoolean(value, \"On\", \"Off\");\n};\n\n/**\n * Format boolean as active/inactive\n */\nexport const toActiveInactive = (value: boolean | null | undefined): string | null => {\n return toBoolean(value, \"Active\", \"Inactive\");\n};\n\n/**\n * Format boolean as true/false\n */\nexport const toTrueFalse = (value: boolean | null | undefined): string | null => {\n return toBoolean(value, \"True\", \"False\");\n};\n\n/**\n * Format boolean as checkmark/cross\n */\nexport const toCheckmark = (value: boolean | null | undefined): string | null => {\n return toBoolean(value, \"✓\", \"✗\");\n};\n\n/**\n * Parse various truthy/falsy values to boolean\n */\nexport const parseBoolean = (value: FieldValue): boolean | null => {\n if (value === null || value === undefined) return null;\n\n if (typeof value === \"boolean\") {\n return value;\n }\n\n if (typeof value === \"string\") {\n const lower = value.toLowerCase().trim();\n if (\n lower === \"true\" ||\n lower === \"yes\" ||\n lower === \"1\" ||\n lower === \"on\" ||\n lower === \"enabled\"\n ) {\n return true;\n }\n if (\n lower === \"false\" ||\n lower === \"no\" ||\n lower === \"0\" ||\n lower === \"off\" ||\n lower === \"disabled\"\n ) {\n return false;\n }\n return null;\n }\n\n if (typeof value === \"number\") {\n return value !== 0;\n }\n\n return null;\n};\n\n/**\n * Format boolean according to BooleanFormat specification\n */\nexport const formatBoolean = (value: FieldValue, format: BooleanFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (value == null) return format.nullText ?? null;\n\n const boolValue = parseBoolean(value);\n if (boolValue === null) return format.nullText ?? null;\n\n return toBoolean(boolValue, format.trueText ?? \"Yes\", format.falseText ?? \"No\");\n};\n\n// Register boolean formatters\nFormatRegistry.register(\"boolean\", (value, trueText, falseText) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toBoolean(\n boolValue,\n typeof trueText === \"string\" ? trueText : \"Yes\",\n typeof falseText === \"string\" ? falseText : \"No\"\n );\n }\n return null;\n});\n\nFormatRegistry.register(\"yesNo\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toBoolean(boolValue, \"Yes\", \"No\");\n }\n return null;\n});\n\nFormatRegistry.register(\"enabledDisabled\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toEnabledDisabled(boolValue);\n }\n return null;\n});\n\nFormatRegistry.register(\"onOff\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toOnOff(boolValue);\n }\n return null;\n});\n\nFormatRegistry.register(\"activeInactive\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toActiveInactive(boolValue);\n }\n return null;\n});\n\nFormatRegistry.register(\"trueFalse\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toTrueFalse(boolValue);\n }\n return null;\n});\n\nFormatRegistry.register(\"checkmark\", (value) => {\n const boolValue = parseBoolean(value);\n if (boolValue !== null) {\n return toCheckmark(boolValue);\n }\n return null;\n});\n","/**\n * Number and currency formatting utilities\n */\n\nimport { FormatRegistry } from \"./registry\";\nimport type { CurrencyFormat, FieldValue, FormattedValue, NumberFormat } from \"./types\";\n\n/**\n * Check if a value is null or undefined\n */\nexport const isNil = (value: unknown): value is null | undefined => {\n return value === null || value === undefined;\n};\n\n/**\n * Format as percentage\n */\nexport const toPercentage = (\n value: number | null | undefined,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)}%`;\n};\n\n/**\n * Format percentage (simple wrapper for consistency with other formatters)\n *\n * @param value - Numeric value (0-100 range)\n * @param precision - Number of decimal places (default: 0)\n * @returns Formatted percentage string with % symbol\n */\nexport const formatPercent = (value: number | null | undefined, precision: number = 0): string => {\n const result = toPercentage(value, precision);\n return result ?? \"—\";\n};\n\n/**\n * Format as integer\n */\nexport const toInteger = (value: number | null | undefined): string | null => {\n if (isNil(value)) return null;\n return Math.round(value).toString();\n};\n\n/**\n * Format as float with specified decimals\n */\nexport const toFloat = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return value.toFixed(decimals);\n};\n\n/**\n * Format number with thousands separator\n */\nexport const toFormattedNumber = (\n value: number | null | undefined,\n decimals?: number,\n thousandsSeparator: boolean = true\n): string | null => {\n if (isNil(value)) return null;\n\n const options: Intl.NumberFormatOptions = {\n useGrouping: thousandsSeparator,\n };\n\n if (decimals !== undefined) {\n options.minimumFractionDigits = decimals;\n options.maximumFractionDigits = decimals;\n }\n\n return new Intl.NumberFormat(\"en-US\", options).format(value);\n};\n\n/**\n * Format number with compact notation (1K, 1M, etc.)\n */\nexport const toCompactNumber = (\n value: number | null | undefined,\n display: \"short\" | \"long\" = \"short\"\n): string | null => {\n if (isNil(value)) return null;\n\n return new Intl.NumberFormat(\"en-US\", {\n notation: \"compact\",\n compactDisplay: display,\n }).format(value);\n};\n\n/**\n * Format number with scientific notation\n */\nexport const toScientificNotation = (\n value: number | null | undefined,\n decimals: number = 2\n): string | null => {\n if (isNil(value)) return null;\n return value.toExponential(decimals);\n};\n\n/**\n * Format as currency\n */\nexport const toCurrency = (\n value: number | null | undefined,\n currency: string = \"USD\",\n options?: Partial<CurrencyFormat>\n): string | null => {\n if (isNil(value)) return null;\n\n const formatOptions: Intl.NumberFormatOptions = {\n style: \"currency\",\n currency,\n currencyDisplay: options?.currencyDisplay ?? \"symbol\",\n useGrouping: options?.thousandsSeparator ?? true,\n };\n\n if (options?.minimumFractionDigits !== undefined) {\n formatOptions.minimumFractionDigits = options.minimumFractionDigits;\n }\n\n if (options?.maximumFractionDigits !== undefined) {\n formatOptions.maximumFractionDigits = options.maximumFractionDigits;\n }\n\n return new Intl.NumberFormat(\"en-US\", formatOptions).format(value);\n};\n\n/**\n * Format number according to NumberFormat specification\n */\nexport const formatNumber = (value: FieldValue, format: NumberFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const options: Intl.NumberFormatOptions = {\n useGrouping: format.thousandsSeparator ?? false,\n };\n\n if (format.decimals !== undefined) {\n options.minimumFractionDigits = format.decimals;\n options.maximumFractionDigits = format.decimals;\n }\n\n if (format.notation) {\n options.notation = format.notation;\n if (format.notation === \"compact\" && format.compactDisplay) {\n options.compactDisplay = format.compactDisplay;\n }\n }\n\n if (format.sign) {\n options.signDisplay = format.sign;\n }\n\n return new Intl.NumberFormat(\"en-US\", options).format(numValue);\n};\n\n/**\n * Format currency according to CurrencyFormat specification\n */\nexport const formatCurrency = (value: FieldValue, format: CurrencyFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n return toCurrency(numValue, format.currency, format);\n};\n\n// Register number formatters\nFormatRegistry.register(\"percentage\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toPercentage(value, typeof decimals === \"number\" ? decimals : 0);\n }\n return null;\n});\n\nFormatRegistry.register(\"integer\", (value) => {\n if (typeof value === \"number\") {\n return toInteger(value);\n }\n return null;\n});\n\nFormatRegistry.register(\"float\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toFloat(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\nFormatRegistry.register(\"number\", (value, decimals, thousandsSeparator) => {\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (!isNaN(numValue)) {\n return toFormattedNumber(\n numValue,\n typeof decimals === \"number\" ? decimals : undefined,\n typeof thousandsSeparator === \"boolean\" ? thousandsSeparator : true\n );\n }\n return null;\n});\n\nFormatRegistry.register(\"compact\", (value, display) => {\n if (typeof value === \"number\") {\n return toCompactNumber(value, display === \"long\" ? \"long\" : \"short\");\n }\n return null;\n});\n\nFormatRegistry.register(\"scientific\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toScientificNotation(value, typeof decimals === \"number\" ? decimals : 2);\n }\n return null;\n});\n\nFormatRegistry.register(\"currency\", (value, currency, options) => {\n if (typeof value === \"number\") {\n return toCurrency(\n value,\n typeof currency === \"string\" ? currency : \"USD\",\n typeof options === \"object\" && options !== null ? options : {}\n );\n }\n return null;\n});\n","/**\n * Centralized formatting utility for UI components\n * Used by Kpi, StatList, and other data display components\n */\n\nimport React from \"react\";\nimport { formatFieldValue } from \"./index\";\nimport type { FieldFormat, FieldValue } from \"./types\";\n\n/**\n * Common formatter type used by data display components\n * Can be either a custom function or a FieldFormat object\n */\nexport type ComponentFormatter = ((value: FieldValue) => React.ReactNode) | FieldFormat;\n\n/**\n * Options for formatting values in components\n */\nexport interface ComponentFormatOptions {\n /** The value to format */\n value: FieldValue;\n /** The formatter to apply */\n formatter?: ComponentFormatter;\n /** CSS class for null/empty values */\n emptyClassName?: string;\n /** Text to show for null/empty values */\n emptyText?: React.ReactNode;\n}\n\n/**\n * Format a value for display in a component\n * Centralizes the logic used by Kpi, StatList, and similar components\n *\n * @example\n * ```tsx\n * // In a component\n * const formatted = formatComponentValue({\n * value: 1500,\n * formatter: { type: \"power\" }\n * });\n * // Returns: \"1.5 kW\"\n * ```\n */\nexport function formatComponentValue({\n value,\n formatter,\n emptyClassName = \"text-text-muted\",\n emptyText = \"—\",\n}: ComponentFormatOptions): React.ReactNode {\n // Handle null/undefined early\n if (value == null) {\n return <span className={emptyClassName}>{emptyText}</span>;\n }\n\n // Custom formatter function takes precedence\n if (typeof formatter === \"function\") {\n return formatter(value);\n }\n\n // If a FieldFormat is provided, use the unified formatting system\n if (formatter && typeof formatter === \"object\") {\n const formatted = formatFieldValue(value, formatter);\n\n // Wrap dates in semantic time element for accessibility\n if (value instanceof Date && formatted) {\n return (\n <time dateTime={value.toISOString()} title={value.toISOString()}>\n {formatted}\n </time>\n );\n }\n\n return formatted || <span className={emptyClassName}>{emptyText}</span>;\n }\n\n // No formatter provided - use sensible defaults based on type\n if (!formatter) {\n // For strings, just return as-is\n if (typeof value === \"string\") {\n return value;\n }\n\n // For dates, use default date formatting\n if (value instanceof Date) {\n const formatted = formatFieldValue(value, { type: \"date\" });\n return (\n <time dateTime={value.toISOString()} title={value.toISOString()}>\n {formatted}\n </time>\n );\n }\n\n // For numbers, use default number formatting\n if (typeof value === \"number\") {\n return formatFieldValue(value, { type: \"number\" });\n }\n\n // For booleans, use default boolean formatting\n if (typeof value === \"boolean\") {\n return formatFieldValue(value, { type: \"boolean\" });\n }\n }\n\n // Fallback to string conversion\n return String(value);\n}\n\n/**\n * Hook for using the component formatter\n * Provides memoization for better performance\n *\n * @example\n * ```tsx\n * function MyComponent({ value, formatter }) {\n * const format = useComponentFormatter(formatter);\n * const formatted = format(value);\n * return <span>{formatted}</span>;\n * }\n * ```\n */\nexport function useComponentFormatter(\n formatter?: ComponentFormatter,\n emptyClassName?: string,\n emptyText?: React.ReactNode\n) {\n return React.useCallback(\n (value: FieldValue) =>\n formatComponentValue({\n value,\n formatter,\n emptyClassName,\n emptyText,\n }),\n [formatter, emptyClassName, emptyText]\n );\n}\n","/**\n * Electrical current formatting utilities (flow of electric charge)\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { CurrentFormat, FieldValue, FormattedValue } from \"./types\";\n\n/**\n * Format as milliamps\n */\nexport const toMilliamps = (\n value: number | null | undefined,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n const mA = value * 1000;\n return decimals === 0 ? `${Math.round(mA)} mA` : `${mA.toFixed(decimals)} mA`;\n};\n\n/**\n * Format as amperes\n */\nexport const toAmps = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} A`;\n};\n\n/**\n * Format as kiloamps (rarely used but included for completeness)\n */\nexport const toKiloamps = (\n value: number | null | undefined,\n decimals: number = 2\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} kA`;\n};\n\n/**\n * Auto-scale current to the most appropriate unit\n */\nexport const autoScaleCurrent = (\n value: number | null | undefined,\n decimals?: number\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (absValue >= 1000) {\n return toKiloamps(value, decimals ?? 2);\n } else if (absValue < 1) {\n return toMilliamps(value, decimals ?? 0);\n } else {\n return toAmps(value, decimals ?? 1);\n }\n};\n\n/**\n * Format current according to CurrentFormat specification\n */\nexport const formatCurrent = (value: FieldValue, format: CurrentFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals;\n\n // If a specific unit is provided, use it\n if (format.unit) {\n switch (format.unit) {\n case \"kA\":\n return toKiloamps(numValue, decimals ?? 2);\n case \"mA\":\n return toMilliamps(numValue, decimals ?? 0);\n case \"A\":\n return toAmps(numValue, decimals ?? 1);\n }\n }\n\n // Default to auto-scaling unless explicitly disabled\n if (format.autoScale !== false) {\n return autoScaleCurrent(numValue, decimals);\n }\n\n // If auto-scale is explicitly false and no unit specified, use base amps\n return toAmps(numValue, decimals ?? 1);\n};\n\n// Register the formatter\n// biome-ignore lint/suspicious/noExplicitAny: Required for FormatRegistry type compatibility\nFormatRegistry.register(\"current\", formatCurrent as any);\n\n// Convenience exports with shorter names\nexport const toMA = toMilliamps;\nexport const toA = toAmps;\nexport const toKA = toKiloamps;\n","/**\n * Date formatting utilities using Luxon\n */\n\nimport { DateTime } from \"luxon\";\nimport { FormatRegistry } from \"./registry\";\nimport type { DateFormat, FieldValue, FormattedValue } from \"./types\";\n\n/**\n * Convert a value to a Luxon DateTime object.\n * Handles Date objects, ISO strings, and timestamps.\n *\n * @param value - Value to convert (Date, string, number, or null/undefined)\n * @returns Luxon DateTime object or null if invalid\n */\nconst toDateTime = (value: FieldValue): DateTime | null => {\n if (value === null || value === undefined) return null;\n\n if (value instanceof Date) {\n return DateTime.fromJSDate(value);\n }\n\n if (typeof value === \"string\") {\n const dt = DateTime.fromISO(value);\n return dt.isValid ? dt : null;\n }\n\n if (typeof value === \"number\") {\n // Assume it's a timestamp in milliseconds\n const dt = DateTime.fromMillis(value);\n return dt.isValid ? dt : null;\n }\n\n return null;\n};\n\n/**\n * Format date to a localized string with optional time and timezone.\n *\n * @param value - Date value (string, Date object, or timestamp)\n * @param showTime - Whether to include time in the output (default: false)\n * @param timezone - Optional timezone for display (e.g., \"America/New_York\")\n * @returns Formatted date string or null\n *\n * @example\n * ```typescript\n * toDateString(new Date()); // \"12/25/2023\"\n * toDateString(new Date(), true); // \"12/25/2023, 3:30 PM\"\n * toDateString(\"2023-12-25T15:30:00Z\", true, \"America/New_York\"); // \"12/25/2023, 10:30 AM\"\n * ```\n */\nexport const toDateString = (\n value: string | Date | number | null | undefined,\n showTime: boolean = false,\n timezone?: string\n): string | null => {\n if (!value) return null;\n\n const dt = toDateTime(value);\n if (!dt) return \"Invalid Date\";\n\n const dtWithZone = timezone ? dt.setZone(timezone) : dt;\n\n return showTime\n ? dtWithZone.toLocaleString(DateTime.DATETIME_SHORT)\n : dtWithZone.toLocaleString(DateTime.DATE_SHORT);\n};\n\n/**\n * Format date to relative time (e.g., \"2 hours ago\", \"in 3 days\").\n * Automatically chooses the most appropriate unit.\n *\n * @param value - Date value (string, Date object, or timestamp)\n * @returns Relative time string or null\n *\n * @example\n * ```typescript\n * toRelativeTime(new Date(Date.now() - 3600000)); // \"1 hour ago\"\n * toRelativeTime(new Date(Date.now() + 86400000)); // \"in 1 day\"\n * toRelativeTime(new Date()); // \"now\"\n * ```\n */\nexport const toRelativeTime = (value: string | Date | number | null | undefined): string | null => {\n if (!value) return null;\n\n const dt = toDateTime(value);\n if (!dt) return \"Invalid Date\";\n\n return dt.toRelative();\n};\n\n/**\n * Format date with full date and time including weekday\n */\nexport const toFullDateTime = (\n value: string | Date | number | null | undefined,\n timezone?: string\n): string | null => {\n if (!value) return null;\n\n const dt = toDateTime(value);\n if (!dt) return \"Invalid Date\";\n\n const dtWithZone = timezone ? dt.setZone(timezone) : dt;\n return dtWithZone.toLocaleString(DateTime.DATETIME_MED_WITH_WEEKDAY);\n};\n\n/**\n * Format date to ISO string\n */\nexport const toISOString = (value: string | Date | number | null | undefined): string | null => {\n if (!value) return null;\n\n const dt = toDateTime(value);\n if (!dt) return null;\n\n return dt.toISO();\n};\n\n/**\n * Format date with custom format string\n */\nexport const toCustomDateFormat = (\n value: string | Date | number | null | undefined,\n format: string,\n timezone?: string\n): string | null => {\n if (!value) return null;\n\n const dt = toDateTime(value);\n if (!dt) return \"Invalid Date\";\n\n const dtWithZone = timezone ? dt.setZone(timezone) : dt;\n return dtWithZone.toFormat(format);\n};\n\n/**\n * Get formatted date parts\n */\nexport const getDateParts = (value: string | Date | number | null | undefined) => {\n const dt = toDateTime(value);\n if (!dt) return null;\n\n return {\n year: dt.year,\n month: dt.month,\n day: dt.day,\n weekday: dt.weekday,\n hour: dt.hour,\n minute: dt.minute,\n second: dt.second,\n millisecond: dt.millisecond,\n weekdayShort: dt.weekdayShort,\n weekdayLong: dt.weekdayLong,\n monthShort: dt.monthShort,\n monthLong: dt.monthLong,\n };\n};\n\n/**\n * Format date according to DateFormat specification\n */\nexport const formatDate = (value: FieldValue, format: DateFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (value == null) return format.nullText ?? null;\n\n const dt = toDateTime(value);\n if (!dt) return format.nullText ?? \"Invalid Date\";\n\n const dtWithZone = format.timezone ? dt.setZone(format.timezone) : dt;\n\n // Handle relative time\n if (format.relative) {\n return dtWithZone.toRelative();\n }\n\n // Handle custom format string\n if (format.format) {\n return dtWithZone.toFormat(format.format);\n }\n\n // Handle style-based formatting\n if (format.dateStyle || format.timeStyle) {\n const options: Record<string, unknown> = {};\n\n if (format.dateStyle) {\n switch (format.dateStyle) {\n case \"short\":\n options.date = DateTime.DATE_SHORT;\n break;\n case \"medium\":\n options.date = DateTime.DATE_MED;\n break;\n case \"long\":\n options.date = DateTime.DATE_FULL;\n break;\n case \"full\":\n options.date = DateTime.DATE_HUGE;\n break;\n }\n }\n\n if (format.timeStyle) {\n switch (format.timeStyle) {\n case \"short\":\n options.time = DateTime.TIME_SIMPLE;\n break;\n case \"medium\":\n options.time = DateTime.TIME_WITH_SECONDS;\n break;\n case \"long\":\n case \"full\":\n options.time = DateTime.TIME_WITH_SHORT_OFFSET;\n break;\n }\n }\n\n if (options.date && options.time) {\n return dtWithZone.toLocaleString({ ...options.date, ...options.time });\n } else if (options.date) {\n return dtWithZone.toLocaleString(options.date);\n } else if (options.time) {\n return dtWithZone.toLocaleString(options.time);\n }\n }\n\n // Default formatting\n return dtWithZone.toLocaleString(DateTime.DATETIME_SHORT);\n};\n\n// Register date formatters\nFormatRegistry.register(\"date\", (value, showTime, timezone) => {\n return toDateString(\n value as string | Date | number,\n typeof showTime === \"boolean\" ? showTime : false,\n typeof timezone === \"string\" ? timezone : undefined\n );\n});\n\nFormatRegistry.register(\"relativeTime\", (value) => {\n return toRelativeTime(value as string | Date | number);\n});\n\nFormatRegistry.register(\"fullDateTime\", (value, timezone) => {\n return toFullDateTime(\n value as string | Date | number,\n typeof timezone === \"string\" ? timezone : undefined\n );\n});\n\nFormatRegistry.register(\"isoString\", (value) => {\n return toISOString(value as string | Date | number);\n});\n\nFormatRegistry.register(\"customDateFormat\", (value, format, timezone) => {\n if (typeof format === \"string\") {\n return toCustomDateFormat(\n value as string | Date | number,\n format,\n typeof timezone === \"string\" ? timezone : undefined\n );\n }\n return null;\n});\n","/**\n * Distance and length formatting utilities\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { DistanceFormat, FieldValue, FormattedValue } from \"./types\";\n\n/**\n * Format as meters\n */\nexport const toMeters = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} m`;\n};\n\n/**\n * Format as centimeters\n */\nexport const toCentimeters = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value * 100).toFixed(decimals)} cm`;\n};\n\n/**\n * Format as millimeters\n */\nexport const toMillimeters = (\n value: number | null | undefined,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n return `${(value * 1000).toFixed(decimals)} mm`;\n};\n\n/**\n * Format as kilometers\n */\nexport const toKilometers = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} km`;\n};\n\n/**\n * Format as feet\n */\nexport const toFeet = (value: number | null | undefined, decimals: number = 0): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} ft`;\n};\n\n/**\n * Format as inches\n */\nexport const toInches = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} in`;\n};\n\n/**\n * Format as miles\n */\nexport const toMiles = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} mi`;\n};\n\n/**\n * Format as yards\n */\nexport const toYards = (value: number | null | undefined, decimals: number = 0): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} yd`;\n};\n\n/**\n * Format as nautical miles\n */\nexport const toNauticalMiles = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} nm`;\n};\n\n/**\n * Conversion utilities\n */\nexport const metersToFeet = (meters: number): number => meters * 3.28084;\nexport const feetToMeters = (feet: number): number => feet / 3.28084;\nexport const milesToKilometers = (miles: number): number => miles * 1.60934;\nexport const kilometersToMiles = (km: number): number => km / 1.60934;\nexport const feetToMiles = (feet: number): number => feet / 5280;\nexport const milesToFeet = (miles: number): number => miles * 5280;\nexport const metersToMiles = (meters: number): number => meters / 1609.34;\nexport const milesToMeters = (miles: number): number => miles * 1609.34;\nexport const yardsToMeters = (yards: number): number => yards * 0.9144;\nexport const metersToYards = (meters: number): number => meters / 0.9144;\nexport const inchesToCentimeters = (inches: number): number => inches * 2.54;\nexport const centimetersToInches = (cm: number): number => cm / 2.54;\n\n/**\n * Auto-scale distance to the most appropriate unit\n */\nexport const autoScaleDistance = (\n value: number | null | undefined,\n metric: boolean = false,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (metric) {\n // Assuming value is in meters\n if (absValue >= 1000) {\n return toKilometers(value, decimals);\n } else if (absValue < 0.01) {\n return toMillimeters(value, 0);\n } else if (absValue < 1) {\n return toCentimeters(value, decimals);\n } else {\n return toMeters(value, decimals);\n }\n } else {\n // Assuming value is in miles for imperial\n if (absValue < 0.01) {\n // Convert to feet\n return toFeet(milesToFeet(value), 0);\n } else if (absValue < 0.1) {\n // Convert to yards\n return toYards(milesToFeet(value) / 3, 0);\n } else {\n return toMiles(value, decimals);\n }\n }\n};\n\n/**\n * Format distance according to DistanceFormat specification\n */\nexport const formatDistance = (value: FieldValue, format: DistanceFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals ?? 1;\n\n if (format.autoScale) {\n const isMetric = format.unit === \"m\" || format.unit === \"km\";\n return autoScaleDistance(numValue, isMetric, decimals);\n }\n\n switch (format.unit) {\n case \"km\":\n return toKilometers(numValue, decimals);\n case \"ft\":\n return toFeet(numValue, decimals);\n case \"mi\":\n return toMiles(numValue, decimals);\n case \"yd\":\n return toYards(numValue, decimals);\n case \"m\":\n default:\n return toMeters(numValue, decimals);\n }\n};\n\n// Register distance formatters\nFormatRegistry.register(\"miles\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toMiles(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\nFormatRegistry.register(\"kilometers\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toKilometers(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\nFormatRegistry.register(\"meters\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toMeters(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\nFormatRegistry.register(\"feet\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toFeet(value, typeof decimals === \"number\" ? decimals : 0);\n }\n return null;\n});\n\nFormatRegistry.register(\"yards\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toYards(value, typeof decimals === \"number\" ? decimals : 0);\n }\n return null;\n});\n\nFormatRegistry.register(\"inches\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toInches(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\nFormatRegistry.register(\"autoScaleDistance\", (value, metric, decimals) => {\n if (typeof value === \"number\") {\n return autoScaleDistance(\n value,\n typeof metric === \"boolean\" ? metric : false,\n typeof decimals === \"number\" ? decimals : 1\n );\n }\n return null;\n});\n","/**\n * Energy formatting utilities (stored or consumed energy)\n * For power (rate of energy), use power.ts\n * For electrical units (voltage, current), use voltage.ts and current.ts\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { EnergyFormat, FieldValue, FormattedValue } from \"./types\";\n\n/**\n * Format as Watt-hours\n */\nexport const toWh = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} Wh`;\n};\n\n/**\n * Format as kilowatt-hours\n */\nexport const tokWh = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} kWh`;\n};\n\n/**\n * Format as megawatt-hours\n */\nexport const toMWh = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1_000_000).toFixed(decimals)} MWh`;\n};\n\n/**\n * Format as gigawatt-hours\n */\nexport const toGWh = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1_000_000_000).toFixed(decimals)} GWh`;\n};\n\n/**\n * Auto-scale energy to the most appropriate unit\n */\nexport const autoScaleEnergy = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (absValue >= 1_000_000_000) {\n return toGWh(value, decimals);\n } else if (absValue >= 1_000_000) {\n return toMWh(value, decimals);\n } else if (absValue >= 1000) {\n return tokWh(value, decimals);\n } else {\n return toWh(value, decimals);\n }\n};\n\n// Power formatting has been moved to power.ts\n\n/**\n * Format energy according to EnergyFormat specification\n */\nexport const formatEnergy = (value: FieldValue, format: EnergyFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals ?? 1;\n\n // If a specific unit is provided, use it\n if (format.unit) {\n switch (format.unit) {\n case \"GWh\":\n return toGWh(numValue, decimals);\n case \"MWh\":\n return toMWh(numValue, decimals);\n case \"kWh\":\n return tokWh(numValue, decimals);\n case \"Wh\":\n return toWh(numValue, decimals);\n }\n }\n\n // Default to auto-scaling unless explicitly disabled\n if (format.autoScale !== false) {\n return autoScaleEnergy(numValue, decimals);\n }\n\n // If auto-scale is explicitly false and no unit specified, use base Wh\n return toWh(numValue, decimals);\n};\n\n// Electrical units have been moved to voltage.ts and current.ts\n// Resistance units (Ohms) could be moved to a separate resistance.ts if needed\n\n// Register energy and power formatters\nFormatRegistry.register(\"kWh\", (value) => {\n if (typeof value === \"number\") return tokWh(value);\n return null;\n});\n\n// Power formatters are now in power.ts\n\nFormatRegistry.register(\"autoScaleEnergy\", (value, decimals) => {\n if (typeof value === \"number\") {\n return autoScaleEnergy(value, typeof decimals === \"number\" ? decimals : 1);\n }\n return null;\n});\n\n// Auto-scale power is now in power.ts\n\n// Register the energy formatter\n// biome-ignore lint/suspicious/noExplicitAny: Required for FormatRegistry type compatibility\nFormatRegistry.register(\"energy\", formatEnergy as any);\n","/**\n * Phone number formatting utilities\n */\n\nimport { FormatRegistry } from \"./registry\";\nimport type { FieldValue, FormattedValue, PhoneFormat } from \"./types\";\n\n/**\n * Format US phone number\n */\nexport const formatUSPhone = (phone: string | null | undefined): string | null => {\n if (!phone) return null;\n\n // Remove all non-digits\n const cleaned = phone.replace(/\\D/g, \"\");\n\n // Check if it's a valid US phone number (10 or 11 digits)\n if (cleaned.length === 10) {\n return cleaned.replace(/(\\d{3})(\\d{3})(\\d{4})/, \"($1) $2-$3\");\n } else if (cleaned.length === 11 && cleaned.startsWith(\"1\")) {\n return cleaned.replace(/1(\\d{3})(\\d{3})(\\d{4})/, \"+1 ($1) $2-$3\");\n }\n\n // Return original if not a valid format\n return phone;\n};\n\n/**\n * Format international phone number\n */\nexport const formatInternationalPhone = (phone: string | null | undefined): string | null => {\n if (!phone) return null;\n\n // Remove all non-digits except +\n const cleaned = phone.replace(/[^\\d+]/g, \"\");\n\n // If it starts with +, format as international\n if (cleaned.startsWith(\"+\")) {\n // Try to format common patterns\n if (cleaned.length === 12 && cleaned.startsWith(\"+1\")) {\n // US/Canada\n return cleaned.replace(/\\+1(\\d{3})(\\d{3})(\\d{4})/, \"+1 ($1) $2-$3\");\n } else if (cleaned.length === 13 && cleaned.startsWith(\"+44\")) {\n // UK\n return cleaned.replace(/\\+44(\\d{2})(\\d{4})(\\d{4})/, \"+44 $1 $2 $3\");\n }\n // Add spaces every 3-4 digits for other countries\n return cleaned.replace(/(\\+\\d{1,3})(\\d{3,4})(\\d{3,4})(\\d{3,4})?/, \"$1 $2 $3 $4\").trim();\n }\n\n // Default to US format if no country code\n return formatUSPhone(phone);\n};\n\n/**\n * Format phone number with basic formatting\n */\nexport const formatPhoneNumber = (phone: string | null | undefined): string | null => {\n if (!phone) return null;\n\n // Try to detect if it's international\n if (phone.startsWith(\"+\") || phone.length > 11) {\n return formatInternationalPhone(phone);\n }\n\n return formatUSPhone(phone);\n};\n\n/**\n * Format phone according to PhoneFormat specification\n */\nexport const formatPhone = (value: FieldValue, format: PhoneFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (value == null) return format.nullText ?? null;\n\n const phoneStr = String(value);\n\n if (format.international) {\n return formatInternationalPhone(phoneStr);\n }\n\n // Handle specific country formats if needed\n switch (format.country) {\n case \"US\":\n case \"CA\":\n return formatUSPhone(phoneStr);\n default:\n return formatPhoneNumber(phoneStr);\n }\n};\n\n// Register formatters\nFormatRegistry.register(\"phoneNumber\", (value) => {\n if (typeof value === \"string\") {\n return formatPhoneNumber(value);\n }\n return null;\n});\n\nFormatRegistry.register(\"usPhone\", (value) => {\n if (typeof value === \"string\") {\n return formatUSPhone(value);\n }\n return null;\n});\n\nFormatRegistry.register(\"internationalPhone\", (value) => {\n if (typeof value === \"string\") {\n return formatInternationalPhone(value);\n }\n return null;\n});\n","/**\n * Power formatting utilities (rate of energy transfer)\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { FieldValue, FormattedValue, PowerFormat } from \"./types\";\n\n/**\n * Format as Watts\n */\nexport const toWatts = (value: number | null | undefined, decimals: number = 0): string | null => {\n if (isNil(value)) return null;\n return decimals === 0 ? `${Math.round(value)} W` : `${value.toFixed(decimals)} W`;\n};\n\n/**\n * Format as kilowatts\n */\nexport const toKilowatts = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} kW`;\n};\n\n/**\n * Format as megawatts\n */\nexport const toMegawatts = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1_000_000).toFixed(decimals)} MW`;\n};\n\n/**\n * Format as gigawatts\n */\nexport const toGigawatts = (\n value: number | null | undefined,\n decimals: number = 2\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1_000_000_000).toFixed(decimals)} GW`;\n};\n\n/**\n * Auto-scale power to the most appropriate unit\n */\nexport const autoScalePower = (\n value: number | null | undefined,\n decimals?: number\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (absValue >= 1_000_000_000) {\n return toGigawatts(value, decimals ?? 2);\n } else if (absValue >= 1_000_000) {\n return toMegawatts(value, decimals ?? 1);\n } else if (absValue >= 1000) {\n return toKilowatts(value, decimals ?? 1);\n } else {\n return toWatts(value, decimals ?? 0);\n }\n};\n\n/**\n * Format power according to PowerFormat specification\n */\nexport const formatPower = (value: FieldValue, format: PowerFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals;\n\n // If a specific unit is provided, use it\n if (format.unit) {\n switch (format.unit) {\n case \"GW\":\n return toGigawatts(numValue, decimals ?? 2);\n case \"MW\":\n return toMegawatts(numValue, decimals ?? 1);\n case \"kW\":\n return toKilowatts(numValue, decimals ?? 1);\n case \"W\":\n return toWatts(numValue, decimals ?? 0);\n }\n }\n\n // Default to auto-scaling unless explicitly disabled\n if (format.autoScale !== false) {\n return autoScalePower(numValue, decimals);\n }\n\n // If auto-scale is explicitly false and no unit specified, use base watts\n return toWatts(numValue, decimals ?? 0);\n};\n\n// Register the formatter\n// biome-ignore lint/suspicious/noExplicitAny: Required for FormatRegistry type compatibility\nFormatRegistry.register(\"power\", formatPower as any);\n\n// Convenience exports with shorter names\nexport const toW = toWatts;\nexport const toKW = toKilowatts;\nexport const toMW = toMegawatts;\nexport const toGW = toGigawatts;\n","/**\n * Electrical resistance formatting utilities\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { FieldValue, FormattedValue, ResistanceFormat } from \"./types\";\n\n/**\n * Format as milliohms\n */\nexport const toMilliohms = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n const mOhms = value * 1000;\n return `${mOhms.toFixed(decimals)} mΩ`;\n};\n\n/**\n * Format as ohms\n */\nexport const toOhms = (value: number | null | undefined, decimals: number = 1): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)} Ω`;\n};\n\n/**\n * Format as kilohms\n */\nexport const toKilohms = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} kΩ`;\n};\n\n/**\n * Format as megohms\n */\nexport const toMegohms = (\n value: number | null | undefined,\n decimals: number = 2\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1_000_000).toFixed(decimals)} MΩ`;\n};\n\n/**\n * Auto-scale resistance to the most appropriate unit\n */\nexport const autoScaleResistance = (\n value: number | null | undefined,\n decimals?: number\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (absValue >= 1_000_000) {\n return toMegohms(value, decimals ?? 2);\n } else if (absValue >= 1000) {\n return toKilohms(value, decimals ?? 1);\n } else if (absValue < 1) {\n return toMilliohms(value, decimals ?? 1);\n } else {\n return toOhms(value, decimals ?? 1);\n }\n};\n\n/**\n * Format resistance according to ResistanceFormat specification\n */\nexport const formatResistance = (value: FieldValue, format: ResistanceFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals;\n\n // If a specific unit is provided, use it\n if (format.unit) {\n switch (format.unit) {\n case \"MΩ\":\n return toMegohms(numValue, decimals ?? 2);\n case \"kΩ\":\n return toKilohms(numValue, decimals ?? 1);\n case \"mΩ\":\n return toMilliohms(numValue, decimals ?? 1);\n case \"Ω\":\n return toOhms(numValue, decimals ?? 1);\n }\n }\n\n // Default to auto-scaling unless explicitly disabled\n if (format.autoScale !== false) {\n return autoScaleResistance(numValue, decimals);\n }\n\n // If auto-scale is explicitly false and no unit specified, use base ohms\n return toOhms(numValue, decimals ?? 1);\n};\n\n// Register the formatter\n// biome-ignore lint/suspicious/noExplicitAny: Required for FormatRegistry type compatibility\nFormatRegistry.register(\"resistance\", formatResistance as any);\n\n// Register legacy shortcuts\nFormatRegistry.register(\"ohms\", (value) => {\n if (typeof value === \"number\") return toOhms(value);\n return null;\n});\n\nFormatRegistry.register(\"milliohms\", (value) => {\n if (typeof value === \"number\") return toMilliohms(value);\n return null;\n});\n","/**\n * Temperature formatting utilities\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type {\n FieldValue,\n FormattedValue,\n TemperatureFormat,\n TemperatureUnit,\n TemperatureUnitString,\n} from \"./types\";\n\n/**\n * Convert temperature unit string to symbol\n */\nexport const temperatureStringToSymbol = (unit: TemperatureUnitString): TemperatureUnit => {\n switch (unit) {\n case \"FAHRENHEIT\":\n return \"F\";\n case \"CELSIUS\":\n return \"C\";\n case \"KELVIN\":\n return \"K\";\n default:\n return \"F\";\n }\n};\n\n/**\n * Format as Fahrenheit\n */\nexport const toFahrenheit = (\n value: number | null | undefined,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n return `${value.toFixed(decimals)}°F`;\n};\n\n/**\n * Format as Celsius\n */\nexport const toCelsius = (\n value: number | null | undefined,\n fromFahrenheit: boolean = true,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n const celsius = fromFahrenheit ? (value - 32) * (5 / 9) : value;\n return `${celsius.toFixed(decimals)}°C`;\n};\n\n/**\n * Format as Kelvin\n */\nexport const toKelvin = (\n value: number | null | undefined,\n fromFahrenheit: boolean = true,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n const kelvin = fromFahrenheit ? (value - 32) * (5 / 9) + 273.15 : value + 273.15;\n return `${kelvin.toFixed(decimals)}K`;\n};\n\n/**\n * Convert Celsius to Fahrenheit\n */\nexport const celsiusToFahrenheit = (celsius: number): number => {\n return (celsius * 9) / 5 + 32;\n};\n\n/**\n * Convert Fahrenheit to Celsius\n */\nexport const fahrenheitToCelsius = (fahrenheit: number): number => {\n return (fahrenheit - 32) * (5 / 9);\n};\n\n/**\n * Convert Celsius to Kelvin\n */\nexport const celsiusToKelvin = (celsius: number): number => {\n return celsius + 273.15;\n};\n\n/**\n * Convert Kelvin to Celsius\n */\nexport const kelvinToCelsius = (kelvin: number): number => {\n return kelvin - 273.15;\n};\n\n/**\n * Convert Fahrenheit to Kelvin\n */\nexport const fahrenheitToKelvin = (fahrenheit: number): number => {\n return fahrenheitToCelsius(fahrenheit) + 273.15;\n};\n\n/**\n * Convert Kelvin to Fahrenheit\n */\nexport const kelvinToFahrenheit = (kelvin: number): number => {\n return celsiusToFahrenheit(kelvinToCelsius(kelvin));\n};\n\n/**\n * Format temperature with specified unit\n */\nexport const toTemperature = (\n value: number | null | undefined,\n unit: TemperatureUnit | TemperatureUnitString = \"F\",\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n\n const normalizedUnit =\n typeof unit === \"string\" && unit.length > 1\n ? temperatureStringToSymbol(unit as TemperatureUnitString)\n : (unit as TemperatureUnit);\n\n switch (normalizedUnit) {\n case \"C\":\n return toCelsius(value, true, decimals);\n case \"K\":\n return toKelvin(value, true, decimals);\n case \"F\":\n default:\n return toFahrenheit(value, decimals);\n }\n};\n\n/**\n * Format temperature according to TemperatureFormat specification\n */\nexport const formatTemperature = (value: FieldValue, format: TemperatureFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals ?? 0;\n const unit = format.unit ?? \"F\";\n\n if (format.showUnit === false) {\n const normalizedUnit =\n typeof unit === \"string\" && unit.length > 1\n ? temperatureStringToSymbol(unit as TemperatureUnitString)\n : (unit as TemperatureUnit);\n\n switch (normalizedUnit) {\n case \"C\": {\n const celsius = (numValue - 32) * (5 / 9);\n return celsius.toFixed(decimals);\n }\n case \"K\": {\n const kelvin = (numValue - 32) * (5 / 9) + 273.15;\n return kelvin.toFixed(decimals);\n }\n case \"F\":\n default:\n return numValue.toFixed(decimals);\n }\n }\n\n return toTemperature(numValue, unit, decimals);\n};\n\n// Register temperature formatters\nFormatRegistry.register(\"temperature\", (value, unit, decimals) => {\n if (typeof value === \"number\") {\n return toTemperature(\n value,\n typeof unit === \"string\" ? (unit as TemperatureUnit | TemperatureUnitString) : \"F\",\n typeof decimals === \"number\" ? decimals : 0\n );\n }\n return null;\n});\n\nFormatRegistry.register(\"fahrenheit\", (value, decimals) => {\n if (typeof value === \"number\") {\n return toFahrenheit(value, typeof decimals === \"number\" ? decimals : 0);\n }\n return null;\n});\n\nFormatRegistry.register(\"celsius\", (value, fromFahrenheit, decimals) => {\n if (typeof value === \"number\") {\n return toCelsius(\n value,\n typeof fromFahrenheit === \"boolean\" ? fromFahrenheit : true,\n typeof decimals === \"number\" ? decimals : 0\n );\n }\n return null;\n});\n\nFormatRegistry.register(\"kelvin\", (value, fromFahrenheit, decimals) => {\n if (typeof value === \"number\") {\n return toKelvin(\n value,\n typeof fromFahrenheit === \"boolean\" ? fromFahrenheit : true,\n typeof decimals === \"number\" ? decimals : 0\n );\n }\n return null;\n});\n","/**\n * Text formatting utilities\n */\n\nimport { FormatRegistry } from \"./registry\";\nimport type { FieldValue, FormattedValue, TextFormat } from \"./types\";\n\n/**\n * Check if a value should be hidden based on format rules\n */\nconst shouldHideValue = (\n value: FieldValue,\n format: { hideWhenNull?: boolean; hideWhenZero?: boolean }\n): boolean => {\n if (format.hideWhenNull && (value === null || value === undefined)) {\n return true;\n }\n if (format.hideWhenZero && value === 0) {\n return true;\n }\n return false;\n};\n\n/**\n * Convert text to uppercase\n */\nexport const toUpperCase = (text: string | null | undefined): string => {\n return text?.toUpperCase() ?? \"\";\n};\n\n/**\n * Convert text to lowercase\n */\nexport const toLowerCase = (text: string | null | undefined): string => {\n return text?.toLowerCase() ?? \"\";\n};\n\n/**\n * Convert text to sentence case (first letter capitalized, rest lowercase).\n *\n * @param text - Text to convert\n * @returns Sentence-cased text\n *\n * @example\n * ```typescript\n * toSentenceCase(\"HELLO WORLD\"); // \"Hello world\"\n * toSentenceCase(\"hello world\"); // \"Hello world\"\n * ```\n */\nexport const toSentenceCase = (text: string | null | undefined): string => {\n if (!text) return \"\";\n return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();\n};\n\n/**\n * Convert text to title case with proper handling of articles and prepositions.\n * Capitalizes the first letter of each word except common articles/prepositions\n * (unless they're the first word).\n *\n * @param text - Text to convert\n * @returns Title-cased text\n *\n * @example\n * ```typescript\n * toTitleCase(\"the quick brown fox\"); // \"The Quick Brown Fox\"\n * toTitleCase(\"war and peace\"); // \"War and Peace\"\n * toTitleCase(\"to be or not to be\"); // \"To Be or Not to Be\"\n * ```\n */\nexport const toTitleCase = (text: string | null | undefined): string => {\n if (!text) return \"\";\n const articles = new Set([\n \"a\",\n \"an\",\n \"the\",\n \"and\",\n \"but\",\n \"or\",\n \"for\",\n \"nor\",\n \"on\",\n \"at\",\n \"of\",\n \"to\",\n \"with\",\n \"in\",\n \"as\",\n \"by\",\n ]);\n\n return text\n .toLowerCase()\n .split(/\\s+/)\n .map((word, index) =>\n articles.has(word) && index !== 0 ? word : word.charAt(0).toUpperCase() + word.slice(1)\n )\n .join(\" \");\n};\n\n/**\n * Capitalize first letter of each word\n */\nexport const capitalize = (text: string | null | undefined): string => {\n if (!text) return \"\";\n return text\n .split(/\\s+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\" \");\n};\n\n/**\n * Uppercase first letter only\n */\nexport const ucFirst = (text: string | null | undefined): string => {\n if (!text) return \"\";\n return text.charAt(0).toUpperCase() + text.slice(1);\n};\n\n/**\n * Convert camelCase to words\n */\nexport const camelCaseToWords = (text: string | null | undefined): string => {\n if (!text) return \"\";\n return text\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (str) => str.toUpperCase())\n .trim();\n};\n\n/**\n * Convert snake_case to words\n */\nexport const snakeCaseToWords = (text: string | null | undefined): string => {\n if (!text) return \"\";\n return text\n .toLowerCase()\n .split(\"_\")\n .map((word) => ucFirst(word))\n .join(\" \");\n};\n\n/**\n * Convert enum-style text to sentence case\n */\nexport const enumToSentenceCase = (text: string | null | undefined): string => {\n if (!text) return \"\";\n\n // Handle snake_case\n if (text.includes(\"_\")) {\n return snakeCaseToWords(text);\n }\n\n // Handle SCREAMING_CASE\n if (text.toUpperCase() === text) {\n return ucFirst(text.toLowerCase());\n }\n\n // Handle camelCase\n return camelCaseToWords(text);\n};\n\n/**\n * Truncate text in the middle\n */\nexport const truncateMiddle = (value: string | null | undefined, length: number = 16): string => {\n if (!value) return \"\";\n\n // Handle invalid length\n if (length < 5) return value;\n\n // Handle case where specified length is longer than string\n if (value.length <= length) return value;\n\n const totalChars = length - 3; // Account for ...\n const leadingChars = Math.ceil(totalChars / 2);\n const trailingChars = Math.floor(totalChars / 2);\n\n return `${value.slice(0, leadingChars)}...${value.slice(-trailingChars)}`;\n};\n\n/**\n * Truncate text at the start\n */\nexport const truncateStart = (value: string | null | undefined, length: number = 8): string => {\n if (!value) return \"\";\n if (value.length <= length) return value;\n return `...${value.slice(-length)}`;\n};\n\n/**\n * Truncate text at the end\n */\nexport const truncateEnd = (\n value: string | null | undefined,\n length: number = 16,\n ellipsis: string = \"...\"\n): string => {\n if (!value) return \"\";\n if (value.length <= length) return value;\n return value.slice(0, length) + ellipsis;\n};\n\n/**\n * Mask sensitive text (e.g., secrets, API keys)\n */\nexport const toSecret = (value: string | null | undefined): string => {\n if (!value) return \"\";\n const str = value.toString();\n const lastFour = str.slice(-4);\n const maskedLength = str.length - 4;\n return maskedLength > 0 ? \"*\".repeat(maskedLength) + lastFour : str;\n};\n\n/**\n * Format text according to TextFormat specification\n */\nexport const formatText = (value: FieldValue, format: TextFormat): FormattedValue => {\n if (shouldHideValue(value, format)) return null;\n if (value == null) return format.nullText ?? null;\n\n let formatted = String(value);\n\n // Apply transforms\n if (format.transform) {\n const transforms = Array.isArray(format.transform) ? format.transform : [format.transform];\n\n transforms.forEach((transform) => {\n switch (transform) {\n case \"uppercase\":\n formatted = toUpperCase(formatted);\n break;\n case \"lowercase\":\n formatted = toLowerCase(formatted);\n break;\n case \"capitalize\":\n formatted = capitalize(formatted);\n break;\n case \"titleCase\":\n formatted = toTitleCase(formatted);\n break;\n case \"sentenceCase\":\n formatted = toSentenceCase(formatted);\n break;\n }\n });\n }\n\n // Apply truncation\n if (format.truncate) {\n const { length, position, ellipsis = \"...\" } = format.truncate;\n switch (position) {\n case \"start\":\n formatted = truncateStart(formatted, length);\n break;\n case \"middle\":\n formatted = truncateMiddle(formatted, length);\n break;\n case \"end\":\n formatted = truncateEnd(formatted, length, ellipsis);\n break;\n }\n }\n\n return formatted;\n};\n\n// Register text formatters\nFormatRegistry.register(\"uppercase\", (value) => toUpperCase(String(value)));\nFormatRegistry.register(\"lowercase\", (value) => toLowerCase(String(value)));\nFormatRegistry.register(\"sentenceCase\", (value) => toSentenceCase(String(value)));\nFormatRegistry.register(\"titleCase\", (value) => toTitleCase(String(value)));\nFormatRegistry.register(\"capitalize\", (value) => capitalize(String(value)));\nFormatRegistry.register(\"camelCaseToWords\", (value) => camelCaseToWords(String(value)));\nFormatRegistry.register(\"snakeCaseToWords\", (value) => snakeCaseToWords(String(value)));\nFormatRegistry.register(\"enumToSentenceCase\", (value) => enumToSentenceCase(String(value)));\nFormatRegistry.register(\"truncateMiddle\", (value, length) =>\n truncateMiddle(String(value), typeof length === \"number\" ? length : 16)\n);\nFormatRegistry.register(\"truncateStart\", (value, length) =>\n truncateStart(String(value), typeof length === \"number\" ? length : 8)\n);\nFormatRegistry.register(\"truncateEnd\", (value, length, ellipsis) =>\n truncateEnd(\n String(value),\n typeof length === \"number\" ? length : 16,\n typeof ellipsis === \"string\" ? ellipsis : \"...\"\n )\n);\nFormatRegistry.register(\"secret\", (value) => toSecret(String(value)));\n","/**\n * Voltage formatting utilities (electrical potential)\n */\n\nimport { isNil } from \"./number\";\nimport { FormatRegistry } from \"./registry\";\nimport type { FieldValue, FormattedValue, VoltageFormat } from \"./types\";\n\n/**\n * Format as millivolts\n */\nexport const toMillivolts = (\n value: number | null | undefined,\n decimals: number = 0\n): string | null => {\n if (isNil(value)) return null;\n const mV = value * 1000;\n return decimals === 0 ? `${Math.round(mV)} mV` : `${mV.toFixed(decimals)} mV`;\n};\n\n/**\n * Format as volts\n */\nexport const toVolts = (value: number | null | undefined, decimals: number = 0): string | null => {\n if (isNil(value)) return null;\n return decimals === 0 ? `${Math.round(value)} V` : `${value.toFixed(decimals)} V`;\n};\n\n/**\n * Format as kilovolts\n */\nexport const toKilovolts = (\n value: number | null | undefined,\n decimals: number = 1\n): string | null => {\n if (isNil(value)) return null;\n return `${(value / 1000).toFixed(decimals)} kV`;\n};\n\n/**\n * Auto-scale voltage to the most appropriate unit\n */\nexport const autoScaleVoltage = (\n value: number | null | undefined,\n decimals?: number\n): string | null => {\n if (isNil(value)) return null;\n\n const absValue = Math.abs(value);\n\n if (absValue >= 1000) {\n return toKilovolts(value, decimals ?? 1);\n } else if (absValue < 1) {\n return toMillivolts(value, decimals ?? 0);\n } else {\n return toVolts(value, decimals ?? 0);\n }\n};\n\n/**\n * Format voltage according to VoltageFormat specification\n */\nexport const formatVoltage = (value: FieldValue, format: VoltageFormat): FormattedValue => {\n if (format.hideWhenNull && (value === null || value === undefined)) return null;\n if (format.hideWhenZero && value === 0) return null;\n if (value == null) return format.nullText ?? null;\n\n const numValue = typeof value === \"string\" ? parseFloat(value) : Number(value);\n if (isNaN(numValue)) return format.nullText ?? null;\n\n const decimals = format.decimals;\n\n // If a specific unit is provided, use it\n if (format.unit) {\n switch (format.unit) {\n case \"kV\":\n return toKilovolts(numValue, decimals ?? 1);\n case \"mV\":\n return toMillivolts(numValue, decimals ?? 0);\n case \"V\":\n return toVolts(numValue, decimals ?? 0);\n }\n }\n\n // Default to auto-scaling unless explicitly disabled\n if (format.autoScale !== false) {\n return autoScaleVoltage(numValue, decimals);\n }\n\n // If auto-scale is explicitly false and no unit specified, use base volts\n return toVolts(numValue, decimals ?? 0);\n};\n\n// Register the formatter\n// biome-ignore lint/suspicious/noExplicitAny: Required for FormatRegistry type compatibility\nFormatRegistry.register(\"voltage\", formatVoltage as any);\n\n// Convenience exports with shorter names\nexport const toMV = toMillivolts;\nexport const toV = toVolts;\nexport const toKV = toKilovolts;\n","/**\n * Comprehensive formatting utilities for the Edges design system\n *\n * This module provides a unified formatting system with support for:\n * - Text formatting (case conversion, truncation, etc.)\n * - Number formatting (decimals, thousands separators, compact notation)\n * - Currency formatting (multiple currencies and display options)\n * - Date formatting (relative time, custom formats, timezones)\n * - Boolean formatting (custom true/false text)\n * - Energy units (Wh, kWh, MWh, GWh with auto-scaling)\n * - Temperature units (Celsius, Fahrenheit, Kelvin)\n * - Distance units (meters, kilometers, miles, feet)\n * - Phone number formatting (US and international)\n * - Custom formatters via the FormatRegistry\n */\n\nexport * from \"./boolean\";\nexport * from \"./capacity\";\nexport * from \"./component-formatter\";\nexport * from \"./current\";\nexport * from \"./date\";\nexport * from \"./distance\";\nexport * from \"./energy\";\nexport * from \"./number\";\nexport * from \"./phone\";\nexport * from \"./power\";\n// Export the registry\nexport { FormatRegistry } from \"./registry\";\nexport * from \"./resistance\";\nexport * from \"./temperature\";\n// Export all formatting utilities\nexport * from \"./text\";\n// Export all types\nexport * from \"./types\";\nexport * from \"./voltage\";\n\nimport { formatBoolean } from \"./boolean\";\nimport { formatCurrent } from \"./current\";\nimport { formatDate } from \"./date\";\nimport { formatDistance } from \"./distance\";\nimport { formatEnergy } from \"./energy\";\nimport { formatCurrency, formatNumber, formatPercent } from \"./number\";\nimport { formatPhone } from \"./phone\";\nimport { formatPower } from \"./power\";\nimport { formatResistance } from \"./resistance\";\nimport { formatTemperature } from \"./temperature\";\nimport { formatText } from \"./text\";\n// Import types for the main formatting function\nimport type {\n CustomFormat,\n FieldFormat,\n FieldValue,\n FormattedValue,\n PercentageFormat,\n} from \"./types\";\nimport { formatVoltage } from \"./voltage\";\n\n/**\n * Format a value as a percentage\n * Internal helper for the percentage format type\n */\nconst formatPercentage = (value: FieldValue, format: PercentageFormat): FormattedValue => {\n if (value == null) return format.nullText ?? null;\n if (format.hideWhenNull && value === null) return null;\n\n const num = typeof value === \"number\" ? value : Number(value);\n if (Number.isNaN(num)) return format.nullText ?? null;\n\n return formatPercent(num, format.decimals ?? 0);\n};\n\n/**\n * Main formatting function that routes to the appropriate formatter\n * based on the format type\n *\n * @param value - The value to format\n * @param format - The format specification\n * @returns The formatted value or null\n *\n * @example\n * ```typescript\n * // Format as currency\n * formatFieldValue(1234.56, { type: \"currency\", currency: \"USD\" })\n * // Returns: \"$1,234.56\"\n *\n * // Format as relative time\n * formatFieldValue(new Date(), { type: \"date\", relative: true })\n * // Returns: \"just now\"\n *\n * // Format with custom formatter\n * formatFieldValue(\"hello\", {\n * type: \"custom\",\n * formatter: (val) => String(val).toUpperCase()\n * })\n * // Returns: \"HELLO\"\n * ```\n */\nexport const formatFieldValue = (value: FieldValue, format: FieldFormat): FormattedValue => {\n switch (format.type) {\n case \"text\":\n return formatText(value, format);\n case \"number\":\n return formatNumber(value, format);\n case \"percentage\":\n return formatPercentage(value, format);\n case \"currency\":\n return formatCurrency(value, format);\n case \"date\":\n return formatDate(value, format);\n case \"boolean\":\n return formatBoolean(value, format);\n case \"energy\":\n return formatEnergy(value, format);\n case \"power\":\n return formatPower(value, format);\n case \"voltage\":\n return formatVoltage(value, format);\n case \"current\":\n return formatCurrent(value, format);\n case \"resistance\":\n return formatResistance(value, format);\n case \"temperature\":\n return formatTemperature(value, format);\n case \"distance\":\n return formatDistance(value, format);\n case \"phone\":\n return formatPhone(value, format);\n case \"custom\": {\n const customFormat = format as CustomFormat;\n if (customFormat.hideWhenNull && (value === null || value === undefined)) {\n return null;\n }\n if (value == null) return customFormat.nullText ?? null;\n return customFormat.formatter(value, customFormat.options);\n }\n default:\n // Fallback to string conversion\n return value != null ? String(value) : null;\n }\n};\n\n/**\n * Convenience function to create a format object\n *\n * @example\n * ```typescript\n * const currencyFormat = createFormat(\"currency\", { currency: \"EUR\" });\n * const dateFormat = createFormat(\"date\", { relative: true });\n * ```\n */\nexport const createFormat = <T extends FieldFormat[\"type\"]>(\n type: T,\n options?: Omit<Extract<FieldFormat, { type: T }>, \"type\">\n): Extract<FieldFormat, { type: T }> => {\n return { type, ...options } as Extract<FieldFormat, { type: T }>;\n};\n","import { scaleLinear, scaleTime } from \"@visx/scale\";\nimport { extent, max, min } from \"d3-array\";\nimport type { YFormatType } from \"../context/ChartContext\";\nimport { formatComponentValue } from \"./formatting\";\n\nexport type { YFormatType };\n\nexport interface BaseDataPoint {\n xValue: Date;\n yValue: number;\n category?: string;\n}\n\nexport interface ChartMargin {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport const defaultMargin: ChartMargin = {\n top: 0,\n right: 0,\n bottom: 50,\n left: 60,\n};\n\nexport interface YFormatSettings {\n format: (value: number) => string;\n min?: number;\n max?: number;\n tickInterval?: number;\n tickFormat?: (value: number) => string;\n}\n\n/**\n * Get Y-axis format settings from a ComponentFormatter\n * Uses the main formatting system for consistency across all components\n */\nexport function getYFormatSettings(formatter: YFormatType = { type: \"number\" }): YFormatSettings {\n const safeFormat = (value: number | null | undefined): string => {\n if (value == null) return \"-\";\n const result = formatComponentValue({ value, formatter });\n // formatComponentValue returns ReactNode, convert to string\n if (result === null) return \"-\";\n if (typeof result === \"string\") return result;\n if (typeof result === \"number\") return result.toString();\n // For React elements, try to extract text content if possible\n // This handles the case where formatComponentValue returns JSX with units\n if (typeof result === \"object\" && result !== null && \"props\" in result) {\n // Extract text from React element children\n const extractText = (node: unknown): string => {\n if (node == null) return \"\";\n if (typeof node === \"string\") return node;\n if (typeof node === \"number\") return node.toString();\n if (typeof node === \"object\" && \"props\" in node) {\n const props = (node as { props?: { children?: unknown } }).props;\n if (props?.children) {\n if (Array.isArray(props.children)) {\n return props.children.map(extractText).join(\"\");\n }\n return extractText(props.children);\n }\n }\n return \"\";\n };\n const text = extractText(result);\n return text || value.toString();\n }\n // Fallback to raw value for chart axes\n return value.toString();\n };\n\n // Create a simplified tick format for axis labels (less verbose)\n const tickFormat = (value: number | null | undefined): string => {\n if (value == null) return \"-\";\n\n // Handle string shorthand formatters\n if (typeof formatter === \"string\") {\n const result = formatComponentValue({ value, formatter });\n if (result === null) return \"-\";\n return String(result);\n }\n\n // For specific format types, provide concise axis labels\n if (typeof formatter === \"object\" && formatter.type) {\n switch (formatter.type) {\n case \"energy\":\n case \"power\":\n case \"voltage\":\n case \"current\":\n case \"resistance\":\n case \"temperature\":\n case \"distance\":\n // These formatters include units, which is good for axes\n return safeFormat(value);\n\n case \"currency\":\n // For currency, just use the standard format\n return safeFormat(value);\n\n default:\n return safeFormat(value);\n }\n }\n\n return safeFormat(value);\n };\n\n // Determine min/max/intervals based on format type\n let min: number | undefined;\n let max: number | undefined;\n let tickInterval: number | undefined;\n\n if (typeof formatter === \"object\" && formatter.type) {\n switch (formatter.type) {\n case \"number\":\n if (\"min\" in formatter) min = formatter.min as number | undefined;\n if (\"max\" in formatter) max = formatter.max as number | undefined;\n break;\n }\n }\n\n return {\n format: safeFormat,\n tickFormat,\n min,\n max,\n tickInterval,\n };\n}\n\nexport const createXScale = (data: BaseDataPoint[], width: number) => {\n const dateExtent = extent(data, (d) => d.xValue) as [Date, Date];\n return scaleTime({\n range: [defaultMargin.left, width - defaultMargin.right],\n domain: dateExtent,\n nice: true,\n });\n};\n\nexport const createYScale = (data: BaseDataPoint[], height: number, formatType: YFormatType) => {\n const yFormatSettings = getYFormatSettings(formatType);\n const dataYMin = min(data, (d) => d.yValue) || 0;\n const dataYMax = max(data, (d) => d.yValue) || 0;\n const yMin =\n yFormatSettings.min !== undefined\n ? yFormatSettings.min\n : dataYMin >= 0\n ? 0 // 0 if all positive values, min is 0\n : dataYMin * 1.1; // else scale the negative values by 10% to make room for the y-axis values\n const yMax =\n yFormatSettings.max !== undefined\n ? yFormatSettings.max\n : dataYMax <= 0\n ? 0 // If all values are negative, max is 0\n : dataYMax * 1.1; // else scale the positive values by 10% to make room for the y-axis values\n return scaleLinear({\n range: [height - defaultMargin.bottom, defaultMargin.top],\n domain: [yMin, yMax],\n nice: true,\n });\n};\n"]}
|