@nswds/app 1.103.0 → 1.104.0

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/index.js CHANGED
@@ -42,8 +42,8 @@ import * as LabelPrimitive from '@radix-ui/react-label';
42
42
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
43
43
  import * as TabsPrimitives from '@radix-ui/react-tabs';
44
44
  import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
45
+ import * as SheetPrimitive from '@radix-ui/react-dialog';
45
46
  import { Command as Command$1 } from 'cmdk';
46
- import * as DialogPrimitive from '@radix-ui/react-dialog';
47
47
  import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
48
48
  import { useReactTable, getFacetedUniqueValues, getFacetedRowModel, getSortedRowModel, getPaginationRowModel, getFilteredRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
49
49
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
@@ -16860,18 +16860,35 @@ function ColorPairingToolV2Content({ visibleFormats }) {
16860
16860
  initialState.selectedBackgroundToken
16861
16861
  );
16862
16862
  const [selectedPairId, setSelectedPairId] = useState(initialState.selectedPairId);
16863
- const themeFamilies = getPairingFamilies(themeCategory);
16864
- const context = getPairingContext(themeCategory, primaryFamilyKey, accentFamilyKey);
16865
- const selectableFamilies = themeFamilies.filter((family) => family.key !== context.grey.key);
16866
- const selectableAccentFamilies = selectableFamilies.filter(
16867
- (family) => family.key !== context.primary.key
16868
- );
16869
- const selectedBackground = context.backgrounds.find((background) => background.token === selectedBackgroundToken) ?? context.backgrounds[0] ?? null;
16870
- const selectedBackgroundPairs = selectedBackground ? context.pairsByBackground[selectedBackground.token] ?? [] : [];
16871
- const selectedPair = getPreferredPairForBackground2(selectedBackgroundPairs, selectedPairId);
16863
+ const themeFamilies = useMemo(() => getPairingFamilies(themeCategory), [themeCategory]);
16864
+ const context = useMemo(
16865
+ () => getPairingContext(themeCategory, primaryFamilyKey, accentFamilyKey),
16866
+ [themeCategory, primaryFamilyKey, accentFamilyKey]
16867
+ );
16868
+ const selectableFamilies = useMemo(
16869
+ () => themeFamilies.filter((family) => family.key !== context.grey.key),
16870
+ [themeFamilies, context.grey.key]
16871
+ );
16872
+ const selectableAccentFamilies = useMemo(
16873
+ () => selectableFamilies.filter((family) => family.key !== context.primary.key),
16874
+ [selectableFamilies, context.primary.key]
16875
+ );
16876
+ const selectedBackground = useMemo(
16877
+ () => context.backgrounds.find((background) => background.token === selectedBackgroundToken) ?? context.backgrounds[0] ?? null,
16878
+ [context.backgrounds, selectedBackgroundToken]
16879
+ );
16880
+ const selectedBackgroundPairs = useMemo(
16881
+ () => selectedBackground ? context.pairsByBackground[selectedBackground.token] ?? [] : [],
16882
+ [context.pairsByBackground, selectedBackground]
16883
+ );
16884
+ const selectedPair = useMemo(
16885
+ () => getPreferredPairForBackground2(selectedBackgroundPairs, selectedPairId),
16886
+ [selectedBackgroundPairs, selectedPairId]
16887
+ );
16872
16888
  const detailForeground = selectedPair?.foreground ?? null;
16873
- const familySummary = [context.primary.label, context.accent.label, context.grey.label].join(
16874
- " + "
16889
+ const familySummary = useMemo(
16890
+ () => [context.primary.label, context.accent.label, context.grey.label].join(" + "),
16891
+ [context.primary.label, context.accent.label, context.grey.label]
16875
16892
  );
16876
16893
  const updateUrlParams = (nextThemeCategory, nextPrimaryKey, nextAccentKey, nextSelectedBackgroundToken, nextSelectedPairId) => {
16877
16894
  const params = new URLSearchParams(window.location.search);
@@ -17174,6 +17191,1723 @@ function ColorPairingToolV2({
17174
17191
  const normalizedVisibleFormats = [...new Set(visibleFormats)];
17175
17192
  return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(ColorPairingToolV2Loading, {}), children: /* @__PURE__ */ jsx(ColorPairingToolV2Content, { visibleFormats: normalizedVisibleFormats }) });
17176
17193
  }
17194
+ function Sheet({ ...props }) {
17195
+ return /* @__PURE__ */ jsx(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
17196
+ }
17197
+ function SheetTrigger({ ...props }) {
17198
+ return /* @__PURE__ */ jsx(SheetPrimitive.Trigger, { "data-slot": "sheet-trigger", ...props });
17199
+ }
17200
+ function SheetClose({ ...props }) {
17201
+ return /* @__PURE__ */ jsx(SheetPrimitive.Close, { "data-slot": "sheet-close", ...props });
17202
+ }
17203
+ function SheetPortal({ ...props }) {
17204
+ return /* @__PURE__ */ jsx(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
17205
+ }
17206
+ function SheetOverlay({
17207
+ className,
17208
+ ...props
17209
+ }) {
17210
+ return /* @__PURE__ */ jsx(
17211
+ SheetPrimitive.Overlay,
17212
+ {
17213
+ "data-slot": "sheet-overlay",
17214
+ className: cn(
17215
+ "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
17216
+ className
17217
+ ),
17218
+ ...props
17219
+ }
17220
+ );
17221
+ }
17222
+ function SheetContent({
17223
+ className,
17224
+ children,
17225
+ side = "right",
17226
+ showClose = true,
17227
+ ...props
17228
+ }) {
17229
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [
17230
+ /* @__PURE__ */ jsx(SheetOverlay, {}),
17231
+ /* @__PURE__ */ jsxs(
17232
+ SheetPrimitive.Content,
17233
+ {
17234
+ "data-slot": "sheet-content",
17235
+ className: cn(
17236
+ "fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=closed]:animate-out data-[state=open]:duration-500 data-[state=open]:animate-in",
17237
+ side === "right" && "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
17238
+ side === "left" && "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
17239
+ side === "top" && "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
17240
+ side === "bottom" && "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
17241
+ className
17242
+ ),
17243
+ ...props,
17244
+ children: [
17245
+ children,
17246
+ showClose && /* @__PURE__ */ jsx(SheetPrimitive.Close, { "data-slot": "sheet-close", className: "absolute top-4 right-4", asChild: true, children: /* @__PURE__ */ jsxs(Button2, { variant: "ghost", size: "icon", children: [
17247
+ /* @__PURE__ */ jsx(Icons.close, { className: "size-6", "aria-hidden": "true" }),
17248
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
17249
+ ] }) })
17250
+ ]
17251
+ }
17252
+ )
17253
+ ] });
17254
+ }
17255
+ function SheetHeader({ className, ...props }) {
17256
+ return /* @__PURE__ */ jsx(
17257
+ "div",
17258
+ {
17259
+ "data-slot": "sheet-header",
17260
+ className: cn("flex flex-col gap-1.5 p-4", className),
17261
+ ...props
17262
+ }
17263
+ );
17264
+ }
17265
+ function SheetFooter({ className, ...props }) {
17266
+ return /* @__PURE__ */ jsx(
17267
+ "div",
17268
+ {
17269
+ "data-slot": "sheet-footer",
17270
+ className: cn("mt-auto flex flex-col gap-2 p-4", className),
17271
+ ...props
17272
+ }
17273
+ );
17274
+ }
17275
+ function SheetTitle({ className, ...props }) {
17276
+ return /* @__PURE__ */ jsx(
17277
+ SheetPrimitive.Title,
17278
+ {
17279
+ "data-slot": "sheet-title",
17280
+ className: cn("font-semibold text-foreground", className),
17281
+ ...props
17282
+ }
17283
+ );
17284
+ }
17285
+ function SheetDescription({
17286
+ className,
17287
+ ...props
17288
+ }) {
17289
+ return /* @__PURE__ */ jsx(
17290
+ SheetPrimitive.Description,
17291
+ {
17292
+ "data-slot": "sheet-description",
17293
+ className: cn("text-sm text-muted-foreground", className),
17294
+ ...props
17295
+ }
17296
+ );
17297
+ }
17298
+ function useSelectorHeight(selector = "header") {
17299
+ const [height, setHeight] = useState(0);
17300
+ const elementRef = useRef(null);
17301
+ const resizeObserverRef = useRef(null);
17302
+ useEffect(() => {
17303
+ const element = document.querySelector(selector);
17304
+ if (!element) return;
17305
+ elementRef.current = element;
17306
+ const resizeObserver = new ResizeObserver((entries) => {
17307
+ const entry = entries[0];
17308
+ const target = entry?.target ?? elementRef.current;
17309
+ if (!target) return;
17310
+ setHeight(target.offsetHeight);
17311
+ });
17312
+ resizeObserverRef.current = resizeObserver;
17313
+ resizeObserver.observe(element);
17314
+ return () => {
17315
+ resizeObserverRef.current?.disconnect();
17316
+ };
17317
+ }, [selector]);
17318
+ return height;
17319
+ }
17320
+
17321
+ // src/hooks/useStickyOffset.ts
17322
+ function useStickyOffset(extraPadding = 0) {
17323
+ const headerHeight = useSelectorHeight("#nsw-header");
17324
+ const navigationHeight = useSelectorHeight("#nsw-main-navigation");
17325
+ return useMemo(() => {
17326
+ const total = headerHeight + navigationHeight + extraPadding;
17327
+ return total > 0 ? total : 0;
17328
+ }, [extraPadding, headerHeight, navigationHeight]);
17329
+ }
17330
+ var PREFERRED_BACKGROUND_TONES3 = [400, 600, 200, 800, 100, 50];
17331
+ var DEFAULT_VISIBLE_FORMATS3 = ["hex", "rgb", "hsl", "oklch"];
17332
+ var DEFAULT_INITIAL_BACKGROUND_TOKEN3 = "nsw-blue-800";
17333
+ var DEFAULT_INITIAL_PAIR_ID3 = "nsw-blue-800:nsw-blue-200";
17334
+ var COLOR_PAIRING_TOOL_V3_PATH = "/core/colour/colour-pairing-tool-3";
17335
+ var AAA_NORMAL_TEXT_THRESHOLD2 = "7.0:1 for text below the WCAG large-text threshold. Sentence-case body copy should generally stay at 16px+ unless it is microcopy.";
17336
+ var AAA_LARGE_TEXT_THRESHOLD2 = "4.5:1 for WCAG large text: 24px+, or 18.5px+ bold";
17337
+ var MOBILE_RESULT_SCROLL_QUERY = "(max-width: 1023px)";
17338
+ var PERSISTENT_DRAWER_MIN_WIDTH_QUERY = "(min-width: 1280px)";
17339
+ var COLOR_PAIRING_TOOL_DRAWER_STEPS = [
17340
+ {
17341
+ id: "colours",
17342
+ title: "Choose colours",
17343
+ eyebrow: "Step 1 of 3",
17344
+ description: "Select the palette, primary family, and accent family."
17345
+ },
17346
+ {
17347
+ id: "backgrounds",
17348
+ title: "Choose background",
17349
+ eyebrow: "Step 2 of 3",
17350
+ description: "Pick the background tone that you want to pair."
17351
+ },
17352
+ {
17353
+ id: "combinations",
17354
+ title: "Choose recommended combinations",
17355
+ eyebrow: "Step 3 of 3",
17356
+ description: "Select the foreground pairing that should drive the example."
17357
+ }
17358
+ ];
17359
+ var COLOR_PAIRING_TOOL_V3_ANALYTICS_EVENT = "nsw-colour-pairing-tool-v3";
17360
+ function getToneFromToken3(token) {
17361
+ if (!token) return null;
17362
+ const match = token.match(/-(\d+)$/);
17363
+ return match ? Number.parseInt(match[1], 10) : null;
17364
+ }
17365
+ function getFamilySwatchColor3(family, preferredTone = 600) {
17366
+ const exactMatch = family.colors.find((color2) => color2.tone === preferredTone);
17367
+ if (exactMatch) {
17368
+ return exactMatch.hex;
17369
+ }
17370
+ const closestMatch = [...family.colors].sort(
17371
+ (left, right) => Math.abs(left.tone - preferredTone) - Math.abs(right.tone - preferredTone)
17372
+ )[0];
17373
+ return closestMatch?.hex ?? "transparent";
17374
+ }
17375
+ function getFamilySelectorLabel3(family, themeCategory, selectionRole) {
17376
+ if (themeCategory !== "aboriginal") {
17377
+ return family.label;
17378
+ }
17379
+ const preferredTone = selectionRole === "primary colour" ? 800 : 600;
17380
+ return family.colors.find((color2) => color2.tone === preferredTone)?.name ?? family.label;
17381
+ }
17382
+ function getPairingColorDisplayName3(color2) {
17383
+ return color2.name ?? `${color2.familyLabel} ${color2.tone}`;
17384
+ }
17385
+ function isWhiteForegroundPair3(pair) {
17386
+ return pair.foreground.token === "white";
17387
+ }
17388
+ function isLargeTextOnlyPair(pair) {
17389
+ return pair.passes.aaaLarge && !pair.passes.aaaText;
17390
+ }
17391
+ function getWhiteForegroundGuidance3(pair) {
17392
+ if (pair.passes.aaaText) {
17393
+ return "White is approved for headings, body copy, and calls to action on this background.";
17394
+ }
17395
+ if (pair.passes.aaaLarge) {
17396
+ return "Use white only for WCAG large text on this background, such as headings at 24px+ or bold text at 18.5px+. Keep sentence-case body copy at 16px+ and use a darker recommended foreground instead.";
17397
+ }
17398
+ return "Do not use white on this background. Choose one of the recommended foregrounds below instead.";
17399
+ }
17400
+ function getPreviewGuidance3(pair, isRecommended) {
17401
+ if (!isWhiteForegroundPair3(pair)) {
17402
+ return "Use only AAA-recommended combinations across your selected primary, accent, and grey families.";
17403
+ }
17404
+ if (isRecommended) {
17405
+ return "Use white text on dark colour only when it meets AAA for headings, body copy, and calls to action.";
17406
+ }
17407
+ return getWhiteForegroundGuidance3(pair);
17408
+ }
17409
+ function getPreferredPairForBackground3(pairs, preferredPairId) {
17410
+ if (preferredPairId) {
17411
+ const preferredPair = pairs.find((pair) => pair.id === preferredPairId);
17412
+ if (preferredPair) {
17413
+ return preferredPair;
17414
+ }
17415
+ }
17416
+ return pairs.find((pair) => !isWhiteForegroundPair3(pair)) ?? pairs[0] ?? null;
17417
+ }
17418
+ function getDefaultBackgroundToken3(context) {
17419
+ for (const tone of PREFERRED_BACKGROUND_TONES3) {
17420
+ for (const group of context.backgroundGroups) {
17421
+ const match = group.backgrounds.find(
17422
+ (background) => background.tone === tone && (context.pairsByBackground[background.token]?.length ?? 0) > 0
17423
+ );
17424
+ if (match) {
17425
+ return match.token;
17426
+ }
17427
+ }
17428
+ }
17429
+ for (const tone of PREFERRED_BACKGROUND_TONES3) {
17430
+ for (const group of context.backgroundGroups) {
17431
+ const match = group.backgrounds.find((background) => background.tone === tone);
17432
+ if (match) {
17433
+ return match.token;
17434
+ }
17435
+ }
17436
+ }
17437
+ return context.backgrounds[0]?.token ?? "";
17438
+ }
17439
+ function resolveBackgroundToken3(context, preferredToken, preferredTone) {
17440
+ if (preferredToken && context.backgrounds.some((background) => background.token === preferredToken)) {
17441
+ return preferredToken;
17442
+ }
17443
+ if (preferredTone !== null && preferredTone !== void 0) {
17444
+ for (const group of context.backgroundGroups) {
17445
+ const match = group.backgrounds.find((background) => background.tone === preferredTone);
17446
+ if (match) {
17447
+ return match.token;
17448
+ }
17449
+ }
17450
+ }
17451
+ return getDefaultBackgroundToken3(context);
17452
+ }
17453
+ function getInitialPairingState3(searchParams) {
17454
+ const paletteParam = searchParams.get("palette");
17455
+ const primaryParam = searchParams.get("primary");
17456
+ const accentParam = searchParams.get("accent");
17457
+ const pairParam = searchParams.get("pair");
17458
+ const backgroundParam = searchParams.get("background");
17459
+ const themeCategory = paletteParam === "brand" || paletteParam === "aboriginal" ? paletteParam : "brand";
17460
+ const context = getPairingContext(themeCategory, primaryParam, accentParam);
17461
+ const shouldUseDefaultBrandExample = !backgroundParam && !pairParam && themeCategory === "brand" && context.primary.key === "blue" && context.accent.key === "red";
17462
+ const defaultBackgroundToken = shouldUseDefaultBrandExample ? context.backgrounds.some(
17463
+ (background) => background.token === DEFAULT_INITIAL_BACKGROUND_TOKEN3
17464
+ ) ? DEFAULT_INITIAL_BACKGROUND_TOKEN3 : null : null;
17465
+ const defaultPairId = shouldUseDefaultBrandExample && defaultBackgroundToken && context.pairsByBackground[defaultBackgroundToken]?.some(
17466
+ (pair) => pair.id === DEFAULT_INITIAL_PAIR_ID3
17467
+ ) ? DEFAULT_INITIAL_PAIR_ID3 : null;
17468
+ const pairBackgroundToken = context.recommendedPairs.find((pair) => pair.id === pairParam)?.background.token ?? null;
17469
+ const selectedBackgroundToken = resolveBackgroundToken3(
17470
+ context,
17471
+ backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken,
17472
+ getToneFromToken3(backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken)
17473
+ );
17474
+ const selectedPairId = getPreferredPairForBackground3(
17475
+ context.pairsByBackground[selectedBackgroundToken] ?? [],
17476
+ pairParam ?? defaultPairId
17477
+ )?.id ?? "";
17478
+ return {
17479
+ accentKey: context.accent.key,
17480
+ primaryKey: context.primary.key,
17481
+ selectedBackgroundToken,
17482
+ selectedPairId,
17483
+ themeCategory
17484
+ };
17485
+ }
17486
+ function getReadableTextColor2(tone) {
17487
+ return tone >= 600 ? "#ffffff" : "#002664";
17488
+ }
17489
+ function getBackgroundOptionName(background) {
17490
+ return background.name ?? `${background.familyLabel} ${background.tone}`;
17491
+ }
17492
+ function getResultExplanation(pair, bestPair) {
17493
+ if (!pair) {
17494
+ return "No AAA-compliant foreground options available for this selection.";
17495
+ }
17496
+ if (pair.id === bestPair?.id) {
17497
+ return "Meets AAA for normal and large text. This is the NSW-recommended starting point for this background.";
17498
+ }
17499
+ if (isWhiteForegroundPair3(pair) && isLargeTextOnlyPair(pair)) {
17500
+ return "White meets AAA for large text on this background only. Use a darker foreground for standard body copy and smaller interface text.";
17501
+ }
17502
+ if (isWhiteForegroundPair3(pair) && !pair.passes.aaaLarge) {
17503
+ return "White does not meet AAA for normal or large text on this background. Use another approved background or a darker foreground where one is available.";
17504
+ }
17505
+ return "Meets AAA for normal and large text. This is a valid alternative, while the recommended pairing remains the clearest default.";
17506
+ }
17507
+ function getBestRecommendationReason(pair, context) {
17508
+ if (isWhiteForegroundPair3(pair)) {
17509
+ return "Recommended because this background is dark enough to support white text at AAA contrast.";
17510
+ }
17511
+ if (pair.foreground.familyKey === pair.background.familyKey) {
17512
+ return "Recommended because it stays within the same colour family while keeping clear AAA contrast.";
17513
+ }
17514
+ if (pair.foreground.familyKey === context.grey.key) {
17515
+ return "Recommended because grey provides a strong neutral contrast without competing with the background.";
17516
+ }
17517
+ if (pair.foreground.familyKey === context.accent.key) {
17518
+ return "Recommended because the selected accent family adds emphasis while preserving AAA contrast.";
17519
+ }
17520
+ if (pair.foreground.familyKey === context.primary.key) {
17521
+ return "Recommended because the selected primary family gives the clearest AAA-compliant contrast for this background.";
17522
+ }
17523
+ return "Recommended because it is the clearest NSW-approved AAA pairing for this background.";
17524
+ }
17525
+ function getRecommendationCategory(pair, bestPair, context) {
17526
+ if (pair.id === bestPair?.id) return "best";
17527
+ if (isWhiteForegroundPair3(pair)) return "white";
17528
+ if (pair.foreground.familyKey === pair.background.familyKey) return "same-family";
17529
+ if (pair.foreground.familyKey === context.accent.key) return "accent-family";
17530
+ if (pair.foreground.familyKey === context.grey.key) return "grey-option";
17531
+ if (pair.foreground.familyKey === context.primary.key) return "primary-family";
17532
+ return "approved";
17533
+ }
17534
+ function getRecommendationCategoryLabel(category) {
17535
+ switch (category) {
17536
+ case "best":
17537
+ return "Best recommended";
17538
+ case "same-family":
17539
+ return "Same family";
17540
+ case "accent-family":
17541
+ return "Accent family";
17542
+ case "grey-option":
17543
+ return "Grey option";
17544
+ case "primary-family":
17545
+ return "Primary family";
17546
+ case "white":
17547
+ return "White";
17548
+ default:
17549
+ return "Approved option";
17550
+ }
17551
+ }
17552
+ function getRecommendationSortRank(category) {
17553
+ switch (category) {
17554
+ case "best":
17555
+ return 0;
17556
+ case "same-family":
17557
+ return 1;
17558
+ case "accent-family":
17559
+ return 2;
17560
+ case "grey-option":
17561
+ return 3;
17562
+ case "white":
17563
+ return 4;
17564
+ case "primary-family":
17565
+ return 5;
17566
+ default:
17567
+ return 6;
17568
+ }
17569
+ }
17570
+ function getAvailabilityMeta(isSelected, hasPairs) {
17571
+ if (isSelected && hasPairs) {
17572
+ return {
17573
+ description: "Selected background with AAA foreground options.",
17574
+ icon: Icons.check_circle,
17575
+ label: "Selected",
17576
+ tone: "selected"
17577
+ };
17578
+ }
17579
+ if (isSelected) {
17580
+ return {
17581
+ description: "Selected background with no AAA foreground options.",
17582
+ icon: Icons.warning,
17583
+ label: "Selected, no AAA",
17584
+ tone: "unavailable"
17585
+ };
17586
+ }
17587
+ if (hasPairs) {
17588
+ return {
17589
+ description: "AAA foreground options available.",
17590
+ icon: Icons.radio_button_checked,
17591
+ label: "Available",
17592
+ tone: "available"
17593
+ };
17594
+ }
17595
+ return {
17596
+ description: "No AAA foreground available.",
17597
+ icon: Icons.close,
17598
+ label: "No AAA",
17599
+ tone: "unavailable"
17600
+ };
17601
+ }
17602
+ function getPairingCopyText(pair) {
17603
+ return [
17604
+ `Background: ${pair.background.token} (${pair.background.hex})`,
17605
+ `Foreground: ${pair.foreground.token} (${pair.foreground.hex})`,
17606
+ `Contrast ratio: ${pair.contrastRatio.toFixed(2)}:1`,
17607
+ "Accessibility: Meets AAA for normal and large text"
17608
+ ].join("\n");
17609
+ }
17610
+ function getLiveAnnouncement(pair, background) {
17611
+ if (!background) {
17612
+ return "No approved background tones available.";
17613
+ }
17614
+ if (!pair) {
17615
+ return `${background.token} selected. No AAA-compliant foreground options available for this selection.`;
17616
+ }
17617
+ if (isWhiteForegroundPair3(pair) && isLargeTextOnlyPair(pair)) {
17618
+ return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for large text only.`;
17619
+ }
17620
+ if (isWhiteForegroundPair3(pair) && !pair.passes.aaaLarge) {
17621
+ return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Fails AAA for normal and large text.`;
17622
+ }
17623
+ return `${background.token} with ${pair.foreground.token}. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for normal and large text.`;
17624
+ }
17625
+ function formatValueRows(color2, visibleFormats) {
17626
+ const hasDisplayTone = color2.token !== "white";
17627
+ return [
17628
+ { key: "token", label: "Token", value: color2.token, copyable: true },
17629
+ {
17630
+ key: "tone",
17631
+ label: "Tone",
17632
+ value: hasDisplayTone ? String(color2.tone) : "Not applicable",
17633
+ copyable: hasDisplayTone
17634
+ },
17635
+ ...visibleFormats.map((format) => ({
17636
+ key: format,
17637
+ label: format.toUpperCase(),
17638
+ value: color2[format],
17639
+ copyable: true
17640
+ }))
17641
+ ];
17642
+ }
17643
+ function SelectorButton({
17644
+ description,
17645
+ isSelected,
17646
+ label,
17647
+ onClick,
17648
+ swatch
17649
+ }) {
17650
+ return /* @__PURE__ */ jsx(
17651
+ "button",
17652
+ {
17653
+ type: "button",
17654
+ "aria-pressed": isSelected,
17655
+ onClick,
17656
+ className: cn(
17657
+ "w-full rounded-sm border px-3 py-3 text-left transition-colors focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
17658
+ isSelected ? "border-primary-800 bg-primary-50" : "border-grey-300 bg-white hover:border-primary-500 hover:bg-grey-50"
17659
+ ),
17660
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
17661
+ swatch ? /* @__PURE__ */ jsx(
17662
+ "span",
17663
+ {
17664
+ "aria-hidden": "true",
17665
+ className: "mt-0.5 size-4 shrink-0 rounded-full border border-black/10",
17666
+ style: { backgroundColor: swatch }
17667
+ }
17668
+ ) : null,
17669
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1", children: [
17670
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: label }),
17671
+ description ? /* @__PURE__ */ jsx("p", { className: "text-xs/5 text-muted-foreground", children: description }) : null
17672
+ ] })
17673
+ ] })
17674
+ }
17675
+ );
17676
+ }
17677
+ function BackgroundSwatchButton({
17678
+ background,
17679
+ hasPairs,
17680
+ isSelected,
17681
+ onClick
17682
+ }) {
17683
+ const status = getAvailabilityMeta(isSelected, hasPairs);
17684
+ const StatusIcon = status.icon;
17685
+ return /* @__PURE__ */ jsxs(
17686
+ "button",
17687
+ {
17688
+ type: "button",
17689
+ "aria-pressed": isSelected,
17690
+ "aria-label": `Select ${background.token} background. ${status.description}`,
17691
+ onClick,
17692
+ className: cn(
17693
+ "w-full rounded-sm border bg-white p-3 text-left transition-colors focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
17694
+ isSelected ? "border-primary-800 bg-primary-50" : hasPairs ? "border-grey-300 hover:border-primary-500 hover:bg-grey-50" : "border-grey-300 hover:border-grey-500"
17695
+ ),
17696
+ children: [
17697
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
17698
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
17699
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: getBackgroundOptionName(background) }),
17700
+ /* @__PURE__ */ jsx("p", { className: "mt-1 font-mono text-[0.72rem] break-all text-muted-foreground", children: background.token })
17701
+ ] }),
17702
+ /* @__PURE__ */ jsxs(
17703
+ "span",
17704
+ {
17705
+ className: cn(
17706
+ "inline-flex items-center gap-1 rounded-sm border px-2 py-1 text-[0.68rem] font-semibold uppercase",
17707
+ status.tone === "selected" && "border-primary-800 bg-primary-800 text-white dark:border-primary-500 dark:bg-primary-500",
17708
+ status.tone === "available" && "border-grey-300 bg-grey-50 text-foreground",
17709
+ status.tone === "unavailable" && "border-danger-300 bg-danger-50 text-danger-900 dark:border-danger-800 dark:bg-danger-950/20 dark:text-danger-200"
17710
+ ),
17711
+ children: [
17712
+ /* @__PURE__ */ jsx(StatusIcon, { "data-slot": "icon", className: "size-4" }),
17713
+ status.label
17714
+ ]
17715
+ }
17716
+ )
17717
+ ] }),
17718
+ /* @__PURE__ */ jsx("div", { className: "mt-3 overflow-hidden rounded-[2px] border border-black/10", children: /* @__PURE__ */ jsx("div", { className: "h-14 w-full", style: { backgroundColor: background.hex } }) }),
17719
+ /* @__PURE__ */ jsx("p", { className: "mt-3 text-xs/5 text-muted-foreground", children: status.description })
17720
+ ]
17721
+ }
17722
+ );
17723
+ }
17724
+ function ResultSummaryTile({
17725
+ children,
17726
+ className,
17727
+ label
17728
+ }) {
17729
+ return /* @__PURE__ */ jsxs("div", { className: cn("rounded-sm border border-grey-200 bg-white px-4 py-4 sm:px-5", className), children: [
17730
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-grey-700", children: label }),
17731
+ /* @__PURE__ */ jsx("div", { className: "mt-3", children })
17732
+ ] });
17733
+ }
17734
+ function AccessibilityCheckTile({
17735
+ className,
17736
+ label,
17737
+ passes,
17738
+ threshold
17739
+ }) {
17740
+ const status = passes === null ? "unavailable" : passes ? "pass" : "fail";
17741
+ return /* @__PURE__ */ jsx(
17742
+ "div",
17743
+ {
17744
+ className: cn(
17745
+ "rounded-sm border px-4 py-4 sm:px-5",
17746
+ className,
17747
+ status === "pass" && "border-success-200 bg-success-50",
17748
+ status === "fail" && "border-danger-200 bg-danger-50",
17749
+ status === "unavailable" && "border-grey-200 bg-white"
17750
+ ),
17751
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between sm:gap-4", children: [
17752
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
17753
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: label }),
17754
+ /* @__PURE__ */ jsx("p", { className: "text-sm/6 text-muted-foreground", children: status === "unavailable" ? "No contrast ratio available for this result." : threshold })
17755
+ ] }),
17756
+ /* @__PURE__ */ jsxs(
17757
+ "span",
17758
+ {
17759
+ className: cn(
17760
+ "inline-flex items-center gap-1 rounded-sm px-2.5 py-1 text-[0.72rem] font-semibold tracking-[0.12em] uppercase",
17761
+ status === "pass" && "bg-success-700 text-white",
17762
+ status === "fail" && "bg-danger-700 text-white",
17763
+ status === "unavailable" && "bg-grey-100 text-foreground"
17764
+ ),
17765
+ children: [
17766
+ status === "pass" ? /* @__PURE__ */ jsx(Icons.check, { "data-slot": "icon", className: "size-4" }) : status === "fail" ? /* @__PURE__ */ jsx(Icons.close, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsx(Icons.info, { "data-slot": "icon", className: "size-4" }),
17767
+ status === "pass" ? "Pass" : status === "fail" ? "Fail" : "Unavailable"
17768
+ ]
17769
+ }
17770
+ )
17771
+ ] })
17772
+ }
17773
+ );
17774
+ }
17775
+ function ResultColorSummary({
17776
+ color: color2,
17777
+ fallbackLabel
17778
+ }) {
17779
+ if (!color2) {
17780
+ return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: fallbackLabel ?? "Not available" });
17781
+ }
17782
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4", children: [
17783
+ /* @__PURE__ */ jsx(
17784
+ "span",
17785
+ {
17786
+ "aria-hidden": "true",
17787
+ className: "mt-1 size-6 shrink-0 rounded-full border border-black/10",
17788
+ style: { backgroundColor: color2.hex }
17789
+ }
17790
+ ),
17791
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
17792
+ /* @__PURE__ */ jsx("p", { className: "leading-7 font-semibold text-foreground", children: getPairingColorDisplayName3(color2) }),
17793
+ /* @__PURE__ */ jsx("p", { className: "mt-1 font-mono text-sm break-all text-muted-foreground", children: color2.token })
17794
+ ] })
17795
+ ] });
17796
+ }
17797
+ function CurrentResultCard({
17798
+ bestPair,
17799
+ familySummary,
17800
+ pair,
17801
+ selectedBackground
17802
+ }) {
17803
+ const previewForeground = pair?.foreground.hex ?? getReadableTextColor2(selectedBackground.tone);
17804
+ const isRecommended = pair ? pair.id === bestPair?.id : false;
17805
+ const whiteForeground = pair ? isWhiteForegroundPair3(pair) : false;
17806
+ const statusLabel = pair ? pair.passes.aaaText ? "Pass" : pair.passes.aaaLarge ? "Large text only" : "Example only" : "No recommendation";
17807
+ const fauxButtonStyle = pair ? {
17808
+ "--btn-bg": pair.foreground.hex,
17809
+ "--btn-border": pair.foreground.hex,
17810
+ "--btn-text": pair.background.hex,
17811
+ "--btn-icon": pair.background.hex,
17812
+ "--btn-hover-overlay": pair.background.hex
17813
+ } : null;
17814
+ return /* @__PURE__ */ jsxs(Card, { className: "gap-0 overflow-hidden py-0", children: [
17815
+ /* @__PURE__ */ jsx("div", { className: "border-b border-grey-200 px-4 py-4 sm:px-6 sm:py-5", children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
17816
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
17817
+ /* @__PURE__ */ jsx("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: "Current result" }),
17818
+ /* @__PURE__ */ jsx(Heading, { level: 2, size: 4, className: "text-foreground", trim: "normal", children: pair ? `${getPairingColorDisplayName3(pair.foreground)} on ${getPairingColorDisplayName3(pair.background)}` : `${getPairingColorDisplayName3(selectedBackground)} selected` })
17819
+ ] }),
17820
+ /* @__PURE__ */ jsx(Text, { size: 2, className: "max-w-3xl text-grey-700", children: getResultExplanation(pair, bestPair) })
17821
+ ] }) }),
17822
+ /* @__PURE__ */ jsx(
17823
+ "div",
17824
+ {
17825
+ className: "p-4 sm:min-h-[26rem] sm:p-8",
17826
+ style: {
17827
+ backgroundColor: selectedBackground.hex,
17828
+ color: previewForeground
17829
+ },
17830
+ children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-[18rem] flex-col justify-between gap-6 sm:min-h-[22rem] sm:gap-8", children: [
17831
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
17832
+ /* @__PURE__ */ jsxs(
17833
+ "span",
17834
+ {
17835
+ className: "inline-flex items-center gap-2 rounded-full border px-3 py-1 text-[0.68rem] font-semibold tracking-[0.16em] uppercase sm:text-[0.72rem]",
17836
+ style: {
17837
+ borderColor: pair ? pair.foreground.hex : "currentColor",
17838
+ backgroundColor: pair ? pair.foreground.hex : "transparent",
17839
+ color: pair ? pair.background.hex : "currentColor"
17840
+ },
17841
+ children: [
17842
+ /* @__PURE__ */ jsx(Icons.palette, { "data-slot": "icon", className: "size-4" }),
17843
+ familySummary
17844
+ ]
17845
+ }
17846
+ ),
17847
+ pair ? /* @__PURE__ */ jsxs(
17848
+ "span",
17849
+ {
17850
+ className: "inline-flex rounded-full border px-3 py-1 text-[0.68rem] font-semibold tracking-[0.16em] uppercase sm:text-[0.72rem]",
17851
+ style: {
17852
+ borderColor: pair.foreground.hex
17853
+ },
17854
+ children: [
17855
+ pair.rating,
17856
+ " ",
17857
+ pair.contrastRatio.toFixed(2),
17858
+ ":1"
17859
+ ]
17860
+ }
17861
+ ) : null
17862
+ ] }),
17863
+ /* @__PURE__ */ jsxs("div", { className: "max-w-xl space-y-4 pb-8 sm:pb-16", children: [
17864
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold tracking-[0.22em] uppercase", children: pair ? whiteForeground && !isRecommended ? "White on colour example" : whiteForeground ? "White on colour" : "Colour on colour" : "Approved background" }),
17865
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
17866
+ /* @__PURE__ */ jsx("h3", { className: "max-w-lg text-3xl leading-tight font-bold text-current sm:text-5xl sm:leading-none", children: "Pair colour with confidence." }),
17867
+ /* @__PURE__ */ jsx("p", { className: "max-w-full text-base/6 sm:max-w-md sm:text-base/7", children: pair ? getPreviewGuidance3(pair, isRecommended) : "This approved background tone does not currently have a recommended AAA foreground in this tool. Choose another approved background tone to continue." }),
17868
+ pair && fauxButtonStyle ? /* @__PURE__ */ jsx(
17869
+ "span",
17870
+ {
17871
+ "aria-hidden": "true",
17872
+ "data-variant": "solid",
17873
+ className: cn(
17874
+ buttonVariants({ variant: "solid", size: "default" }),
17875
+ "pointer-events-none cursor-default px-6 text-[16px] font-[700] select-none sm:px-6 sm:text-[16px] sm:font-[700]"
17876
+ ),
17877
+ style: fauxButtonStyle,
17878
+ children: "Get started"
17879
+ }
17880
+ ) : null
17881
+ ] })
17882
+ ] }),
17883
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
17884
+ /* @__PURE__ */ jsxs(
17885
+ "span",
17886
+ {
17887
+ className: "inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm font-semibold",
17888
+ style: pair ? {
17889
+ backgroundColor: pair.foreground.hex,
17890
+ color: pair.background.hex
17891
+ } : {
17892
+ backgroundColor: "rgb(255 255 255 / 0.14)",
17893
+ color: "currentColor"
17894
+ },
17895
+ children: [
17896
+ statusLabel,
17897
+ pair && pair.passes.aaaText ? /* @__PURE__ */ jsx(Icons.check, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsx(Icons.info, { "data-slot": "icon", className: "size-4" })
17898
+ ]
17899
+ }
17900
+ ),
17901
+ /* @__PURE__ */ jsx(
17902
+ "span",
17903
+ {
17904
+ className: "inline-flex max-w-full rounded-full border px-4 py-2 text-[0.82rem] break-all sm:text-sm",
17905
+ style: {
17906
+ borderColor: pair ? pair.foreground.hex : "currentColor"
17907
+ },
17908
+ children: pair ? `${pair.background.token} / ${pair.foreground.token}` : selectedBackground.token
17909
+ }
17910
+ )
17911
+ ] })
17912
+ ] })
17913
+ }
17914
+ ),
17915
+ /* @__PURE__ */ jsx("div", { className: "space-y-5 border-t border-grey-200 bg-grey-50 px-4 py-5 sm:px-6 sm:py-6", children: /* @__PURE__ */ jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
17916
+ /* @__PURE__ */ jsx(ResultSummaryTile, { label: "Background", children: /* @__PURE__ */ jsx(ResultColorSummary, { color: selectedBackground }) }),
17917
+ /* @__PURE__ */ jsx(ResultSummaryTile, { label: "Foreground", children: /* @__PURE__ */ jsx(
17918
+ ResultColorSummary,
17919
+ {
17920
+ color: pair?.foreground,
17921
+ fallbackLabel: "No AAA foreground available"
17922
+ }
17923
+ ) }),
17924
+ /* @__PURE__ */ jsxs(ResultSummaryTile, { label: "Contrast ratio", className: "lg:col-span-2", children: [
17925
+ /* @__PURE__ */ jsx("p", { className: "text-4xl leading-none font-bold text-foreground", children: pair ? `${pair.contrastRatio.toFixed(2)}:1` : "N/A" }),
17926
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: pair ? pair.passes.aaaText ? "Meets AAA accessibility" : pair.passes.aaaLarge ? "Meets AAA for large text only" : "Does not meet accessibility requirements" : "Does not meet accessibility requirements" })
17927
+ ] }),
17928
+ /* @__PURE__ */ jsx(
17929
+ AccessibilityCheckTile,
17930
+ {
17931
+ className: "lg:col-span-2",
17932
+ label: "AAA normal text",
17933
+ passes: pair ? pair.passes.aaaText : null,
17934
+ threshold: AAA_NORMAL_TEXT_THRESHOLD2
17935
+ }
17936
+ ),
17937
+ /* @__PURE__ */ jsx(
17938
+ AccessibilityCheckTile,
17939
+ {
17940
+ className: "lg:col-span-2",
17941
+ label: "AAA large text",
17942
+ passes: pair ? pair.passes.aaaLarge : null,
17943
+ threshold: AAA_LARGE_TEXT_THRESHOLD2
17944
+ }
17945
+ )
17946
+ ] }) })
17947
+ ] });
17948
+ }
17949
+ function BestRecommendationCard({
17950
+ copiedKey,
17951
+ isCurrentSelection,
17952
+ onCopyPairing,
17953
+ onUsePairing,
17954
+ pair,
17955
+ reason
17956
+ }) {
17957
+ return /* @__PURE__ */ jsxs(Card, { className: "gap-5 border-primary-200 bg-primary-50/60 px-6 py-6", children: [
17958
+ /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
17959
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
17960
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
17961
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2 rounded-sm bg-primary-800 px-3 py-1 text-[0.72rem] font-semibold tracking-[0.12em] text-white uppercase", children: [
17962
+ /* @__PURE__ */ jsx(Icons.check_circle, { "data-slot": "icon", className: "size-4" }),
17963
+ "Best recommended pairing"
17964
+ ] }),
17965
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex rounded-sm border border-primary-300 px-3 py-1 text-[0.72rem] font-semibold tracking-[0.12em] text-primary-900 uppercase", children: [
17966
+ pair.contrastRatio.toFixed(2),
17967
+ ":1"
17968
+ ] })
17969
+ ] }),
17970
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
17971
+ /* @__PURE__ */ jsxs(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: [
17972
+ pair.background.token,
17973
+ " / ",
17974
+ pair.foreground.token
17975
+ ] }),
17976
+ /* @__PURE__ */ jsx(Text, { size: 2, className: "max-w-3xl text-grey-700", children: reason })
17977
+ ] })
17978
+ ] }),
17979
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center", children: [
17980
+ isCurrentSelection ? null : /* @__PURE__ */ jsx(
17981
+ Button2,
17982
+ {
17983
+ className: "w-full justify-center sm:w-auto sm:min-w-56",
17984
+ color: "primary",
17985
+ onClick: onUsePairing,
17986
+ "aria-label": `Use ${pair.foreground.token} on ${pair.background.token}`,
17987
+ children: "Use best recommendation"
17988
+ }
17989
+ ),
17990
+ /* @__PURE__ */ jsxs(
17991
+ Button2,
17992
+ {
17993
+ className: "w-full justify-center sm:w-auto sm:min-w-48",
17994
+ variant: "outline",
17995
+ color: "grey",
17996
+ onClick: onCopyPairing,
17997
+ children: [
17998
+ /* @__PURE__ */ jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
17999
+ copiedKey === "best-pairing" ? "Pairing copied" : "Copy pairing"
18000
+ ]
18001
+ }
18002
+ )
18003
+ ] })
18004
+ ] }),
18005
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
18006
+ /* @__PURE__ */ jsx(ResultSummaryTile, { label: "Background", children: /* @__PURE__ */ jsx(ResultColorSummary, { color: pair.background }) }),
18007
+ /* @__PURE__ */ jsx(ResultSummaryTile, { label: "Foreground", children: /* @__PURE__ */ jsx(ResultColorSummary, { color: pair.foreground }) }),
18008
+ /* @__PURE__ */ jsxs(ResultSummaryTile, { label: "Accessibility", className: "md:col-span-2", children: [
18009
+ /* @__PURE__ */ jsx("p", { className: "text-xl leading-8 font-semibold text-foreground", children: "Meets AAA accessibility" }),
18010
+ /* @__PURE__ */ jsx("p", { className: "mt-3 text-base/7 text-muted-foreground", children: "Best NSW default for this background." })
18011
+ ] })
18012
+ ] })
18013
+ ] });
18014
+ }
18015
+ function RecommendationCard({
18016
+ copiedKey,
18017
+ isSelected,
18018
+ item,
18019
+ onCopyPairing,
18020
+ onSelect
18021
+ }) {
18022
+ const { pair } = item;
18023
+ return /* @__PURE__ */ jsxs(
18024
+ "div",
18025
+ {
18026
+ className: cn(
18027
+ "relative rounded-sm border bg-white p-4 text-left transition-colors focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
18028
+ isSelected ? "border-primary-800 bg-primary-50/50" : "border-grey-200 hover:border-primary-500 hover:bg-grey-50"
18029
+ ),
18030
+ children: [
18031
+ /* @__PURE__ */ jsx(
18032
+ "button",
18033
+ {
18034
+ type: "button",
18035
+ "aria-pressed": isSelected,
18036
+ "aria-label": `Use ${pair.foreground.token} on ${pair.background.token}`,
18037
+ onClick: onSelect,
18038
+ className: "absolute inset-0 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden"
18039
+ }
18040
+ ),
18041
+ /* @__PURE__ */ jsxs("div", { className: "pointer-events-none relative z-10", children: [
18042
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
18043
+ /* @__PURE__ */ jsxs(
18044
+ "span",
18045
+ {
18046
+ className: cn(
18047
+ "inline-flex items-center gap-2 rounded-sm px-2.5 py-1 text-[0.68rem] font-semibold tracking-[0.12em] uppercase",
18048
+ item.category === "best" ? "bg-primary-800 text-white" : "border border-grey-300 bg-grey-50 text-foreground"
18049
+ ),
18050
+ children: [
18051
+ item.category === "best" ? /* @__PURE__ */ jsx(Icons.check_circle, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsx(Icons.info, { "data-slot": "icon", className: "size-4" }),
18052
+ item.categoryLabel
18053
+ ]
18054
+ }
18055
+ ),
18056
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-auto shrink-0 self-start", children: /* @__PURE__ */ jsxs(
18057
+ Button2,
18058
+ {
18059
+ variant: "ghost",
18060
+ color: "grey",
18061
+ size: "sm",
18062
+ onClick: onCopyPairing,
18063
+ "aria-label": `Copy pairing ${pair.background.token} and ${pair.foreground.token}`,
18064
+ children: [
18065
+ /* @__PURE__ */ jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
18066
+ copiedKey === `pair:${pair.id}` ? "Copied" : "Copy"
18067
+ ]
18068
+ }
18069
+ ) })
18070
+ ] }),
18071
+ /* @__PURE__ */ jsxs("div", { className: "mt-4", children: [
18072
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-4 sm:grid-cols-[4rem_minmax(0,1fr)]", children: [
18073
+ /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-[2px] border border-black/10", children: [
18074
+ /* @__PURE__ */ jsx("div", { className: "h-16 w-full", style: { backgroundColor: pair.background.hex } }),
18075
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-full", style: { backgroundColor: pair.foreground.hex } })
18076
+ ] }),
18077
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-2", children: [
18078
+ /* @__PURE__ */ jsxs("div", { children: [
18079
+ /* @__PURE__ */ jsx("p", { className: "text-base font-semibold text-foreground", children: getPairingColorDisplayName3(pair.foreground) }),
18080
+ /* @__PURE__ */ jsx("p", { className: "mt-1 font-mono text-[0.74rem] break-all text-muted-foreground", children: pair.foreground.token })
18081
+ ] }),
18082
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
18083
+ pair.foreground.familyLabel,
18084
+ " on ",
18085
+ pair.background.familyLabel
18086
+ ] })
18087
+ ] })
18088
+ ] }),
18089
+ /* @__PURE__ */ jsxs("div", { className: "mt-4 flex flex-col items-start gap-3 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between", children: [
18090
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
18091
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex rounded-sm border border-grey-300 px-2.5 py-1 text-sm font-semibold text-foreground", children: [
18092
+ pair.contrastRatio.toFixed(2),
18093
+ ":1"
18094
+ ] }),
18095
+ /* @__PURE__ */ jsx("span", { className: "inline-flex rounded-sm bg-success-700 px-2.5 py-1 text-[0.72rem] font-semibold tracking-[0.12em] text-white uppercase", children: "AAA" })
18096
+ ] }),
18097
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-primary-800", children: isSelected ? "Selected" : "Use pairing" })
18098
+ ] })
18099
+ ] })
18100
+ ] })
18101
+ ]
18102
+ }
18103
+ );
18104
+ }
18105
+ function TechnicalDetailsPanel({
18106
+ color: color2,
18107
+ copiedKey,
18108
+ onCopyValue,
18109
+ title,
18110
+ visibleFormats
18111
+ }) {
18112
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-sm border border-grey-200 bg-white", children: [
18113
+ /* @__PURE__ */ jsxs("div", { className: "border-b border-grey-200 px-4 py-4 sm:px-5", children: [
18114
+ /* @__PURE__ */ jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: title }),
18115
+ color2 ? /* @__PURE__ */ jsxs(Fragment, { children: [
18116
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: getPairingColorDisplayName3(color2) }),
18117
+ /* @__PURE__ */ jsx("div", { className: "mt-4 overflow-hidden rounded-sm border border-black/10 bg-white", children: /* @__PURE__ */ jsx("div", { className: "h-20 w-full sm:h-24", style: { backgroundColor: color2.hex } }) })
18118
+ ] }) : /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "No AAA foreground available." })
18119
+ ] }),
18120
+ color2 ? /* @__PURE__ */ jsx("div", { className: "divide-y divide-grey-200", children: formatValueRows(color2, visibleFormats).map((row) => {
18121
+ const copyKey = `${title}-${row.key}`;
18122
+ return /* @__PURE__ */ jsxs(
18123
+ "div",
18124
+ {
18125
+ className: "flex flex-col items-start gap-3 px-4 py-4 sm:flex-row sm:items-start sm:justify-between sm:gap-4 sm:px-5",
18126
+ children: [
18127
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
18128
+ /* @__PURE__ */ jsx("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: row.label }),
18129
+ /* @__PURE__ */ jsx(
18130
+ "p",
18131
+ {
18132
+ className: cn(
18133
+ "mt-2 text-sm text-foreground",
18134
+ row.key !== "tone" && "font-mono break-all"
18135
+ ),
18136
+ children: row.value
18137
+ }
18138
+ )
18139
+ ] }),
18140
+ row.copyable ? /* @__PURE__ */ jsx(
18141
+ Button2,
18142
+ {
18143
+ variant: "ghost",
18144
+ color: "grey",
18145
+ size: "sm",
18146
+ className: "self-start",
18147
+ onClick: () => onCopyValue(copyKey, row.value, `${row.label} copied`),
18148
+ "aria-label": `Copy ${title.toLowerCase()} ${row.label.toLowerCase()}`,
18149
+ children: copiedKey === copyKey ? /* @__PURE__ */ jsxs(Fragment, { children: [
18150
+ /* @__PURE__ */ jsx(Icons.check_circle, { "data-slot": "icon", className: "size-5" }),
18151
+ "Copied"
18152
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
18153
+ /* @__PURE__ */ jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
18154
+ "Copy"
18155
+ ] })
18156
+ }
18157
+ ) : null
18158
+ ]
18159
+ },
18160
+ row.key
18161
+ );
18162
+ }) }) : /* @__PURE__ */ jsx("div", { className: "px-5 py-5", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No technical values are shown because there is no AAA-compliant foreground for this background." }) })
18163
+ ] });
18164
+ }
18165
+ function resolveSelectionState(nextThemeCategory, nextPrimaryKey, nextAccentKey, preferredBackgroundToken, preferredPairId) {
18166
+ const context = getPairingContext(nextThemeCategory, nextPrimaryKey, nextAccentKey);
18167
+ const selectedBackgroundToken = resolveBackgroundToken3(
18168
+ context,
18169
+ preferredBackgroundToken,
18170
+ getToneFromToken3(preferredBackgroundToken)
18171
+ );
18172
+ const selectedPairId = getPreferredPairForBackground3(
18173
+ context.pairsByBackground[selectedBackgroundToken] ?? [],
18174
+ preferredPairId
18175
+ )?.id ?? "";
18176
+ return {
18177
+ accentKey: context.accent.key,
18178
+ context,
18179
+ primaryKey: context.primary.key,
18180
+ selectedBackgroundToken,
18181
+ selectedPairId,
18182
+ themeCategory: nextThemeCategory
18183
+ };
18184
+ }
18185
+ function ColorPairingToolV3Loading() {
18186
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-8 xl:grid-cols-[minmax(18rem,24rem)_minmax(0,1fr)]", children: [
18187
+ /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
18188
+ /* @__PURE__ */ jsx("div", { className: "h-52 rounded-sm border border-grey-200 bg-grey-50" }),
18189
+ /* @__PURE__ */ jsx("div", { className: "h-[32rem] rounded-sm border border-grey-200 bg-grey-50" })
18190
+ ] }),
18191
+ /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
18192
+ /* @__PURE__ */ jsx("div", { className: "h-96 rounded-sm border border-grey-200 bg-grey-50" }),
18193
+ /* @__PURE__ */ jsx("div", { className: "h-64 rounded-sm border border-grey-200 bg-grey-50" }),
18194
+ /* @__PURE__ */ jsx("div", { className: "h-72 rounded-sm border border-grey-200 bg-grey-50" })
18195
+ ] })
18196
+ ] });
18197
+ }
18198
+ function ColorPairingToolV3Content({
18199
+ onAnalyticsEvent,
18200
+ visibleFormats
18201
+ }) {
18202
+ const searchParams = useSearchParams();
18203
+ const stickyOffset = useStickyOffset(24);
18204
+ const [initialState] = useState(() => getInitialPairingState3(searchParams));
18205
+ const [themeCategory, setThemeCategory] = useState(initialState.themeCategory);
18206
+ const [primaryFamilyKey, setPrimaryFamilyKey] = useState(initialState.primaryKey);
18207
+ const [accentFamilyKey, setAccentFamilyKey] = useState(initialState.accentKey);
18208
+ const [selectedBackgroundToken, setSelectedBackgroundToken] = useState(
18209
+ initialState.selectedBackgroundToken
18210
+ );
18211
+ const [selectedPairId, setSelectedPairId] = useState(initialState.selectedPairId);
18212
+ const [drawerStepIndex, setDrawerStepIndex] = useState(0);
18213
+ const [isCompactControlsOpen, setIsCompactControlsOpen] = useState(false);
18214
+ const [, copyToClipboardRaw] = useCopyToClipboard();
18215
+ const [copiedKey, setCopiedKey] = useState(null);
18216
+ const copiedKeyTimeoutRef = useRef(null);
18217
+ const resultSectionRef = useRef(null);
18218
+ const noValidStateRef = useRef(/* @__PURE__ */ new Set());
18219
+ const technicalDetailsOpenedRef = useRef(false);
18220
+ const emitAnalyticsEvent = useCallback(
18221
+ (event) => {
18222
+ onAnalyticsEvent(event);
18223
+ if (typeof window !== "undefined") {
18224
+ window.dispatchEvent(
18225
+ new CustomEvent(COLOR_PAIRING_TOOL_V3_ANALYTICS_EVENT, {
18226
+ detail: event
18227
+ })
18228
+ );
18229
+ }
18230
+ },
18231
+ [onAnalyticsEvent]
18232
+ );
18233
+ useEffect(() => {
18234
+ return () => {
18235
+ if (copiedKeyTimeoutRef.current) {
18236
+ clearTimeout(copiedKeyTimeoutRef.current);
18237
+ }
18238
+ };
18239
+ }, []);
18240
+ useEffect(() => {
18241
+ if (typeof window === "undefined") {
18242
+ return;
18243
+ }
18244
+ const mediaQuery = window.matchMedia(PERSISTENT_DRAWER_MIN_WIDTH_QUERY);
18245
+ const handleChange = (event) => {
18246
+ if (event?.matches ?? mediaQuery.matches) {
18247
+ setIsCompactControlsOpen(false);
18248
+ }
18249
+ };
18250
+ handleChange();
18251
+ mediaQuery.addEventListener("change", handleChange);
18252
+ return () => {
18253
+ mediaQuery.removeEventListener("change", handleChange);
18254
+ };
18255
+ }, []);
18256
+ const themeFamilies = useMemo(() => getPairingFamilies(themeCategory), [themeCategory]);
18257
+ const context = useMemo(
18258
+ () => getPairingContext(themeCategory, primaryFamilyKey, accentFamilyKey),
18259
+ [themeCategory, primaryFamilyKey, accentFamilyKey]
18260
+ );
18261
+ const selectableFamilies = useMemo(
18262
+ () => themeFamilies.filter((family) => family.key !== context.grey.key),
18263
+ [themeFamilies, context.grey.key]
18264
+ );
18265
+ const selectableAccentFamilies = useMemo(
18266
+ () => selectableFamilies.filter((family) => family.key !== context.primary.key),
18267
+ [selectableFamilies, context.primary.key]
18268
+ );
18269
+ const selectedBackground = useMemo(
18270
+ () => context.backgrounds.find((background) => background.token === selectedBackgroundToken) ?? context.backgrounds[0] ?? null,
18271
+ [context.backgrounds, selectedBackgroundToken]
18272
+ );
18273
+ const selectedBackgroundPairs = useMemo(
18274
+ () => selectedBackground ? context.pairsByBackground[selectedBackground.token] ?? [] : [],
18275
+ [context.pairsByBackground, selectedBackground]
18276
+ );
18277
+ const bestRecommendedPair = useMemo(
18278
+ () => getPreferredPairForBackground3(selectedBackgroundPairs),
18279
+ [selectedBackgroundPairs]
18280
+ );
18281
+ const selectedPair = useMemo(
18282
+ () => getPreferredPairForBackground3(selectedBackgroundPairs, selectedPairId),
18283
+ [selectedBackgroundPairs, selectedPairId]
18284
+ );
18285
+ const whiteForegroundExample = useMemo(
18286
+ () => selectedBackground && supportsWhiteForegroundPreview(selectedBackground) ? getWhiteForegroundPair(selectedBackground) : null,
18287
+ [selectedBackground]
18288
+ );
18289
+ const previewPair = selectedPair ?? whiteForegroundExample ?? null;
18290
+ const detailForeground = selectedPair?.foreground ?? whiteForegroundExample?.foreground ?? null;
18291
+ const familySummary = useMemo(
18292
+ () => [context.primary.label, context.accent.label, context.grey.label].join(" + "),
18293
+ [context.accent.label, context.grey.label, context.primary.label]
18294
+ );
18295
+ const recommendationItems = useMemo(() => {
18296
+ return selectedBackgroundPairs.map((pair) => {
18297
+ const category = getRecommendationCategory(pair, bestRecommendedPair, context);
18298
+ return {
18299
+ category,
18300
+ categoryLabel: getRecommendationCategoryLabel(category),
18301
+ pair
18302
+ };
18303
+ }).sort(
18304
+ (left, right) => getRecommendationSortRank(left.category) - getRecommendationSortRank(right.category)
18305
+ );
18306
+ }, [bestRecommendedPair, context, selectedBackgroundPairs]);
18307
+ const liveAnnouncement = useMemo(
18308
+ () => getLiveAnnouncement(previewPair, selectedBackground),
18309
+ [previewPair, selectedBackground]
18310
+ );
18311
+ const shareBackgroundToken = selectedBackground?.token ?? selectedBackgroundToken;
18312
+ const shareUrl = useMemo(() => {
18313
+ const params = new URLSearchParams();
18314
+ params.set("palette", themeCategory);
18315
+ params.set("primary", context.primary.key);
18316
+ params.set("accent", context.accent.key);
18317
+ if (shareBackgroundToken) {
18318
+ params.set("background", shareBackgroundToken);
18319
+ }
18320
+ if (selectedPairId) {
18321
+ params.set("pair", selectedPairId);
18322
+ }
18323
+ const query = params.toString();
18324
+ return `${COLOR_PAIRING_TOOL_V3_PATH}${query ? `?${query}` : ""}`;
18325
+ }, [context.accent.key, context.primary.key, shareBackgroundToken, selectedPairId, themeCategory]);
18326
+ const activeDrawerStep = COLOR_PAIRING_TOOL_DRAWER_STEPS[drawerStepIndex];
18327
+ const isFirstDrawerStep = drawerStepIndex === 0;
18328
+ const isLastDrawerStep = drawerStepIndex === COLOR_PAIRING_TOOL_DRAWER_STEPS.length - 1;
18329
+ const desktopSidebarStyle = useMemo(
18330
+ () => ({
18331
+ "--tool-sidebar-max-height": `calc(100vh - ${stickyOffset}px)`,
18332
+ "--tool-sidebar-top": `${stickyOffset}px`
18333
+ }),
18334
+ [stickyOffset]
18335
+ );
18336
+ const goToDrawerStep = useCallback((stepIndex) => {
18337
+ setDrawerStepIndex(Math.max(0, Math.min(stepIndex, COLOR_PAIRING_TOOL_DRAWER_STEPS.length - 1)));
18338
+ }, []);
18339
+ const goToNextDrawerStep = useCallback(() => {
18340
+ setDrawerStepIndex(
18341
+ (currentStep) => Math.min(currentStep + 1, COLOR_PAIRING_TOOL_DRAWER_STEPS.length - 1)
18342
+ );
18343
+ }, []);
18344
+ const goToPreviousDrawerStep = useCallback(() => {
18345
+ setDrawerStepIndex((currentStep) => Math.max(currentStep - 1, 0));
18346
+ }, []);
18347
+ const updateUrlParams = useCallback((nextState) => {
18348
+ const params = new URLSearchParams(window.location.search);
18349
+ params.delete("family");
18350
+ params.set("palette", nextState.themeCategory);
18351
+ params.set("primary", nextState.primaryKey);
18352
+ params.set("accent", nextState.accentKey);
18353
+ params.set("background", nextState.selectedBackgroundToken);
18354
+ if (nextState.selectedPairId) {
18355
+ params.set("pair", nextState.selectedPairId);
18356
+ } else {
18357
+ params.delete("pair");
18358
+ }
18359
+ window.history.replaceState(
18360
+ null,
18361
+ "",
18362
+ `${window.location.pathname}?${params.toString()}${window.location.hash}`
18363
+ );
18364
+ }, []);
18365
+ const applyResolvedSelection = useCallback(
18366
+ (nextState) => {
18367
+ setThemeCategory(nextState.themeCategory);
18368
+ setPrimaryFamilyKey(nextState.primaryKey);
18369
+ setAccentFamilyKey(nextState.accentKey);
18370
+ setSelectedBackgroundToken(nextState.selectedBackgroundToken);
18371
+ setSelectedPairId(nextState.selectedPairId);
18372
+ updateUrlParams(nextState);
18373
+ },
18374
+ [updateUrlParams]
18375
+ );
18376
+ const buildAnalyticsContext = useCallback(
18377
+ (overrides) => ({
18378
+ accentKey: context.accent.key,
18379
+ backgroundToken: selectedBackground?.token,
18380
+ foregroundToken: selectedPair?.foreground.token,
18381
+ pairId: selectedPair?.id,
18382
+ palette: themeCategory,
18383
+ primaryKey: context.primary.key,
18384
+ ...overrides
18385
+ }),
18386
+ [context.accent.key, context.primary.key, selectedBackground, selectedPair, themeCategory]
18387
+ );
18388
+ const copyValue = useCallback(
18389
+ (copyKey, value, toastLabel, analyticsEvent) => {
18390
+ copyToClipboardRaw(value);
18391
+ setCopiedKey(copyKey);
18392
+ toast(toastLabel, { duration: 2e3 });
18393
+ if (analyticsEvent) {
18394
+ emitAnalyticsEvent(analyticsEvent);
18395
+ }
18396
+ if (copiedKeyTimeoutRef.current) {
18397
+ clearTimeout(copiedKeyTimeoutRef.current);
18398
+ }
18399
+ copiedKeyTimeoutRef.current = setTimeout(() => {
18400
+ setCopiedKey(null);
18401
+ copiedKeyTimeoutRef.current = null;
18402
+ }, 2e3);
18403
+ },
18404
+ [copyToClipboardRaw, emitAnalyticsEvent]
18405
+ );
18406
+ const handleThemeCategoryChange = (nextThemeCategory) => {
18407
+ const nextState = resolveSelectionState(
18408
+ nextThemeCategory,
18409
+ primaryFamilyKey,
18410
+ accentFamilyKey,
18411
+ selectedBackgroundToken,
18412
+ selectedPairId
18413
+ );
18414
+ applyResolvedSelection(nextState);
18415
+ emitAnalyticsEvent({
18416
+ name: "palette_change",
18417
+ accentKey: nextState.accentKey,
18418
+ backgroundToken: nextState.selectedBackgroundToken,
18419
+ pairId: nextState.selectedPairId,
18420
+ palette: nextState.themeCategory,
18421
+ primaryKey: nextState.primaryKey
18422
+ });
18423
+ };
18424
+ const handlePrimaryColorChange = (nextPrimaryKey) => {
18425
+ const nextAccentKey = nextPrimaryKey === accentFamilyKey ? getDefaultAccentFamilyKey(themeCategory, nextPrimaryKey) : accentFamilyKey;
18426
+ const nextState = resolveSelectionState(
18427
+ themeCategory,
18428
+ nextPrimaryKey,
18429
+ nextAccentKey,
18430
+ selectedBackgroundToken,
18431
+ selectedPairId
18432
+ );
18433
+ applyResolvedSelection(nextState);
18434
+ emitAnalyticsEvent({
18435
+ name: "primary_change",
18436
+ accentKey: nextState.accentKey,
18437
+ backgroundToken: nextState.selectedBackgroundToken,
18438
+ pairId: nextState.selectedPairId,
18439
+ palette: nextState.themeCategory,
18440
+ primaryKey: nextState.primaryKey
18441
+ });
18442
+ };
18443
+ const handleAccentColorChange = (nextAccentKey) => {
18444
+ if (nextAccentKey === primaryFamilyKey) return;
18445
+ const nextState = resolveSelectionState(
18446
+ themeCategory,
18447
+ primaryFamilyKey,
18448
+ nextAccentKey,
18449
+ selectedBackgroundToken,
18450
+ selectedPairId
18451
+ );
18452
+ applyResolvedSelection(nextState);
18453
+ emitAnalyticsEvent({
18454
+ name: "accent_change",
18455
+ accentKey: nextState.accentKey,
18456
+ backgroundToken: nextState.selectedBackgroundToken,
18457
+ pairId: nextState.selectedPairId,
18458
+ palette: nextState.themeCategory,
18459
+ primaryKey: nextState.primaryKey
18460
+ });
18461
+ };
18462
+ const handleBackgroundChange = (nextSelectedBackgroundToken) => {
18463
+ const nextSelectedPairId = getPreferredPairForBackground3(
18464
+ context.pairsByBackground[nextSelectedBackgroundToken] ?? [],
18465
+ selectedPairId
18466
+ )?.id ?? "";
18467
+ const nextState = {
18468
+ accentKey: context.accent.key,
18469
+ context,
18470
+ primaryKey: context.primary.key,
18471
+ selectedBackgroundToken: nextSelectedBackgroundToken,
18472
+ selectedPairId: nextSelectedPairId,
18473
+ themeCategory
18474
+ };
18475
+ applyResolvedSelection(nextState);
18476
+ emitAnalyticsEvent({
18477
+ name: "background_selection",
18478
+ ...buildAnalyticsContext({
18479
+ backgroundToken: nextSelectedBackgroundToken,
18480
+ foregroundToken: context.pairsByBackground[nextSelectedBackgroundToken]?.find(
18481
+ (pair) => pair.id === nextSelectedPairId
18482
+ )?.foreground.token,
18483
+ pairId: nextSelectedPairId
18484
+ })
18485
+ });
18486
+ if (typeof window !== "undefined" && window.matchMedia(MOBILE_RESULT_SCROLL_QUERY).matches) {
18487
+ requestAnimationFrame(() => {
18488
+ resultSectionRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
18489
+ });
18490
+ }
18491
+ };
18492
+ const handlePairChange = (nextSelectedPairId, source) => {
18493
+ if (!selectedBackground) return;
18494
+ const nextPair = selectedBackgroundPairs.find((pair) => pair.id === nextSelectedPairId) ?? null;
18495
+ setSelectedPairId(nextSelectedPairId);
18496
+ updateUrlParams({
18497
+ accentKey: context.accent.key,
18498
+ context,
18499
+ primaryKey: context.primary.key,
18500
+ selectedBackgroundToken: selectedBackground.token,
18501
+ selectedPairId: nextSelectedPairId,
18502
+ themeCategory
18503
+ });
18504
+ emitAnalyticsEvent({
18505
+ name: "foreground_selection",
18506
+ ...buildAnalyticsContext({
18507
+ foregroundToken: nextPair?.foreground.token,
18508
+ pairId: nextSelectedPairId,
18509
+ source
18510
+ })
18511
+ });
18512
+ if (bestRecommendedPair && nextSelectedPairId !== bestRecommendedPair.id) {
18513
+ emitAnalyticsEvent({
18514
+ name: "alternative_combination_selected",
18515
+ ...buildAnalyticsContext({
18516
+ foregroundToken: nextPair?.foreground.token,
18517
+ pairId: nextSelectedPairId,
18518
+ source
18519
+ })
18520
+ });
18521
+ }
18522
+ };
18523
+ useEffect(() => {
18524
+ if (!selectedBackground || selectedBackgroundPairs.length > 0) {
18525
+ return;
18526
+ }
18527
+ const key = `${themeCategory}:${context.primary.key}:${context.accent.key}:${selectedBackground.token}`;
18528
+ if (noValidStateRef.current.has(key)) {
18529
+ return;
18530
+ }
18531
+ noValidStateRef.current.add(key);
18532
+ emitAnalyticsEvent({
18533
+ name: "no_valid_combination_state",
18534
+ ...buildAnalyticsContext({
18535
+ backgroundToken: selectedBackground.token
18536
+ })
18537
+ });
18538
+ }, [
18539
+ buildAnalyticsContext,
18540
+ context.accent.key,
18541
+ context.primary.key,
18542
+ emitAnalyticsEvent,
18543
+ selectedBackground,
18544
+ selectedBackgroundPairs.length,
18545
+ themeCategory
18546
+ ]);
18547
+ useEffect(() => {
18548
+ if (technicalDetailsOpenedRef.current) {
18549
+ return;
18550
+ }
18551
+ technicalDetailsOpenedRef.current = true;
18552
+ emitAnalyticsEvent({
18553
+ name: "technical_details_opened",
18554
+ ...buildAnalyticsContext({
18555
+ source: "details"
18556
+ })
18557
+ });
18558
+ }, [buildAnalyticsContext, emitAnalyticsEvent]);
18559
+ if (!selectedBackground) {
18560
+ return /* @__PURE__ */ jsxs(Card, { className: "px-6 py-6", children: [
18561
+ /* @__PURE__ */ jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "No approved background tones available" }),
18562
+ /* @__PURE__ */ jsx(Text, { size: 2, className: "mt-3", children: "No approved tones are available for the current palette and colour selection." })
18563
+ ] });
18564
+ }
18565
+ const compactControlsSummary = `${themeCategory === "brand" ? "Brand" : "Aboriginal"} palette, ${context.primary.label} primary, ${context.accent.label} accent, ${getPairingColorDisplayName3(
18566
+ selectedBackground
18567
+ )} background.`;
18568
+ const renderControlsPanel = (isOverlay = false) => /* @__PURE__ */ jsxs(Fragment, { children: [
18569
+ /* @__PURE__ */ jsx("div", { className: "border-b border-grey-200 px-5 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
18570
+ /* @__PURE__ */ jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
18571
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
18572
+ !isFirstDrawerStep ? /* @__PURE__ */ jsxs(Button2, { variant: "ghost", color: "grey", size: "sm", onClick: goToPreviousDrawerStep, children: [
18573
+ /* @__PURE__ */ jsx(Icons.west, { "data-slot": "icon", className: "size-5" }),
18574
+ "Back"
18575
+ ] }) : null,
18576
+ isOverlay ? /* @__PURE__ */ jsx(
18577
+ Button2,
18578
+ {
18579
+ variant: "ghost",
18580
+ color: "grey",
18581
+ size: "icon",
18582
+ onClick: () => setIsCompactControlsOpen(false),
18583
+ "aria-label": "Close configuration",
18584
+ children: /* @__PURE__ */ jsx(Icons.close, { "data-slot": "icon", className: "size-5" })
18585
+ }
18586
+ ) : null
18587
+ ] })
18588
+ ] }) }),
18589
+ /* @__PURE__ */ jsxs("div", { className: "border-b border-grey-200 px-5 py-4", children: [
18590
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
18591
+ COLOR_PAIRING_TOOL_DRAWER_STEPS.map((step, index) => /* @__PURE__ */ jsx(
18592
+ "button",
18593
+ {
18594
+ type: "button",
18595
+ "aria-current": index === drawerStepIndex ? "step" : void 0,
18596
+ "aria-label": `${step.eyebrow}: ${step.title}`,
18597
+ onClick: () => goToDrawerStep(index),
18598
+ className: "flex-1 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
18599
+ children: /* @__PURE__ */ jsx(
18600
+ "span",
18601
+ {
18602
+ className: cn(
18603
+ "block h-1.5 rounded-full transition-colors",
18604
+ index <= drawerStepIndex ? "bg-primary-800" : "bg-grey-200"
18605
+ )
18606
+ }
18607
+ )
18608
+ },
18609
+ step.id
18610
+ )),
18611
+ /* @__PURE__ */ jsx("span", { className: "mt-2 basis-full text-[0.68rem] font-semibold tracking-[0.12em] text-primary-800 uppercase sm:mt-0 sm:ml-2 sm:basis-auto sm:text-[0.72rem]", children: activeDrawerStep.eyebrow })
18612
+ ] }),
18613
+ /* @__PURE__ */ jsxs("div", { className: "mt-4 space-y-2", children: [
18614
+ /* @__PURE__ */ jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: activeDrawerStep.title }),
18615
+ /* @__PURE__ */ jsx(Text, { size: 2, children: activeDrawerStep.description })
18616
+ ] })
18617
+ ] }),
18618
+ /* @__PURE__ */ jsx("div", { className: "relative flex-1 overflow-hidden", children: /* @__PURE__ */ jsxs(
18619
+ "div",
18620
+ {
18621
+ className: "flex h-full transition-transform duration-300 ease-out",
18622
+ style: { transform: `translateX(-${drawerStepIndex * 100}%)` },
18623
+ children: [
18624
+ /* @__PURE__ */ jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsxs("div", { className: "space-y-6 pr-1", children: [
18625
+ /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
18626
+ /* @__PURE__ */ jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Palette" }),
18627
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: ["brand", "aboriginal"].map((palette) => {
18628
+ const isSelected = themeCategory === palette;
18629
+ const label = palette === "brand" ? "Brand palette" : "Aboriginal palette";
18630
+ return /* @__PURE__ */ jsx(
18631
+ SelectorButton,
18632
+ {
18633
+ label,
18634
+ isSelected,
18635
+ onClick: () => handleThemeCategoryChange(palette)
18636
+ },
18637
+ palette
18638
+ );
18639
+ }) })
18640
+ ] }),
18641
+ /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
18642
+ /* @__PURE__ */ jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Primary colour family" }),
18643
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableFamilies.map((family) => {
18644
+ const label = getFamilySelectorLabel3(family, themeCategory, "primary colour");
18645
+ return /* @__PURE__ */ jsx(
18646
+ SelectorButton,
18647
+ {
18648
+ label,
18649
+ isSelected: family.key === context.primary.key,
18650
+ onClick: () => handlePrimaryColorChange(family.key),
18651
+ swatch: getFamilySwatchColor3(family, 800)
18652
+ },
18653
+ family.key
18654
+ );
18655
+ }) })
18656
+ ] }),
18657
+ /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
18658
+ /* @__PURE__ */ jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Accent colour family" }),
18659
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableAccentFamilies.map((family) => {
18660
+ const label = getFamilySelectorLabel3(family, themeCategory, "accent colour");
18661
+ return /* @__PURE__ */ jsx(
18662
+ SelectorButton,
18663
+ {
18664
+ label,
18665
+ isSelected: family.key === context.accent.key,
18666
+ onClick: () => handleAccentColorChange(family.key),
18667
+ swatch: getFamilySwatchColor3(family, 600)
18668
+ },
18669
+ family.key
18670
+ );
18671
+ }) })
18672
+ ] }),
18673
+ /* @__PURE__ */ jsxs("div", { className: "border-t border-grey-200 pt-4", children: [
18674
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: "Grey is always included" }),
18675
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Neutral grey options are automatically added so every selection includes a practical fallback family." })
18676
+ ] })
18677
+ ] }) }),
18678
+ /* @__PURE__ */ jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsx("div", { className: "space-y-6 pr-1", children: context.backgroundGroups.map((group, index) => /* @__PURE__ */ jsxs(
18679
+ "section",
18680
+ {
18681
+ className: cn("space-y-3", index > 0 && "border-t border-grey-200 pt-6"),
18682
+ children: [
18683
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
18684
+ /* @__PURE__ */ jsxs(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: [
18685
+ group.family.label,
18686
+ " backgrounds"
18687
+ ] }),
18688
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: group.label })
18689
+ ] }),
18690
+ /* @__PURE__ */ jsx("div", { className: "grid gap-3", children: group.backgrounds.map((background) => /* @__PURE__ */ jsx(
18691
+ BackgroundSwatchButton,
18692
+ {
18693
+ background,
18694
+ hasPairs: (context.pairsByBackground[background.token]?.length ?? 0) > 0,
18695
+ isSelected: selectedBackground.token === background.token,
18696
+ onClick: () => handleBackgroundChange(background.token)
18697
+ },
18698
+ background.token
18699
+ )) })
18700
+ ]
18701
+ },
18702
+ group.key
18703
+ )) }) }),
18704
+ /* @__PURE__ */ jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsx("div", { className: "space-y-4 pr-1", children: recommendationItems.length > 0 ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: recommendationItems.map((item) => /* @__PURE__ */ jsx(
18705
+ RecommendationCard,
18706
+ {
18707
+ copiedKey,
18708
+ item,
18709
+ isSelected: item.pair.id === selectedPair?.id,
18710
+ onCopyPairing: () => copyValue(
18711
+ `pair:${item.pair.id}`,
18712
+ getPairingCopyText(item.pair),
18713
+ "Pairing copied",
18714
+ item.pair.id === bestRecommendedPair?.id ? {
18715
+ name: "best_recommendation_copied",
18716
+ ...buildAnalyticsContext({
18717
+ foregroundToken: item.pair.foreground.token,
18718
+ pairId: item.pair.id,
18719
+ source: "recommendations-list"
18720
+ })
18721
+ } : void 0
18722
+ ),
18723
+ onSelect: () => handlePairChange(item.pair.id, "recommendations-list")
18724
+ },
18725
+ item.pair.id
18726
+ )) }) : /* @__PURE__ */ jsxs("div", { className: "rounded-sm border border-grey-200 bg-white px-5 py-5", children: [
18727
+ /* @__PURE__ */ jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "No valid combinations available" }),
18728
+ /* @__PURE__ */ jsx(Text, { size: 2, className: "mt-3", children: "No AAA-compliant foreground options are available for this background." })
18729
+ ] }) }) })
18730
+ ]
18731
+ }
18732
+ ) }),
18733
+ /* @__PURE__ */ jsx("div", { className: "border-t border-grey-200 px-5 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
18734
+ /* @__PURE__ */ jsx("div", { className: "min-h-10 flex-1", children: isLastDrawerStep ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Select a combination to update the result immediately." }) : null }),
18735
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-2 sm:w-auto sm:flex-none", children: [
18736
+ isOverlay && isLastDrawerStep ? /* @__PURE__ */ jsx(
18737
+ Button2,
18738
+ {
18739
+ color: "primary",
18740
+ className: "w-full sm:w-auto sm:min-w-40",
18741
+ onClick: () => setIsCompactControlsOpen(false),
18742
+ children: "Review result"
18743
+ }
18744
+ ) : null,
18745
+ !isLastDrawerStep ? /* @__PURE__ */ jsxs(Button2, { color: "primary", className: "w-full sm:w-auto", onClick: goToNextDrawerStep, children: [
18746
+ "Continue",
18747
+ /* @__PURE__ */ jsx(Icons.east, { "data-slot": "icon", className: "size-5" })
18748
+ ] }) : null
18749
+ ] })
18750
+ ] }) })
18751
+ ] });
18752
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-8 xl:grid-cols-[minmax(18rem,24rem)_minmax(0,1fr)]", children: [
18753
+ /* @__PURE__ */ jsx(
18754
+ "div",
18755
+ {
18756
+ "data-slot": "tool-sidebar",
18757
+ className: "hidden xl:sticky xl:top-[var(--tool-sidebar-top)] xl:block xl:self-start",
18758
+ style: desktopSidebarStyle,
18759
+ children: /* @__PURE__ */ jsx(Card, { className: "h-[40rem] max-h-[40rem] gap-0 overflow-hidden py-0 sm:h-[44rem] sm:max-h-[44rem] xl:h-[var(--tool-sidebar-max-height)] xl:max-h-[var(--tool-sidebar-max-height)]", children: renderControlsPanel() })
18760
+ }
18761
+ ),
18762
+ /* @__PURE__ */ jsxs("div", { "data-slot": "tool-results", className: "space-y-6", children: [
18763
+ /* @__PURE__ */ jsxs("section", { className: "space-y-4 xl:hidden", children: [
18764
+ /* @__PURE__ */ jsx(Card, { className: "gap-4 px-5 py-5", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between", children: [
18765
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
18766
+ /* @__PURE__ */ jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
18767
+ /* @__PURE__ */ jsx(Text, { size: 2, children: "Open the colour pairing drawer to change palette, background, and recommended combinations." }),
18768
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: compactControlsSummary })
18769
+ ] }),
18770
+ /* @__PURE__ */ jsxs(
18771
+ Button2,
18772
+ {
18773
+ color: "primary",
18774
+ className: "w-full sm:w-auto",
18775
+ onClick: () => setIsCompactControlsOpen(true),
18776
+ children: [
18777
+ /* @__PURE__ */ jsx(Icons.edit_square, { "data-slot": "icon", className: "size-5" }),
18778
+ "Open configuration"
18779
+ ]
18780
+ }
18781
+ )
18782
+ ] }) }),
18783
+ /* @__PURE__ */ jsx(Sheet, { open: isCompactControlsOpen, onOpenChange: setIsCompactControlsOpen, children: /* @__PURE__ */ jsxs(
18784
+ SheetContent,
18785
+ {
18786
+ side: "left",
18787
+ showClose: false,
18788
+ className: "w-[30rem] max-w-[90vw] overflow-hidden p-0",
18789
+ children: [
18790
+ /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Colour pairing configuration" }),
18791
+ /* @__PURE__ */ jsx("div", { className: "flex h-full flex-col bg-background", children: renderControlsPanel(true) })
18792
+ ]
18793
+ }
18794
+ ) })
18795
+ ] }),
18796
+ /* @__PURE__ */ jsxs("section", { ref: resultSectionRef, className: "space-y-6", "aria-label": "Current result", children: [
18797
+ /* @__PURE__ */ jsx("div", { className: "sr-only", "aria-live": "polite", children: liveAnnouncement }),
18798
+ /* @__PURE__ */ jsx(
18799
+ CurrentResultCard,
18800
+ {
18801
+ bestPair: bestRecommendedPair,
18802
+ familySummary,
18803
+ pair: previewPair,
18804
+ selectedBackground
18805
+ }
18806
+ )
18807
+ ] }),
18808
+ bestRecommendedPair ? /* @__PURE__ */ jsx("section", { className: "space-y-4", children: /* @__PURE__ */ jsx(
18809
+ BestRecommendationCard,
18810
+ {
18811
+ copiedKey,
18812
+ isCurrentSelection: selectedPair?.id === bestRecommendedPair.id,
18813
+ pair: bestRecommendedPair,
18814
+ reason: getBestRecommendationReason(bestRecommendedPair, context),
18815
+ onCopyPairing: () => copyValue(
18816
+ "best-pairing",
18817
+ getPairingCopyText(bestRecommendedPair),
18818
+ "Pairing copied",
18819
+ {
18820
+ name: "best_recommendation_copied",
18821
+ ...buildAnalyticsContext({
18822
+ foregroundToken: bestRecommendedPair.foreground.token,
18823
+ pairId: bestRecommendedPair.id,
18824
+ source: "best-recommendation"
18825
+ })
18826
+ }
18827
+ ),
18828
+ onUsePairing: () => handlePairChange(bestRecommendedPair.id, "best-recommendation")
18829
+ }
18830
+ ) }) : /* @__PURE__ */ jsxs(Card, { className: "px-6 py-6", children: [
18831
+ /* @__PURE__ */ jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Best recommended pairing" }),
18832
+ /* @__PURE__ */ jsx(Text, { size: 2, className: "mt-3", children: "No AAA-compliant foreground options available for this selection." })
18833
+ ] }),
18834
+ /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
18835
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
18836
+ /* @__PURE__ */ jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Technical colour values" }),
18837
+ /* @__PURE__ */ jsx(Text, { size: 2, children: "Token, tone, HEX, RGB, HSL, and OKLCH values for the current selection." })
18838
+ ] }),
18839
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
18840
+ /* @__PURE__ */ jsx(
18841
+ TechnicalDetailsPanel,
18842
+ {
18843
+ title: "Background values",
18844
+ color: selectedBackground,
18845
+ visibleFormats,
18846
+ copiedKey,
18847
+ onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
18848
+ }
18849
+ ),
18850
+ /* @__PURE__ */ jsx(
18851
+ TechnicalDetailsPanel,
18852
+ {
18853
+ title: "Foreground values",
18854
+ color: detailForeground,
18855
+ visibleFormats,
18856
+ copiedKey,
18857
+ onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
18858
+ }
18859
+ )
18860
+ ] }),
18861
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
18862
+ /* @__PURE__ */ jsx(Heading, { level: 3, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Share colour pairing" }),
18863
+ /* @__PURE__ */ jsxs("div", { className: "rounded-sm border border-grey-200 bg-white p-4", children: [
18864
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
18865
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Copy this URL to share your current colour pairing:" }),
18866
+ /* @__PURE__ */ jsx(
18867
+ Button2,
18868
+ {
18869
+ variant: "ghost",
18870
+ color: "grey",
18871
+ size: "sm",
18872
+ className: "shrink-0",
18873
+ onClick: () => copyValue(
18874
+ "share-url",
18875
+ typeof window === "undefined" ? shareUrl : new URL(shareUrl, window.location.origin).toString(),
18876
+ "Colour pairing link copied"
18877
+ ),
18878
+ "aria-label": copiedKey === "share-url" ? "Colour pairing URL copied to clipboard" : "Copy colour pairing URL to clipboard",
18879
+ title: copiedKey === "share-url" ? "Copied" : "Copy URL",
18880
+ children: copiedKey === "share-url" ? /* @__PURE__ */ jsxs(Fragment, { children: [
18881
+ /* @__PURE__ */ jsx(Icons.check, { "data-slot": "icon", className: "size-5" }),
18882
+ "Copied"
18883
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
18884
+ /* @__PURE__ */ jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
18885
+ "Copy URL"
18886
+ ] })
18887
+ }
18888
+ )
18889
+ ] }),
18890
+ /* @__PURE__ */ jsx("code", { className: "mt-3 block w-full rounded-sm border border-grey-200 bg-background px-3 py-2 font-mono text-[11px] break-all text-foreground sm:text-xs", children: shareUrl })
18891
+ ] })
18892
+ ] })
18893
+ ] })
18894
+ ] })
18895
+ ] });
18896
+ }
18897
+ function ColorPairingToolV3({
18898
+ onAnalyticsEvent = () => {
18899
+ },
18900
+ visibleFormats = DEFAULT_VISIBLE_FORMATS3
18901
+ } = {}) {
18902
+ const normalizedVisibleFormats = [...new Set(visibleFormats)];
18903
+ return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(ColorPairingToolV3Loading, {}), children: /* @__PURE__ */ jsx(
18904
+ ColorPairingToolV3Content,
18905
+ {
18906
+ onAnalyticsEvent,
18907
+ visibleFormats: normalizedVisibleFormats
18908
+ }
18909
+ ) });
18910
+ }
17177
18911
  function ColorSwatches({ theme: theme2, format, viewMode }) {
17178
18912
  return /* @__PURE__ */ jsx(
17179
18913
  "div",
@@ -18087,23 +19821,23 @@ var ComboChart = React5__default.forwardRef((props, forwardedRef) => {
18087
19821
  });
18088
19822
  ComboChart.displayName = "ComboChart";
18089
19823
  function Dialog({ ...props }) {
18090
- return /* @__PURE__ */ jsx(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
19824
+ return /* @__PURE__ */ jsx(SheetPrimitive.Root, { "data-slot": "dialog", ...props });
18091
19825
  }
18092
19826
  function DialogTrigger({ ...props }) {
18093
- return /* @__PURE__ */ jsx(DialogPrimitive.Trigger, { "data-slot": "dialog-trigger", ...props });
19827
+ return /* @__PURE__ */ jsx(SheetPrimitive.Trigger, { "data-slot": "dialog-trigger", ...props });
18094
19828
  }
18095
19829
  function DialogPortal({ ...props }) {
18096
- return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
19830
+ return /* @__PURE__ */ jsx(SheetPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
18097
19831
  }
18098
19832
  function DialogClose({ ...props }) {
18099
- return /* @__PURE__ */ jsx(DialogPrimitive.Close, { "data-slot": "dialog-close", ...props });
19833
+ return /* @__PURE__ */ jsx(SheetPrimitive.Close, { "data-slot": "dialog-close", ...props });
18100
19834
  }
18101
19835
  function DialogOverlay({
18102
19836
  className,
18103
19837
  ...props
18104
19838
  }) {
18105
19839
  return /* @__PURE__ */ jsx(
18106
- DialogPrimitive.Overlay,
19840
+ SheetPrimitive.Overlay,
18107
19841
  {
18108
19842
  "data-slot": "dialog-overlay",
18109
19843
  className: cn(
@@ -18123,7 +19857,7 @@ function DialogContent({
18123
19857
  return /* @__PURE__ */ jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [
18124
19858
  /* @__PURE__ */ jsx(DialogOverlay, {}),
18125
19859
  /* @__PURE__ */ jsxs(
18126
- DialogPrimitive.Content,
19860
+ SheetPrimitive.Content,
18127
19861
  {
18128
19862
  "data-slot": "dialog-content",
18129
19863
  className: cn(
@@ -18133,7 +19867,7 @@ function DialogContent({
18133
19867
  ...props,
18134
19868
  children: [
18135
19869
  children,
18136
- showClose && /* @__PURE__ */ jsx(DialogPrimitive.Close, { className: "absolute top-1 right-1", asChild: true, children: /* @__PURE__ */ jsxs(Button2, { variant: "ghost", size: "icon", children: [
19870
+ showClose && /* @__PURE__ */ jsx(SheetPrimitive.Close, { className: "absolute top-1 right-1", asChild: true, children: /* @__PURE__ */ jsxs(Button2, { variant: "ghost", size: "icon", children: [
18137
19871
  /* @__PURE__ */ jsx(Icons.close, { className: "size-6", "aria-hidden": "true" }),
18138
19872
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
18139
19873
  ] }) })
@@ -18164,7 +19898,7 @@ function DialogFooter({ className, ...props }) {
18164
19898
  }
18165
19899
  function DialogTitle({ className, ...props }) {
18166
19900
  return /* @__PURE__ */ jsx(
18167
- DialogPrimitive.Title,
19901
+ SheetPrimitive.Title,
18168
19902
  {
18169
19903
  "data-slot": "dialog-title",
18170
19904
  className: cn("text-lg leading-none font-semibold", className),
@@ -18177,7 +19911,7 @@ function DialogDescription({
18177
19911
  ...props
18178
19912
  }) {
18179
19913
  return /* @__PURE__ */ jsx(
18180
- DialogPrimitive.Description,
19914
+ SheetPrimitive.Description,
18181
19915
  {
18182
19916
  "data-slot": "dialog-description",
18183
19917
  className: cn("text-sm text-muted-foreground", className),
@@ -19446,7 +21180,7 @@ function FieldLabel({
19446
21180
  }
19447
21181
  );
19448
21182
  }
19449
- function Description4({
21183
+ function Description5({
19450
21184
  className,
19451
21185
  ...props
19452
21186
  }) {
@@ -19798,7 +21532,7 @@ function FormatToggle({ format, setFormat }) {
19798
21532
 
19799
21533
  // package.json
19800
21534
  var package_default = {
19801
- version: "1.102.0"};
21535
+ version: "1.103.0"};
19802
21536
  function Logo(props) {
19803
21537
  return /* @__PURE__ */ jsxs(Fragment, { children: [
19804
21538
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: "NSW Government" }),
@@ -21070,28 +22804,6 @@ function Loading() {
21070
22804
  /* @__PURE__ */ jsx(Text, { children: "Loading..." })
21071
22805
  ] });
21072
22806
  }
21073
- function useSelectorHeight(selector = "header") {
21074
- const [height, setHeight] = useState(0);
21075
- const elementRef = useRef(null);
21076
- const resizeObserverRef = useRef(null);
21077
- useEffect(() => {
21078
- const element = document.querySelector(selector);
21079
- if (!element) return;
21080
- elementRef.current = element;
21081
- const resizeObserver = new ResizeObserver((entries) => {
21082
- const entry = entries[0];
21083
- const target = entry?.target ?? elementRef.current;
21084
- if (!target) return;
21085
- setHeight(target.offsetHeight);
21086
- });
21087
- resizeObserverRef.current = resizeObserver;
21088
- resizeObserver.observe(element);
21089
- return () => {
21090
- resizeObserverRef.current?.disconnect();
21091
- };
21092
- }, [selector]);
21093
- return height;
21094
- }
21095
22807
  function MainNavigation({ navigation }) {
21096
22808
  const headerHeight = useSelectorHeight();
21097
22809
  return /* @__PURE__ */ jsx(
@@ -30856,110 +32568,6 @@ function ResizableHandle({
30856
32568
  }
30857
32569
  );
30858
32570
  }
30859
- function Sheet({ ...props }) {
30860
- return /* @__PURE__ */ jsx(DialogPrimitive.Root, { "data-slot": "sheet", ...props });
30861
- }
30862
- function SheetTrigger({ ...props }) {
30863
- return /* @__PURE__ */ jsx(DialogPrimitive.Trigger, { "data-slot": "sheet-trigger", ...props });
30864
- }
30865
- function SheetClose({ ...props }) {
30866
- return /* @__PURE__ */ jsx(DialogPrimitive.Close, { "data-slot": "sheet-close", ...props });
30867
- }
30868
- function SheetPortal({ ...props }) {
30869
- return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
30870
- }
30871
- function SheetOverlay({
30872
- className,
30873
- ...props
30874
- }) {
30875
- return /* @__PURE__ */ jsx(
30876
- DialogPrimitive.Overlay,
30877
- {
30878
- "data-slot": "sheet-overlay",
30879
- className: cn(
30880
- "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
30881
- className
30882
- ),
30883
- ...props
30884
- }
30885
- );
30886
- }
30887
- function SheetContent({
30888
- className,
30889
- children,
30890
- side = "right",
30891
- showClose = true,
30892
- ...props
30893
- }) {
30894
- return /* @__PURE__ */ jsxs(SheetPortal, { children: [
30895
- /* @__PURE__ */ jsx(SheetOverlay, {}),
30896
- /* @__PURE__ */ jsxs(
30897
- DialogPrimitive.Content,
30898
- {
30899
- "data-slot": "sheet-content",
30900
- className: cn(
30901
- "fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=closed]:animate-out data-[state=open]:duration-500 data-[state=open]:animate-in",
30902
- side === "right" && "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
30903
- side === "left" && "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
30904
- side === "top" && "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
30905
- side === "bottom" && "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
30906
- className
30907
- ),
30908
- ...props,
30909
- children: [
30910
- children,
30911
- showClose && /* @__PURE__ */ jsx(DialogPrimitive.Close, { "data-slot": "sheet-close", className: "absolute top-4 right-4", asChild: true, children: /* @__PURE__ */ jsxs(Button2, { variant: "ghost", size: "icon", children: [
30912
- /* @__PURE__ */ jsx(Icons.close, { className: "size-6", "aria-hidden": "true" }),
30913
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
30914
- ] }) })
30915
- ]
30916
- }
30917
- )
30918
- ] });
30919
- }
30920
- function SheetHeader({ className, ...props }) {
30921
- return /* @__PURE__ */ jsx(
30922
- "div",
30923
- {
30924
- "data-slot": "sheet-header",
30925
- className: cn("flex flex-col gap-1.5 p-4", className),
30926
- ...props
30927
- }
30928
- );
30929
- }
30930
- function SheetFooter({ className, ...props }) {
30931
- return /* @__PURE__ */ jsx(
30932
- "div",
30933
- {
30934
- "data-slot": "sheet-footer",
30935
- className: cn("mt-auto flex flex-col gap-2 p-4", className),
30936
- ...props
30937
- }
30938
- );
30939
- }
30940
- function SheetTitle({ className, ...props }) {
30941
- return /* @__PURE__ */ jsx(
30942
- DialogPrimitive.Title,
30943
- {
30944
- "data-slot": "sheet-title",
30945
- className: cn("font-semibold text-foreground", className),
30946
- ...props
30947
- }
30948
- );
30949
- }
30950
- function SheetDescription({
30951
- className,
30952
- ...props
30953
- }) {
30954
- return /* @__PURE__ */ jsx(
30955
- DialogPrimitive.Description,
30956
- {
30957
- "data-slot": "sheet-description",
30958
- className: cn("text-sm text-muted-foreground", className),
30959
- ...props
30960
- }
30961
- );
30962
- }
30963
32571
  function Skeleton({ className, ...props }) {
30964
32572
  return /* @__PURE__ */ jsx(
30965
32573
  "div",
@@ -35687,13 +37295,24 @@ function getHeadings(slugify = slugifyWithCounter()) {
35687
37295
  });
35688
37296
  return result;
35689
37297
  }
35690
- function usePageHeadings() {
37298
+ function areHeadingTreesEqual(left, right) {
37299
+ return JSON.stringify(left) === JSON.stringify(right);
37300
+ }
37301
+ function usePageHeadings(enabled = true) {
35691
37302
  const [headings, setHeadings] = useState([]);
35692
37303
  const pathname = usePathname();
35693
37304
  const observerRef = useRef(null);
35694
37305
  const observedElRef = useRef(null);
35695
37306
  useEffect(() => {
35696
- const update = () => setHeadings(getHeadings());
37307
+ if (!enabled) {
37308
+ return;
37309
+ }
37310
+ const update = () => {
37311
+ const nextHeadings = getHeadings();
37312
+ setHeadings(
37313
+ (currentHeadings) => areHeadingTreesEqual(currentHeadings, nextHeadings) ? currentHeadings : nextHeadings
37314
+ );
37315
+ };
35697
37316
  const attachToCurrentArticle = () => {
35698
37317
  const article = document.querySelector("article");
35699
37318
  if (!article || observedElRef.current === article) return;
@@ -35740,16 +37359,8 @@ function usePageHeadings() {
35740
37359
  observerRef.current = null;
35741
37360
  observedElRef.current = null;
35742
37361
  };
35743
- }, [pathname]);
35744
- return headings;
35745
- }
35746
- function useStickyOffset(extraPadding = 0) {
35747
- const headerHeight = useSelectorHeight("#nsw-header");
35748
- const navigationHeight = useSelectorHeight("#nsw-main-navigation");
35749
- return useMemo(() => {
35750
- const total = headerHeight + navigationHeight + extraPadding;
35751
- return total > 0 ? total : 0;
35752
- }, [extraPadding, headerHeight, navigationHeight]);
37362
+ }, [enabled, pathname]);
37363
+ return enabled ? headings : [];
35753
37364
  }
35754
37365
  function createFormStore(opts) {
35755
37366
  const { storageKey, initialFormData, initialFormStatus } = opts;
@@ -35796,6 +37407,6 @@ var languages = [
35796
37407
  "html"
35797
37408
  ];
35798
37409
 
35799
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Action2 as Action, Actions, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AreaChart, Artifact, ArtifactAction, ArtifactActions, ArtifactContent, ArtifactDescription, ArtifactHeader, ArtifactTitle, AspectRatio, AuthLayout, AvailableChartColors, Avatar, AvatarFallback, AvatarImage, Badge, BadgeButton, BarChart, BarList, BaseColorSwatches, Branch, BranchMessages, BranchNext, BranchPage, BranchPrevious, BranchSelector, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Breadcrumbs, Button2 as Button, Calendar, CalendarDayButton, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, CategoryBar, ChainOfThought, ChainOfThoughtContent, ChainOfThoughtHeader, ChainOfThoughtImage, ChainOfThoughtSearchResult, ChainOfThoughtSearchResults, ChainOfThoughtStep, ChartContainer, ChartLegend3 as ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip3 as ChartTooltip, ChartTooltipContent, Checkbox, CheckboxSmall, Code, CodeBlock, CodeBlockCopyButton, CodeDemo, CodeHighlight, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorCard, ColorPairingTool, ColorPairingToolV2, ColorSwatches, ColourScale, ComboChart, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Context, ContextCacheUsage, ContextContent, ContextContentBody, ContextContentFooter, ContextContentHeader, ContextInputUsage, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ContextOutputUsage, ContextReasoningUsage, ContextTrigger, Conversation, ConversationContent, ConversationEmptyState, ConversationScrollButton, DataTable, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableToolbar, DataTableViewOptions, Description4 as Description, DescriptionDetails, DescriptionList, DescriptionTerm, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DonutChart, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, DynamicFavicon, ErrorMessage, ExpandableSearch, ExpandableSearchField, Field2 as Field, FieldGroup, FieldLabel, Fieldset2 as Fieldset, Footer, FooterAcknowledgement, FooterLegalLinks, FooterSmallPrint, FooterSocialLink, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, FormatToggle, GenerateInterpolatedColors, Header2 as Header, Heading, HeroBannerSupportingImage, HoverCard, HoverCardContent, HoverCardTrigger, Icons, Image4 as Image, InlineCitation, InlineCitationCard, InlineCitationCardBody, InlineCitationCardTrigger, InlineCitationCarousel, InlineCitationCarouselContent, InlineCitationCarouselHeader, InlineCitationCarouselIndex, InlineCitationCarouselItem, InlineCitationSource, InlineCitationText, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Label5 as Label, Legend6 as Legend, LineChart, Link, _List as List, Listbox2 as Listbox, ListboxDescription, ListboxLabel, ListboxOption2 as ListboxOption, Loader, Loading, Logo, MainNavigation, Masthead, MegaMenu, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Message, MessageContent, MobileHeader, MobileSearch, MultiLevelPushMenu, NSWCard, NSWCardArrow, NSWCardDescription, NSWCardIcon, NSWCardImg, NSWCardTitle, Navbar, NavbarDivider, NavbarItem, NavbarLabel, NavbarSection, NavbarSpacer, Navigation, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NotFound, OpenIn, OpenInChatGPT, OpenInClaude, OpenInContent, OpenInScira, OpenInT3, OpenInTrigger, OpenInv0, PageHeading, Pagination, PaginationGap, PaginationList, PaginationNext, PaginationPage, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PreWithCopy, PrevNextLinks, PrevNextLinksPageLink, Progress, ProgressBar, ProgressCircle, PromptInput, PromptInputActionAddAttachments, PromptInputActionMenu, PromptInputActionMenuContent, PromptInputActionMenuItem, PromptInputActionMenuTrigger, PromptInputAttachment, PromptInputAttachments, PromptInputBody, PromptInputButton, PromptInputSubmit, PromptInputTextarea, PromptInputToolbar, PromptInputTools, Prose, RadioGroup2 as RadioGroup, RadioGroupItem, Reasoning, ReasoningContent, ReasoningTrigger, ResizableHandle, ResizablePanel, ResizablePanelGroup, Response, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator4 as Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarLink, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarNavigation, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiteSearch, Skeleton, Slider, Social, Source, Sources, SourcesContent, SourcesTrigger, SparkAreaChart, SparkBarChart, SparkLineChart, Spinner, StepIndicator, StepNavigation, Strong, SubmitButton, Suggestion, Suggestions, Switch2 as Switch, SwitchField, SwitchGroup, TabNavigation, TabNavigationLink, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableOfContents, TableRow, Tabs2 as Tabs, TabsContent, TabsList, TabsTrigger, Task, TaskContent, TaskItem, TaskItemFile, TaskTrigger, Text, TextLink, Textarea, ThemeColorPalette, ThemeProvider, ThemeSelector, ThemeSwitcher, Toaster, TocContext, TocProvider, Toggle, ToggleGroup, ToggleGroupItem, Tool, ToolContent, ToolHeader, ToolInput, ToolOutput, Tooltip5 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopLevel, TouchTarget, Tracker, Tooltip3 as TremorTooltip, ViewToggle, WebPreview, WebPreviewBody, WebPreviewNavigation, WebPreviewUrl, Wrapper, aboriginal, addStartStopToColorArray, allPalettes, badgeVariants, brand, buttonVariants, camelCase, chartColors, cn, colorDataArray, colorThemes, colors, constructCategoryColors, createColorArray, createColorData, createFormStore, darkenColor, diverging, domToSimple, focusInput, focusRing, generateColorThemes, generateDataVisColors, getColorClassName, getColorValue, getHeadings, getNodeText, getSurroundingColors, getYAxisDomain, hasErrorInput, hasOnlyOneValueForKey, humaniseVariant, interpolateColors, isLightColor, kebabCase, languages, lightenColor, navigationMenuTriggerStyle, oklchConverter, progressBarVariants, renderColorOutput, renderColorOutputToDTFM, semantic, sequential, shades, themeIndices, themeTokens, toggleVariants, truncate, useActiveSectionObserver, useDisableToc, useFormField, useIsMobile, useOnWindowResize, usePageHeadings, usePromptInputAttachments, useSelectorHeight, useSidebar, useStickyOffset, useToc };
37410
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Action2 as Action, Actions, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AreaChart, Artifact, ArtifactAction, ArtifactActions, ArtifactContent, ArtifactDescription, ArtifactHeader, ArtifactTitle, AspectRatio, AuthLayout, AvailableChartColors, Avatar, AvatarFallback, AvatarImage, Badge, BadgeButton, BarChart, BarList, BaseColorSwatches, Branch, BranchMessages, BranchNext, BranchPage, BranchPrevious, BranchSelector, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Breadcrumbs, Button2 as Button, Calendar, CalendarDayButton, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, CategoryBar, ChainOfThought, ChainOfThoughtContent, ChainOfThoughtHeader, ChainOfThoughtImage, ChainOfThoughtSearchResult, ChainOfThoughtSearchResults, ChainOfThoughtStep, ChartContainer, ChartLegend3 as ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip3 as ChartTooltip, ChartTooltipContent, Checkbox, CheckboxSmall, Code, CodeBlock, CodeBlockCopyButton, CodeDemo, CodeHighlight, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorCard, ColorPairingTool, ColorPairingToolV2, ColorPairingToolV3, ColorSwatches, ColourScale, ComboChart, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Context, ContextCacheUsage, ContextContent, ContextContentBody, ContextContentFooter, ContextContentHeader, ContextInputUsage, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ContextOutputUsage, ContextReasoningUsage, ContextTrigger, Conversation, ConversationContent, ConversationEmptyState, ConversationScrollButton, DataTable, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableToolbar, DataTableViewOptions, Description5 as Description, DescriptionDetails, DescriptionList, DescriptionTerm, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DonutChart, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, DynamicFavicon, ErrorMessage, ExpandableSearch, ExpandableSearchField, Field2 as Field, FieldGroup, FieldLabel, Fieldset2 as Fieldset, Footer, FooterAcknowledgement, FooterLegalLinks, FooterSmallPrint, FooterSocialLink, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, FormatToggle, GenerateInterpolatedColors, Header2 as Header, Heading, HeroBannerSupportingImage, HoverCard, HoverCardContent, HoverCardTrigger, Icons, Image4 as Image, InlineCitation, InlineCitationCard, InlineCitationCardBody, InlineCitationCardTrigger, InlineCitationCarousel, InlineCitationCarouselContent, InlineCitationCarouselHeader, InlineCitationCarouselIndex, InlineCitationCarouselItem, InlineCitationSource, InlineCitationText, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Label5 as Label, Legend6 as Legend, LineChart, Link, _List as List, Listbox2 as Listbox, ListboxDescription, ListboxLabel, ListboxOption2 as ListboxOption, Loader, Loading, Logo, MainNavigation, Masthead, MegaMenu, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Message, MessageContent, MobileHeader, MobileSearch, MultiLevelPushMenu, NSWCard, NSWCardArrow, NSWCardDescription, NSWCardIcon, NSWCardImg, NSWCardTitle, Navbar, NavbarDivider, NavbarItem, NavbarLabel, NavbarSection, NavbarSpacer, Navigation, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NotFound, OpenIn, OpenInChatGPT, OpenInClaude, OpenInContent, OpenInScira, OpenInT3, OpenInTrigger, OpenInv0, PageHeading, Pagination, PaginationGap, PaginationList, PaginationNext, PaginationPage, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PreWithCopy, PrevNextLinks, PrevNextLinksPageLink, Progress, ProgressBar, ProgressCircle, PromptInput, PromptInputActionAddAttachments, PromptInputActionMenu, PromptInputActionMenuContent, PromptInputActionMenuItem, PromptInputActionMenuTrigger, PromptInputAttachment, PromptInputAttachments, PromptInputBody, PromptInputButton, PromptInputSubmit, PromptInputTextarea, PromptInputToolbar, PromptInputTools, Prose, RadioGroup2 as RadioGroup, RadioGroupItem, Reasoning, ReasoningContent, ReasoningTrigger, ResizableHandle, ResizablePanel, ResizablePanelGroup, Response, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator4 as Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarLink, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarNavigation, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiteSearch, Skeleton, Slider, Social, Source, Sources, SourcesContent, SourcesTrigger, SparkAreaChart, SparkBarChart, SparkLineChart, Spinner, StepIndicator, StepNavigation, Strong, SubmitButton, Suggestion, Suggestions, Switch2 as Switch, SwitchField, SwitchGroup, TabNavigation, TabNavigationLink, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableOfContents, TableRow, Tabs2 as Tabs, TabsContent, TabsList, TabsTrigger, Task, TaskContent, TaskItem, TaskItemFile, TaskTrigger, Text, TextLink, Textarea, ThemeColorPalette, ThemeProvider, ThemeSelector, ThemeSwitcher, Toaster, TocContext, TocProvider, Toggle, ToggleGroup, ToggleGroupItem, Tool, ToolContent, ToolHeader, ToolInput, ToolOutput, Tooltip5 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopLevel, TouchTarget, Tracker, Tooltip3 as TremorTooltip, ViewToggle, WebPreview, WebPreviewBody, WebPreviewNavigation, WebPreviewUrl, Wrapper, aboriginal, addStartStopToColorArray, allPalettes, badgeVariants, brand, buttonVariants, camelCase, chartColors, cn, colorDataArray, colorThemes, colors, constructCategoryColors, createColorArray, createColorData, createFormStore, darkenColor, diverging, domToSimple, focusInput, focusRing, generateColorThemes, generateDataVisColors, getColorClassName, getColorValue, getHeadings, getNodeText, getSurroundingColors, getYAxisDomain, hasErrorInput, hasOnlyOneValueForKey, humaniseVariant, interpolateColors, isLightColor, kebabCase, languages, lightenColor, navigationMenuTriggerStyle, oklchConverter, progressBarVariants, renderColorOutput, renderColorOutputToDTFM, semantic, sequential, shades, themeIndices, themeTokens, toggleVariants, truncate, useActiveSectionObserver, useDisableToc, useFormField, useIsMobile, useOnWindowResize, usePageHeadings, usePromptInputAttachments, useSelectorHeight, useSidebar, useStickyOffset, useToc };
35800
37411
  //# sourceMappingURL=index.js.map
35801
37412
  //# sourceMappingURL=index.js.map