@nswds/app 1.104.0 → 1.106.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/globals.css +41 -0
- package/dist/index.cjs +1694 -116
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +1694 -117
- package/dist/index.js.map +1 -1
- package/dist/styles.css +41 -0
- package/dist/styles.css.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -18269,8 +18269,9 @@ function ColorPairingToolV3Content({
|
|
|
18269
18269
|
const [copiedKey, setCopiedKey] = React5.useState(null);
|
|
18270
18270
|
const copiedKeyTimeoutRef = React5.useRef(null);
|
|
18271
18271
|
const resultSectionRef = React5.useRef(null);
|
|
18272
|
+
const technicalDetailsSectionRef = React5.useRef(null);
|
|
18272
18273
|
const noValidStateRef = React5.useRef(/* @__PURE__ */ new Set());
|
|
18273
|
-
const
|
|
18274
|
+
const technicalDetailsViewedRef = React5.useRef(false);
|
|
18274
18275
|
const emitAnalyticsEvent = React5.useCallback(
|
|
18275
18276
|
(event) => {
|
|
18276
18277
|
onAnalyticsEvent(event);
|
|
@@ -18599,24 +18600,1535 @@ function ColorPairingToolV3Content({
|
|
|
18599
18600
|
themeCategory
|
|
18600
18601
|
]);
|
|
18601
18602
|
React5.useEffect(() => {
|
|
18602
|
-
if (
|
|
18603
|
+
if (technicalDetailsViewedRef.current) {
|
|
18603
18604
|
return;
|
|
18604
18605
|
}
|
|
18605
|
-
|
|
18606
|
+
const section = technicalDetailsSectionRef.current;
|
|
18607
|
+
if (!section) {
|
|
18608
|
+
return;
|
|
18609
|
+
}
|
|
18610
|
+
const emitViewedEvent = () => {
|
|
18611
|
+
if (technicalDetailsViewedRef.current) {
|
|
18612
|
+
return;
|
|
18613
|
+
}
|
|
18614
|
+
technicalDetailsViewedRef.current = true;
|
|
18615
|
+
emitAnalyticsEvent({
|
|
18616
|
+
name: "technical_details_viewed",
|
|
18617
|
+
...buildAnalyticsContext({
|
|
18618
|
+
source: "details"
|
|
18619
|
+
})
|
|
18620
|
+
});
|
|
18621
|
+
};
|
|
18622
|
+
if (typeof IntersectionObserver === "undefined") {
|
|
18623
|
+
const rect = section.getBoundingClientRect();
|
|
18624
|
+
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
18625
|
+
if (rect.top < viewportHeight && rect.bottom > 0) {
|
|
18626
|
+
emitViewedEvent();
|
|
18627
|
+
}
|
|
18628
|
+
return;
|
|
18629
|
+
}
|
|
18630
|
+
const observer = new IntersectionObserver(
|
|
18631
|
+
(entries) => {
|
|
18632
|
+
const [entry] = entries;
|
|
18633
|
+
if (entry?.isIntersecting) {
|
|
18634
|
+
emitViewedEvent();
|
|
18635
|
+
observer.disconnect();
|
|
18636
|
+
}
|
|
18637
|
+
},
|
|
18638
|
+
{
|
|
18639
|
+
threshold: 0.2
|
|
18640
|
+
}
|
|
18641
|
+
);
|
|
18642
|
+
observer.observe(section);
|
|
18643
|
+
return () => {
|
|
18644
|
+
observer.disconnect();
|
|
18645
|
+
};
|
|
18646
|
+
}, [buildAnalyticsContext, emitAnalyticsEvent]);
|
|
18647
|
+
if (!selectedBackground) {
|
|
18648
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
|
|
18649
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "No approved background tones available" }),
|
|
18650
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No approved tones are available for the current palette and colour selection." })
|
|
18651
|
+
] });
|
|
18652
|
+
}
|
|
18653
|
+
const compactControlsSummary = `${themeCategory === "brand" ? "Brand" : "Aboriginal"} palette, ${context.primary.label} primary, ${context.accent.label} accent, ${getPairingColorDisplayName3(
|
|
18654
|
+
selectedBackground
|
|
18655
|
+
)} background.`;
|
|
18656
|
+
const renderControlsPanel = (isOverlay = false) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18657
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-grey-200 px-5 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
|
|
18658
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
|
|
18659
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
18660
|
+
!isFirstDrawerStep ? /* @__PURE__ */ jsxRuntime.jsxs(Button2, { variant: "ghost", color: "grey", size: "sm", onClick: goToPreviousDrawerStep, children: [
|
|
18661
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.west, { "data-slot": "icon", className: "size-5" }),
|
|
18662
|
+
"Back"
|
|
18663
|
+
] }) : null,
|
|
18664
|
+
isOverlay ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
18665
|
+
Button2,
|
|
18666
|
+
{
|
|
18667
|
+
variant: "ghost",
|
|
18668
|
+
color: "grey",
|
|
18669
|
+
size: "icon",
|
|
18670
|
+
onClick: () => setIsCompactControlsOpen(false),
|
|
18671
|
+
"aria-label": "Close configuration",
|
|
18672
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.close, { "data-slot": "icon", className: "size-5" })
|
|
18673
|
+
}
|
|
18674
|
+
) : null
|
|
18675
|
+
] })
|
|
18676
|
+
] }) }),
|
|
18677
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-grey-200 px-5 py-4", children: [
|
|
18678
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
18679
|
+
COLOR_PAIRING_TOOL_DRAWER_STEPS.map((step, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
18680
|
+
"button",
|
|
18681
|
+
{
|
|
18682
|
+
type: "button",
|
|
18683
|
+
"aria-current": index === drawerStepIndex ? "step" : void 0,
|
|
18684
|
+
"aria-label": `${step.eyebrow}: ${step.title}`,
|
|
18685
|
+
onClick: () => goToDrawerStep(index),
|
|
18686
|
+
className: "flex-1 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
|
|
18687
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18688
|
+
"span",
|
|
18689
|
+
{
|
|
18690
|
+
className: cn(
|
|
18691
|
+
"block h-1.5 rounded-full transition-colors",
|
|
18692
|
+
index <= drawerStepIndex ? "bg-primary-800" : "bg-grey-200"
|
|
18693
|
+
)
|
|
18694
|
+
}
|
|
18695
|
+
)
|
|
18696
|
+
},
|
|
18697
|
+
step.id
|
|
18698
|
+
)),
|
|
18699
|
+
/* @__PURE__ */ jsxRuntime.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 })
|
|
18700
|
+
] }),
|
|
18701
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 space-y-2", children: [
|
|
18702
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: activeDrawerStep.title }),
|
|
18703
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: activeDrawerStep.description })
|
|
18704
|
+
] })
|
|
18705
|
+
] }),
|
|
18706
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18707
|
+
"div",
|
|
18708
|
+
{
|
|
18709
|
+
className: "flex h-full transition-transform duration-300 ease-out",
|
|
18710
|
+
style: { transform: `translateX(-${drawerStepIndex * 100}%)` },
|
|
18711
|
+
children: [
|
|
18712
|
+
/* @__PURE__ */ jsxRuntime.jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6 pr-1", children: [
|
|
18713
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
18714
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Palette" }),
|
|
18715
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: ["brand", "aboriginal"].map((palette) => {
|
|
18716
|
+
const isSelected = themeCategory === palette;
|
|
18717
|
+
const label = palette === "brand" ? "Brand palette" : "Aboriginal palette";
|
|
18718
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18719
|
+
SelectorButton,
|
|
18720
|
+
{
|
|
18721
|
+
label,
|
|
18722
|
+
isSelected,
|
|
18723
|
+
onClick: () => handleThemeCategoryChange(palette)
|
|
18724
|
+
},
|
|
18725
|
+
palette
|
|
18726
|
+
);
|
|
18727
|
+
}) })
|
|
18728
|
+
] }),
|
|
18729
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
18730
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Primary colour family" }),
|
|
18731
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableFamilies.map((family) => {
|
|
18732
|
+
const label = getFamilySelectorLabel3(family, themeCategory, "primary colour");
|
|
18733
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18734
|
+
SelectorButton,
|
|
18735
|
+
{
|
|
18736
|
+
label,
|
|
18737
|
+
isSelected: family.key === context.primary.key,
|
|
18738
|
+
onClick: () => handlePrimaryColorChange(family.key),
|
|
18739
|
+
swatch: getFamilySwatchColor3(family, 800)
|
|
18740
|
+
},
|
|
18741
|
+
family.key
|
|
18742
|
+
);
|
|
18743
|
+
}) })
|
|
18744
|
+
] }),
|
|
18745
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
18746
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Accent colour family" }),
|
|
18747
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableAccentFamilies.map((family) => {
|
|
18748
|
+
const label = getFamilySelectorLabel3(family, themeCategory, "accent colour");
|
|
18749
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18750
|
+
SelectorButton,
|
|
18751
|
+
{
|
|
18752
|
+
label,
|
|
18753
|
+
isSelected: family.key === context.accent.key,
|
|
18754
|
+
onClick: () => handleAccentColorChange(family.key),
|
|
18755
|
+
swatch: getFamilySwatchColor3(family, 600)
|
|
18756
|
+
},
|
|
18757
|
+
family.key
|
|
18758
|
+
);
|
|
18759
|
+
}) })
|
|
18760
|
+
] }),
|
|
18761
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-grey-200 pt-4", children: [
|
|
18762
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: "Grey is always included" }),
|
|
18763
|
+
/* @__PURE__ */ jsxRuntime.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." })
|
|
18764
|
+
] })
|
|
18765
|
+
] }) }),
|
|
18766
|
+
/* @__PURE__ */ jsxRuntime.jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6 pr-1", children: context.backgroundGroups.map((group, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18767
|
+
"section",
|
|
18768
|
+
{
|
|
18769
|
+
className: cn("space-y-3", index > 0 && "border-t border-grey-200 pt-6"),
|
|
18770
|
+
children: [
|
|
18771
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
18772
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: [
|
|
18773
|
+
group.family.label,
|
|
18774
|
+
" backgrounds"
|
|
18775
|
+
] }),
|
|
18776
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: group.label })
|
|
18777
|
+
] }),
|
|
18778
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3", children: group.backgrounds.map((background) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
18779
|
+
BackgroundSwatchButton,
|
|
18780
|
+
{
|
|
18781
|
+
background,
|
|
18782
|
+
hasPairs: (context.pairsByBackground[background.token]?.length ?? 0) > 0,
|
|
18783
|
+
isSelected: selectedBackground.token === background.token,
|
|
18784
|
+
onClick: () => handleBackgroundChange(background.token)
|
|
18785
|
+
},
|
|
18786
|
+
background.token
|
|
18787
|
+
)) })
|
|
18788
|
+
]
|
|
18789
|
+
},
|
|
18790
|
+
group.key
|
|
18791
|
+
)) }) }),
|
|
18792
|
+
/* @__PURE__ */ jsxRuntime.jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4 pr-1", children: recommendationItems.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: recommendationItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
18793
|
+
RecommendationCard,
|
|
18794
|
+
{
|
|
18795
|
+
copiedKey,
|
|
18796
|
+
item,
|
|
18797
|
+
isSelected: item.pair.id === selectedPair?.id,
|
|
18798
|
+
onCopyPairing: () => copyValue(
|
|
18799
|
+
`pair:${item.pair.id}`,
|
|
18800
|
+
getPairingCopyText(item.pair),
|
|
18801
|
+
"Pairing copied",
|
|
18802
|
+
item.pair.id === bestRecommendedPair?.id ? {
|
|
18803
|
+
name: "best_recommendation_copied",
|
|
18804
|
+
...buildAnalyticsContext({
|
|
18805
|
+
foregroundToken: item.pair.foreground.token,
|
|
18806
|
+
pairId: item.pair.id,
|
|
18807
|
+
source: "recommendations-list"
|
|
18808
|
+
})
|
|
18809
|
+
} : void 0
|
|
18810
|
+
),
|
|
18811
|
+
onSelect: () => handlePairChange(item.pair.id, "recommendations-list")
|
|
18812
|
+
},
|
|
18813
|
+
item.pair.id
|
|
18814
|
+
)) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white px-5 py-5", children: [
|
|
18815
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "No valid combinations available" }),
|
|
18816
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No AAA-compliant foreground options are available for this background." })
|
|
18817
|
+
] }) }) })
|
|
18818
|
+
]
|
|
18819
|
+
}
|
|
18820
|
+
) }),
|
|
18821
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-grey-200 px-5 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
18822
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-10 flex-1", children: isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Select a combination to update the result immediately." }) : null }),
|
|
18823
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2 sm:w-auto sm:flex-none", children: [
|
|
18824
|
+
isOverlay && isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
18825
|
+
Button2,
|
|
18826
|
+
{
|
|
18827
|
+
color: "primary",
|
|
18828
|
+
className: "w-full sm:w-auto sm:min-w-40",
|
|
18829
|
+
onClick: () => setIsCompactControlsOpen(false),
|
|
18830
|
+
children: "Review result"
|
|
18831
|
+
}
|
|
18832
|
+
) : null,
|
|
18833
|
+
!isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsxs(Button2, { color: "primary", className: "w-full sm:w-auto", onClick: goToNextDrawerStep, children: [
|
|
18834
|
+
"Continue",
|
|
18835
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.east, { "data-slot": "icon", className: "size-5" })
|
|
18836
|
+
] }) : null
|
|
18837
|
+
] })
|
|
18838
|
+
] }) })
|
|
18839
|
+
] });
|
|
18840
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 xl:grid-cols-[minmax(18rem,24rem)_minmax(0,1fr)]", children: [
|
|
18841
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18842
|
+
"div",
|
|
18843
|
+
{
|
|
18844
|
+
"data-slot": "tool-sidebar",
|
|
18845
|
+
className: "hidden xl:sticky xl:top-[var(--tool-sidebar-top)] xl:block xl:self-start",
|
|
18846
|
+
style: desktopSidebarStyle,
|
|
18847
|
+
children: /* @__PURE__ */ jsxRuntime.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() })
|
|
18848
|
+
}
|
|
18849
|
+
),
|
|
18850
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "tool-results", className: "space-y-6", children: [
|
|
18851
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4 xl:hidden", children: [
|
|
18852
|
+
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "gap-4 px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between", children: [
|
|
18853
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
18854
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
|
|
18855
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Open the colour pairing drawer to change palette, background, and recommended combinations." }),
|
|
18856
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: compactControlsSummary })
|
|
18857
|
+
] }),
|
|
18858
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
18859
|
+
Button2,
|
|
18860
|
+
{
|
|
18861
|
+
color: "primary",
|
|
18862
|
+
className: "w-full sm:w-auto",
|
|
18863
|
+
onClick: () => setIsCompactControlsOpen(true),
|
|
18864
|
+
children: [
|
|
18865
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.edit_square, { "data-slot": "icon", className: "size-5" }),
|
|
18866
|
+
"Open configuration"
|
|
18867
|
+
]
|
|
18868
|
+
}
|
|
18869
|
+
)
|
|
18870
|
+
] }) }),
|
|
18871
|
+
/* @__PURE__ */ jsxRuntime.jsx(Sheet, { open: isCompactControlsOpen, onOpenChange: setIsCompactControlsOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18872
|
+
SheetContent,
|
|
18873
|
+
{
|
|
18874
|
+
side: "left",
|
|
18875
|
+
showClose: false,
|
|
18876
|
+
className: "w-[30rem] max-w-[90vw] overflow-hidden p-0",
|
|
18877
|
+
children: [
|
|
18878
|
+
/* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Colour pairing configuration" }),
|
|
18879
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full flex-col bg-background", children: renderControlsPanel(true) })
|
|
18880
|
+
]
|
|
18881
|
+
}
|
|
18882
|
+
) })
|
|
18883
|
+
] }),
|
|
18884
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { ref: resultSectionRef, className: "space-y-6", "aria-label": "Current result", children: [
|
|
18885
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sr-only", "aria-live": "polite", children: liveAnnouncement }),
|
|
18886
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18887
|
+
CurrentResultCard,
|
|
18888
|
+
{
|
|
18889
|
+
bestPair: bestRecommendedPair,
|
|
18890
|
+
familySummary,
|
|
18891
|
+
pair: previewPair,
|
|
18892
|
+
selectedBackground
|
|
18893
|
+
}
|
|
18894
|
+
)
|
|
18895
|
+
] }),
|
|
18896
|
+
bestRecommendedPair ? /* @__PURE__ */ jsxRuntime.jsx("section", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18897
|
+
BestRecommendationCard,
|
|
18898
|
+
{
|
|
18899
|
+
copiedKey,
|
|
18900
|
+
isCurrentSelection: selectedPair?.id === bestRecommendedPair.id,
|
|
18901
|
+
pair: bestRecommendedPair,
|
|
18902
|
+
reason: getBestRecommendationReason(bestRecommendedPair, context),
|
|
18903
|
+
onCopyPairing: () => copyValue(
|
|
18904
|
+
"best-pairing",
|
|
18905
|
+
getPairingCopyText(bestRecommendedPair),
|
|
18906
|
+
"Pairing copied",
|
|
18907
|
+
{
|
|
18908
|
+
name: "best_recommendation_copied",
|
|
18909
|
+
...buildAnalyticsContext({
|
|
18910
|
+
foregroundToken: bestRecommendedPair.foreground.token,
|
|
18911
|
+
pairId: bestRecommendedPair.id,
|
|
18912
|
+
source: "best-recommendation"
|
|
18913
|
+
})
|
|
18914
|
+
}
|
|
18915
|
+
),
|
|
18916
|
+
onUsePairing: () => handlePairChange(bestRecommendedPair.id, "best-recommendation")
|
|
18917
|
+
}
|
|
18918
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
|
|
18919
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Best recommended pairing" }),
|
|
18920
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No AAA-compliant foreground options available for this selection." })
|
|
18921
|
+
] }),
|
|
18922
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { ref: technicalDetailsSectionRef, className: "space-y-4", children: [
|
|
18923
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
18924
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Technical colour values" }),
|
|
18925
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Token, tone, HEX, RGB, HSL, and OKLCH values for the current selection." })
|
|
18926
|
+
] }),
|
|
18927
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
|
|
18928
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18929
|
+
TechnicalDetailsPanel,
|
|
18930
|
+
{
|
|
18931
|
+
title: "Background values",
|
|
18932
|
+
color: selectedBackground,
|
|
18933
|
+
visibleFormats,
|
|
18934
|
+
copiedKey,
|
|
18935
|
+
onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
|
|
18936
|
+
}
|
|
18937
|
+
),
|
|
18938
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18939
|
+
TechnicalDetailsPanel,
|
|
18940
|
+
{
|
|
18941
|
+
title: "Foreground values",
|
|
18942
|
+
color: detailForeground,
|
|
18943
|
+
visibleFormats,
|
|
18944
|
+
copiedKey,
|
|
18945
|
+
onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
|
|
18946
|
+
}
|
|
18947
|
+
)
|
|
18948
|
+
] }),
|
|
18949
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
18950
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Share colour pairing" }),
|
|
18951
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white p-4", children: [
|
|
18952
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
18953
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Copy this URL to share your current colour pairing:" }),
|
|
18954
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18955
|
+
Button2,
|
|
18956
|
+
{
|
|
18957
|
+
variant: "ghost",
|
|
18958
|
+
color: "grey",
|
|
18959
|
+
size: "sm",
|
|
18960
|
+
className: "shrink-0",
|
|
18961
|
+
onClick: () => copyValue(
|
|
18962
|
+
"share-url",
|
|
18963
|
+
typeof window === "undefined" ? shareUrl : new URL(shareUrl, window.location.origin).toString(),
|
|
18964
|
+
"Colour pairing link copied"
|
|
18965
|
+
),
|
|
18966
|
+
"aria-label": copiedKey === "share-url" ? "Colour pairing URL copied to clipboard" : "Copy colour pairing URL to clipboard",
|
|
18967
|
+
title: copiedKey === "share-url" ? "Copied" : "Copy URL",
|
|
18968
|
+
children: copiedKey === "share-url" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18969
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" }),
|
|
18970
|
+
"Copied"
|
|
18971
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18972
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
|
|
18973
|
+
"Copy URL"
|
|
18974
|
+
] })
|
|
18975
|
+
}
|
|
18976
|
+
)
|
|
18977
|
+
] }),
|
|
18978
|
+
/* @__PURE__ */ jsxRuntime.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 })
|
|
18979
|
+
] })
|
|
18980
|
+
] })
|
|
18981
|
+
] })
|
|
18982
|
+
] })
|
|
18983
|
+
] });
|
|
18984
|
+
}
|
|
18985
|
+
function ColorPairingToolV3({
|
|
18986
|
+
onAnalyticsEvent = () => {
|
|
18987
|
+
},
|
|
18988
|
+
visibleFormats = DEFAULT_VISIBLE_FORMATS3
|
|
18989
|
+
} = {}) {
|
|
18990
|
+
const normalizedVisibleFormats = [...new Set(visibleFormats)];
|
|
18991
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolV3Loading, {}), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18992
|
+
ColorPairingToolV3Content,
|
|
18993
|
+
{
|
|
18994
|
+
onAnalyticsEvent,
|
|
18995
|
+
visibleFormats: normalizedVisibleFormats
|
|
18996
|
+
}
|
|
18997
|
+
) });
|
|
18998
|
+
}
|
|
18999
|
+
var PREFERRED_BACKGROUND_TONES4 = [400, 600, 200, 800, 100, 50];
|
|
19000
|
+
var DEFAULT_VISIBLE_FORMATS4 = ["hex", "rgb", "hsl", "oklch"];
|
|
19001
|
+
var DEFAULT_INITIAL_BACKGROUND_TOKEN4 = "nsw-blue-800";
|
|
19002
|
+
var DEFAULT_INITIAL_PAIR_ID4 = "nsw-blue-800:nsw-blue-200";
|
|
19003
|
+
var COLOR_PAIRING_TOOL_V4_PATH = "/core/colour/colour-pairing-tool-4";
|
|
19004
|
+
var MOBILE_RESULT_SCROLL_QUERY2 = "(max-width: 1023px)";
|
|
19005
|
+
var PERSISTENT_DRAWER_MIN_WIDTH_QUERY2 = "(min-width: 1280px)";
|
|
19006
|
+
var INITIAL_VISIBLE_ALTERNATIVES = 6;
|
|
19007
|
+
var COLOR_PAIRING_TOOL_DRAWER_STEPS2 = [
|
|
19008
|
+
{
|
|
19009
|
+
id: "colours",
|
|
19010
|
+
title: "Choose colours",
|
|
19011
|
+
eyebrow: "Step 1 of 3",
|
|
19012
|
+
description: "Select the palette, primary family, and accent family."
|
|
19013
|
+
},
|
|
19014
|
+
{
|
|
19015
|
+
id: "backgrounds",
|
|
19016
|
+
title: "Choose background",
|
|
19017
|
+
eyebrow: "Step 2 of 3",
|
|
19018
|
+
description: "Pick the background tone that you want to pair."
|
|
19019
|
+
},
|
|
19020
|
+
{
|
|
19021
|
+
id: "refine",
|
|
19022
|
+
title: "Refine or override recommendation",
|
|
19023
|
+
eyebrow: "Step 3 of 3",
|
|
19024
|
+
description: "Use the result panel to review the NSW default pairing and override it only when a different approved option is needed."
|
|
19025
|
+
}
|
|
19026
|
+
];
|
|
19027
|
+
var COLOR_PAIRING_TOOL_V4_ANALYTICS_EVENT = "nsw-colour-pairing-tool-v4";
|
|
19028
|
+
function getToneFromToken4(token) {
|
|
19029
|
+
if (!token) return null;
|
|
19030
|
+
const match = token.match(/-(\d+)$/);
|
|
19031
|
+
return match ? Number.parseInt(match[1], 10) : null;
|
|
19032
|
+
}
|
|
19033
|
+
function getFamilySwatchColor4(family, preferredTone = 600) {
|
|
19034
|
+
const exactMatch = family.colors.find((color2) => color2.tone === preferredTone);
|
|
19035
|
+
if (exactMatch) {
|
|
19036
|
+
return exactMatch.hex;
|
|
19037
|
+
}
|
|
19038
|
+
const closestMatch = [...family.colors].sort(
|
|
19039
|
+
(left, right) => Math.abs(left.tone - preferredTone) - Math.abs(right.tone - preferredTone)
|
|
19040
|
+
)[0];
|
|
19041
|
+
return closestMatch?.hex ?? "transparent";
|
|
19042
|
+
}
|
|
19043
|
+
function getFamilySelectorLabel4(family, themeCategory, selectionRole) {
|
|
19044
|
+
if (themeCategory !== "aboriginal") {
|
|
19045
|
+
return family.label;
|
|
19046
|
+
}
|
|
19047
|
+
const preferredTone = selectionRole === "primary colour" ? 800 : 600;
|
|
19048
|
+
return family.colors.find((color2) => color2.tone === preferredTone)?.name ?? family.label;
|
|
19049
|
+
}
|
|
19050
|
+
function getPairingColorDisplayName4(color2) {
|
|
19051
|
+
return color2.name ?? `${color2.familyLabel} ${color2.tone}`;
|
|
19052
|
+
}
|
|
19053
|
+
function isWhiteForegroundPair4(pair) {
|
|
19054
|
+
return pair.foreground.token === "white";
|
|
19055
|
+
}
|
|
19056
|
+
function isLargeTextOnlyPair2(pair) {
|
|
19057
|
+
return pair.passes.aaaLarge && !pair.passes.aaaText;
|
|
19058
|
+
}
|
|
19059
|
+
function getWhiteForegroundGuidance4(pair) {
|
|
19060
|
+
if (pair.passes.aaaText) {
|
|
19061
|
+
return "White is approved for headings, body copy, and calls to action on this background.";
|
|
19062
|
+
}
|
|
19063
|
+
if (pair.passes.aaaLarge) {
|
|
19064
|
+
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.";
|
|
19065
|
+
}
|
|
19066
|
+
return "Do not use white on this background. Choose one of the recommended foregrounds below instead.";
|
|
19067
|
+
}
|
|
19068
|
+
function getPreviewGuidance4(pair, isRecommended) {
|
|
19069
|
+
if (!isWhiteForegroundPair4(pair)) {
|
|
19070
|
+
return isRecommended ? "Use this pairing for headings, body copy, and actions on the selected background." : "Use this approved alternative when you need a different tone or stronger emphasis.";
|
|
19071
|
+
}
|
|
19072
|
+
if (isRecommended) {
|
|
19073
|
+
return "Use white text on this background for headings, body copy, and actions only while it maintains AAA contrast.";
|
|
19074
|
+
}
|
|
19075
|
+
return getWhiteForegroundGuidance4(pair);
|
|
19076
|
+
}
|
|
19077
|
+
function getPreferredPairForBackground4(pairs, preferredPairId) {
|
|
19078
|
+
if (preferredPairId) {
|
|
19079
|
+
const preferredPair = pairs.find((pair) => pair.id === preferredPairId);
|
|
19080
|
+
if (preferredPair) {
|
|
19081
|
+
return preferredPair;
|
|
19082
|
+
}
|
|
19083
|
+
}
|
|
19084
|
+
return pairs.find((pair) => !isWhiteForegroundPair4(pair)) ?? pairs[0] ?? null;
|
|
19085
|
+
}
|
|
19086
|
+
function getDefaultBackgroundToken4(context) {
|
|
19087
|
+
for (const tone of PREFERRED_BACKGROUND_TONES4) {
|
|
19088
|
+
for (const group of context.backgroundGroups) {
|
|
19089
|
+
const match = group.backgrounds.find(
|
|
19090
|
+
(background) => background.tone === tone && (context.pairsByBackground[background.token]?.length ?? 0) > 0
|
|
19091
|
+
);
|
|
19092
|
+
if (match) {
|
|
19093
|
+
return match.token;
|
|
19094
|
+
}
|
|
19095
|
+
}
|
|
19096
|
+
}
|
|
19097
|
+
for (const tone of PREFERRED_BACKGROUND_TONES4) {
|
|
19098
|
+
for (const group of context.backgroundGroups) {
|
|
19099
|
+
const match = group.backgrounds.find((background) => background.tone === tone);
|
|
19100
|
+
if (match) {
|
|
19101
|
+
return match.token;
|
|
19102
|
+
}
|
|
19103
|
+
}
|
|
19104
|
+
}
|
|
19105
|
+
return context.backgrounds[0]?.token ?? "";
|
|
19106
|
+
}
|
|
19107
|
+
function resolveBackgroundToken4(context, preferredToken, preferredTone) {
|
|
19108
|
+
if (preferredToken && context.backgrounds.some((background) => background.token === preferredToken)) {
|
|
19109
|
+
return preferredToken;
|
|
19110
|
+
}
|
|
19111
|
+
if (preferredTone !== null && preferredTone !== void 0) {
|
|
19112
|
+
for (const group of context.backgroundGroups) {
|
|
19113
|
+
const match = group.backgrounds.find((background) => background.tone === preferredTone);
|
|
19114
|
+
if (match) {
|
|
19115
|
+
return match.token;
|
|
19116
|
+
}
|
|
19117
|
+
}
|
|
19118
|
+
}
|
|
19119
|
+
return getDefaultBackgroundToken4(context);
|
|
19120
|
+
}
|
|
19121
|
+
function getInitialPairingState4(searchParams) {
|
|
19122
|
+
const paletteParam = searchParams.get("palette");
|
|
19123
|
+
const primaryParam = searchParams.get("primary");
|
|
19124
|
+
const accentParam = searchParams.get("accent");
|
|
19125
|
+
const pairParam = searchParams.get("pair");
|
|
19126
|
+
const backgroundParam = searchParams.get("background");
|
|
19127
|
+
const themeCategory = paletteParam === "brand" || paletteParam === "aboriginal" ? paletteParam : "brand";
|
|
19128
|
+
const context = getPairingContext(themeCategory, primaryParam, accentParam);
|
|
19129
|
+
const shouldUseDefaultBrandExample = !backgroundParam && !pairParam && themeCategory === "brand" && context.primary.key === "blue" && context.accent.key === "red";
|
|
19130
|
+
const defaultBackgroundToken = shouldUseDefaultBrandExample ? context.backgrounds.some(
|
|
19131
|
+
(background) => background.token === DEFAULT_INITIAL_BACKGROUND_TOKEN4
|
|
19132
|
+
) ? DEFAULT_INITIAL_BACKGROUND_TOKEN4 : null : null;
|
|
19133
|
+
const defaultPairId = shouldUseDefaultBrandExample && defaultBackgroundToken && context.pairsByBackground[defaultBackgroundToken]?.some(
|
|
19134
|
+
(pair) => pair.id === DEFAULT_INITIAL_PAIR_ID4
|
|
19135
|
+
) ? DEFAULT_INITIAL_PAIR_ID4 : null;
|
|
19136
|
+
const pairBackgroundToken = context.recommendedPairs.find((pair) => pair.id === pairParam)?.background.token ?? null;
|
|
19137
|
+
const selectedBackgroundToken = resolveBackgroundToken4(
|
|
19138
|
+
context,
|
|
19139
|
+
backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken,
|
|
19140
|
+
getToneFromToken4(backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken)
|
|
19141
|
+
);
|
|
19142
|
+
const selectedPairId = getPreferredPairForBackground4(
|
|
19143
|
+
context.pairsByBackground[selectedBackgroundToken] ?? [],
|
|
19144
|
+
pairParam ?? defaultPairId
|
|
19145
|
+
)?.id ?? "";
|
|
19146
|
+
return {
|
|
19147
|
+
accentKey: context.accent.key,
|
|
19148
|
+
primaryKey: context.primary.key,
|
|
19149
|
+
selectedBackgroundToken,
|
|
19150
|
+
selectedPairId,
|
|
19151
|
+
themeCategory
|
|
19152
|
+
};
|
|
19153
|
+
}
|
|
19154
|
+
function getReadableTextColor3(tone) {
|
|
19155
|
+
return tone >= 600 ? "#ffffff" : "#002664";
|
|
19156
|
+
}
|
|
19157
|
+
function getBackgroundOptionName2(background) {
|
|
19158
|
+
return background.name ?? `${background.familyLabel} ${background.tone}`;
|
|
19159
|
+
}
|
|
19160
|
+
function getMainPairingLabel(pair, bestPair) {
|
|
19161
|
+
if (!pair) {
|
|
19162
|
+
return "No AAA pairing available";
|
|
19163
|
+
}
|
|
19164
|
+
if (pair.id === bestPair?.id) {
|
|
19165
|
+
return "NSW recommended pairing";
|
|
19166
|
+
}
|
|
19167
|
+
if (isWhiteForegroundPair4(pair) && isLargeTextOnlyPair2(pair)) {
|
|
19168
|
+
return "Large-text example only";
|
|
19169
|
+
}
|
|
19170
|
+
if (isWhiteForegroundPair4(pair) && !pair.passes.aaaLarge) {
|
|
19171
|
+
return "Example only";
|
|
19172
|
+
}
|
|
19173
|
+
return "Approved alternative";
|
|
19174
|
+
}
|
|
19175
|
+
function getMainPairingSupportCopy(pair, bestPair, context) {
|
|
19176
|
+
if (!pair) {
|
|
19177
|
+
return "No AAA-compliant foreground available for this background.";
|
|
19178
|
+
}
|
|
19179
|
+
if (pair.id === bestPair?.id) {
|
|
19180
|
+
return getBestRecommendationReason2(pair, context);
|
|
19181
|
+
}
|
|
19182
|
+
if (isWhiteForegroundPair4(pair) && isLargeTextOnlyPair2(pair)) {
|
|
19183
|
+
return "White works here for large text only. Use the NSW default for standard body copy and smaller interface text.";
|
|
19184
|
+
}
|
|
19185
|
+
if (isWhiteForegroundPair4(pair) && !pair.passes.aaaLarge) {
|
|
19186
|
+
return "White does not meet AAA on this background. Choose a different approved background or foreground.";
|
|
19187
|
+
}
|
|
19188
|
+
return "Approved AAA alternative when a different tone or emphasis is needed.";
|
|
19189
|
+
}
|
|
19190
|
+
function getBestRecommendationReason2(pair, context) {
|
|
19191
|
+
if (isWhiteForegroundPair4(pair)) {
|
|
19192
|
+
return "Recommended because this background is dark enough to support white text at AAA contrast.";
|
|
19193
|
+
}
|
|
19194
|
+
if (pair.foreground.familyKey === pair.background.familyKey) {
|
|
19195
|
+
return "Recommended because it stays within the same colour family while keeping clear AAA contrast.";
|
|
19196
|
+
}
|
|
19197
|
+
if (pair.foreground.familyKey === context.grey.key) {
|
|
19198
|
+
return "Recommended because grey provides a strong neutral contrast without competing with the background.";
|
|
19199
|
+
}
|
|
19200
|
+
if (pair.foreground.familyKey === context.accent.key) {
|
|
19201
|
+
return "Recommended because the selected accent family adds emphasis while preserving AAA contrast.";
|
|
19202
|
+
}
|
|
19203
|
+
if (pair.foreground.familyKey === context.primary.key) {
|
|
19204
|
+
return "Recommended because the selected primary family gives the clearest AAA-compliant contrast for this background.";
|
|
19205
|
+
}
|
|
19206
|
+
return "Recommended because it is the clearest NSW-approved AAA pairing for this background.";
|
|
19207
|
+
}
|
|
19208
|
+
function getRecommendationCategory2(pair, bestPair, context) {
|
|
19209
|
+
if (pair.id === bestPair?.id) return "best";
|
|
19210
|
+
if (isWhiteForegroundPair4(pair)) return "white";
|
|
19211
|
+
if (pair.foreground.familyKey === pair.background.familyKey) return "same-family";
|
|
19212
|
+
if (pair.foreground.familyKey === context.accent.key) return "accent-family";
|
|
19213
|
+
if (pair.foreground.familyKey === context.grey.key) return "grey-option";
|
|
19214
|
+
if (pair.foreground.familyKey === context.primary.key) return "primary-family";
|
|
19215
|
+
return "approved";
|
|
19216
|
+
}
|
|
19217
|
+
function getRecommendationSortRank2(category) {
|
|
19218
|
+
switch (category) {
|
|
19219
|
+
case "best":
|
|
19220
|
+
return 0;
|
|
19221
|
+
case "same-family":
|
|
19222
|
+
return 1;
|
|
19223
|
+
case "primary-family":
|
|
19224
|
+
return 2;
|
|
19225
|
+
case "accent-family":
|
|
19226
|
+
return 3;
|
|
19227
|
+
case "grey-option":
|
|
19228
|
+
return 4;
|
|
19229
|
+
case "white":
|
|
19230
|
+
return 5;
|
|
19231
|
+
default:
|
|
19232
|
+
return 6;
|
|
19233
|
+
}
|
|
19234
|
+
}
|
|
19235
|
+
function getRecommendationGroupId(category) {
|
|
19236
|
+
switch (category) {
|
|
19237
|
+
case "best":
|
|
19238
|
+
case "same-family":
|
|
19239
|
+
case "primary-family":
|
|
19240
|
+
return "closest";
|
|
19241
|
+
case "accent-family":
|
|
19242
|
+
case "white":
|
|
19243
|
+
case "approved":
|
|
19244
|
+
return "expressive";
|
|
19245
|
+
case "grey-option":
|
|
19246
|
+
return "neutral";
|
|
19247
|
+
default:
|
|
19248
|
+
return null;
|
|
19249
|
+
}
|
|
19250
|
+
}
|
|
19251
|
+
function buildRecommendationGroups(items) {
|
|
19252
|
+
const groupedItems = items.reduce(
|
|
19253
|
+
(accumulator, item) => {
|
|
19254
|
+
const groupId = getRecommendationGroupId(item.category);
|
|
19255
|
+
if (!groupId) {
|
|
19256
|
+
return accumulator;
|
|
19257
|
+
}
|
|
19258
|
+
accumulator[groupId].push(item);
|
|
19259
|
+
return accumulator;
|
|
19260
|
+
},
|
|
19261
|
+
{
|
|
19262
|
+
closest: [],
|
|
19263
|
+
expressive: [],
|
|
19264
|
+
neutral: []
|
|
19265
|
+
}
|
|
19266
|
+
);
|
|
19267
|
+
const groups = [
|
|
19268
|
+
{
|
|
19269
|
+
id: "closest",
|
|
19270
|
+
title: "Closest to default",
|
|
19271
|
+
description: "Stays closest to the NSW default in tone and overall treatment.",
|
|
19272
|
+
items: groupedItems.closest
|
|
19273
|
+
},
|
|
19274
|
+
{
|
|
19275
|
+
id: "expressive",
|
|
19276
|
+
title: "More expressive (accent)",
|
|
19277
|
+
description: "Brings more accent or emphasis into the foreground treatment.",
|
|
19278
|
+
items: groupedItems.expressive
|
|
19279
|
+
},
|
|
19280
|
+
{
|
|
19281
|
+
id: "neutral",
|
|
19282
|
+
title: "Neutral/system",
|
|
19283
|
+
description: "Uses quieter neutral contrast for system or utility treatments.",
|
|
19284
|
+
items: groupedItems.neutral
|
|
19285
|
+
}
|
|
19286
|
+
];
|
|
19287
|
+
return groups.filter((group) => group.items.length > 0);
|
|
19288
|
+
}
|
|
19289
|
+
function getAvailabilityMeta2(isSelected, hasPairs) {
|
|
19290
|
+
if (isSelected && hasPairs) {
|
|
19291
|
+
return {
|
|
19292
|
+
description: "Selected background with AAA foreground options.",
|
|
19293
|
+
icon: Icons.check_circle,
|
|
19294
|
+
label: "Selected",
|
|
19295
|
+
tone: "selected"
|
|
19296
|
+
};
|
|
19297
|
+
}
|
|
19298
|
+
if (isSelected) {
|
|
19299
|
+
return {
|
|
19300
|
+
description: "Selected background with no AAA-compliant foreground available.",
|
|
19301
|
+
icon: Icons.warning,
|
|
19302
|
+
label: "Selected, no AAA",
|
|
19303
|
+
tone: "unavailable"
|
|
19304
|
+
};
|
|
19305
|
+
}
|
|
19306
|
+
if (hasPairs) {
|
|
19307
|
+
return {
|
|
19308
|
+
description: "AAA foreground options available.",
|
|
19309
|
+
icon: Icons.radio_button_checked,
|
|
19310
|
+
label: "Available",
|
|
19311
|
+
tone: "available"
|
|
19312
|
+
};
|
|
19313
|
+
}
|
|
19314
|
+
return {
|
|
19315
|
+
description: "No AAA-compliant foreground available for this background.",
|
|
19316
|
+
icon: Icons.close,
|
|
19317
|
+
label: "No AAA",
|
|
19318
|
+
tone: "unavailable"
|
|
19319
|
+
};
|
|
19320
|
+
}
|
|
19321
|
+
function getPairingCopyText2(pair) {
|
|
19322
|
+
const accessibilityLine = pair.passes.aaaText ? "Accessibility: Meets AAA for normal and large text" : pair.passes.aaaLarge ? "Accessibility: Meets AAA for large text only" : "Accessibility: Fails AAA for normal and large text";
|
|
19323
|
+
return [
|
|
19324
|
+
`Background: ${pair.background.token} (${pair.background.hex})`,
|
|
19325
|
+
`Foreground: ${pair.foreground.token} (${pair.foreground.hex})`,
|
|
19326
|
+
`Contrast ratio: ${pair.contrastRatio.toFixed(2)}:1`,
|
|
19327
|
+
accessibilityLine
|
|
19328
|
+
].join("\n");
|
|
19329
|
+
}
|
|
19330
|
+
function getAccessibilitySummaryLine(pair) {
|
|
19331
|
+
if (!pair) {
|
|
19332
|
+
return "Contrast unavailable";
|
|
19333
|
+
}
|
|
19334
|
+
if (pair.passes.aaaText) {
|
|
19335
|
+
return `${pair.contrastRatio.toFixed(2)}:1 \u2014 AAA compliant (normal + large text)`;
|
|
19336
|
+
}
|
|
19337
|
+
if (pair.passes.aaaLarge) {
|
|
19338
|
+
return `${pair.contrastRatio.toFixed(2)}:1 \u2014 AAA compliant (large text only)`;
|
|
19339
|
+
}
|
|
19340
|
+
return `${pair.contrastRatio.toFixed(2)}:1 \u2014 Not AAA compliant`;
|
|
19341
|
+
}
|
|
19342
|
+
function getLiveAnnouncement2(pair, background) {
|
|
19343
|
+
if (!background) {
|
|
19344
|
+
return "No approved background tones available.";
|
|
19345
|
+
}
|
|
19346
|
+
if (!pair) {
|
|
19347
|
+
return `${background.token} selected. No AAA-compliant foreground options available for this selection.`;
|
|
19348
|
+
}
|
|
19349
|
+
if (isWhiteForegroundPair4(pair) && isLargeTextOnlyPair2(pair)) {
|
|
19350
|
+
return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for large text only.`;
|
|
19351
|
+
}
|
|
19352
|
+
if (isWhiteForegroundPair4(pair) && !pair.passes.aaaLarge) {
|
|
19353
|
+
return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Fails AAA for normal and large text.`;
|
|
19354
|
+
}
|
|
19355
|
+
return `${background.token} with ${pair.foreground.token}. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for normal and large text.`;
|
|
19356
|
+
}
|
|
19357
|
+
function formatValueRows2(color2, visibleFormats) {
|
|
19358
|
+
const hasDisplayTone = color2.token !== "white";
|
|
19359
|
+
return [
|
|
19360
|
+
{ key: "token", label: "Token", value: color2.token, copyable: true },
|
|
19361
|
+
{
|
|
19362
|
+
key: "tone",
|
|
19363
|
+
label: "Tone",
|
|
19364
|
+
value: hasDisplayTone ? String(color2.tone) : "Not applicable",
|
|
19365
|
+
copyable: hasDisplayTone
|
|
19366
|
+
},
|
|
19367
|
+
...visibleFormats.map((format) => ({
|
|
19368
|
+
key: format,
|
|
19369
|
+
label: format.toUpperCase(),
|
|
19370
|
+
value: color2[format],
|
|
19371
|
+
copyable: true
|
|
19372
|
+
}))
|
|
19373
|
+
];
|
|
19374
|
+
}
|
|
19375
|
+
function SelectorButton2({
|
|
19376
|
+
description,
|
|
19377
|
+
isSelected,
|
|
19378
|
+
label,
|
|
19379
|
+
onClick,
|
|
19380
|
+
swatch
|
|
19381
|
+
}) {
|
|
19382
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19383
|
+
"button",
|
|
19384
|
+
{
|
|
19385
|
+
type: "button",
|
|
19386
|
+
"aria-pressed": isSelected,
|
|
19387
|
+
onClick,
|
|
19388
|
+
className: cn(
|
|
19389
|
+
"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",
|
|
19390
|
+
isSelected ? "border-primary-800 bg-primary-50" : "border-grey-300 bg-white hover:border-primary-500 hover:bg-grey-50"
|
|
19391
|
+
),
|
|
19392
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
|
|
19393
|
+
swatch ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19394
|
+
"span",
|
|
19395
|
+
{
|
|
19396
|
+
"aria-hidden": "true",
|
|
19397
|
+
className: "mt-0.5 size-4 shrink-0 rounded-full border border-black/10",
|
|
19398
|
+
style: { backgroundColor: swatch }
|
|
19399
|
+
}
|
|
19400
|
+
) : null,
|
|
19401
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1", children: [
|
|
19402
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: label }),
|
|
19403
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs/5 text-muted-foreground", children: description }) : null
|
|
19404
|
+
] })
|
|
19405
|
+
] })
|
|
19406
|
+
}
|
|
19407
|
+
);
|
|
19408
|
+
}
|
|
19409
|
+
function BackgroundSwatchButton2({
|
|
19410
|
+
background,
|
|
19411
|
+
hasPairs,
|
|
19412
|
+
isSelected,
|
|
19413
|
+
onClick
|
|
19414
|
+
}) {
|
|
19415
|
+
const status = getAvailabilityMeta2(isSelected, hasPairs);
|
|
19416
|
+
const StatusIcon = status.icon;
|
|
19417
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19418
|
+
"button",
|
|
19419
|
+
{
|
|
19420
|
+
type: "button",
|
|
19421
|
+
"aria-pressed": isSelected,
|
|
19422
|
+
"aria-label": `Select ${background.token} background. ${status.description}`,
|
|
19423
|
+
onClick,
|
|
19424
|
+
className: cn(
|
|
19425
|
+
"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",
|
|
19426
|
+
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"
|
|
19427
|
+
),
|
|
19428
|
+
children: [
|
|
19429
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
19430
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
19431
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: getBackgroundOptionName2(background) }),
|
|
19432
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-[0.72rem] break-all text-muted-foreground", children: background.token })
|
|
19433
|
+
] }),
|
|
19434
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
19435
|
+
"span",
|
|
19436
|
+
{
|
|
19437
|
+
className: cn(
|
|
19438
|
+
"inline-flex items-center gap-1 rounded-sm border px-2 py-1 text-[0.68rem] font-semibold uppercase",
|
|
19439
|
+
status.tone === "selected" && "border-primary-800 bg-primary-800 text-white dark:border-primary-500 dark:bg-primary-500",
|
|
19440
|
+
status.tone === "available" && "border-grey-300 bg-grey-50 text-foreground",
|
|
19441
|
+
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"
|
|
19442
|
+
),
|
|
19443
|
+
children: [
|
|
19444
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { "data-slot": "icon", className: "size-4" }),
|
|
19445
|
+
status.label
|
|
19446
|
+
]
|
|
19447
|
+
}
|
|
19448
|
+
)
|
|
19449
|
+
] }),
|
|
19450
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 overflow-hidden rounded-[2px] border border-black/10", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-14 w-full", style: { backgroundColor: background.hex } }) }),
|
|
19451
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-xs/5 text-muted-foreground", children: status.description })
|
|
19452
|
+
]
|
|
19453
|
+
}
|
|
19454
|
+
);
|
|
19455
|
+
}
|
|
19456
|
+
function CurrentResultCard2({
|
|
19457
|
+
bestPair,
|
|
19458
|
+
copiedKey,
|
|
19459
|
+
onCopyPairing,
|
|
19460
|
+
pair,
|
|
19461
|
+
supportText,
|
|
19462
|
+
selectedBackground
|
|
19463
|
+
}) {
|
|
19464
|
+
const previewForeground = pair?.foreground.hex ?? getReadableTextColor3(selectedBackground.tone);
|
|
19465
|
+
const isRecommended = pair ? pair.id === bestPair?.id : false;
|
|
19466
|
+
const pairingLabel = getMainPairingLabel(pair, bestPair);
|
|
19467
|
+
const accessibilitySummary = getAccessibilitySummaryLine(pair);
|
|
19468
|
+
const fauxButtonStyle = pair ? {
|
|
19469
|
+
"--btn-bg": pair.foreground.hex,
|
|
19470
|
+
"--btn-border": pair.foreground.hex,
|
|
19471
|
+
"--btn-text": pair.background.hex,
|
|
19472
|
+
"--btn-icon": pair.background.hex,
|
|
19473
|
+
"--btn-hover-overlay": pair.background.hex
|
|
19474
|
+
} : null;
|
|
19475
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn("gap-0 overflow-hidden py-0", isRecommended && "border-primary-200"), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19476
|
+
"div",
|
|
19477
|
+
{
|
|
19478
|
+
className: "p-4 sm:min-h-[24rem] sm:p-8",
|
|
19479
|
+
style: {
|
|
19480
|
+
backgroundColor: selectedBackground.hex,
|
|
19481
|
+
color: previewForeground
|
|
19482
|
+
},
|
|
19483
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[18rem] flex-col justify-between gap-8 sm:min-h-[20rem]", children: [
|
|
19484
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-3xl rounded-sm bg-white px-4 py-4 text-foreground sm:px-6 sm:py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5 lg:flex-row lg:items-start lg:justify-between", children: [
|
|
19485
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-4", children: [
|
|
19486
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
19487
|
+
"span",
|
|
19488
|
+
{
|
|
19489
|
+
className: cn(
|
|
19490
|
+
"inline-flex items-center gap-2 rounded-sm px-3 py-1 text-[0.72rem] font-semibold tracking-[0.12em] uppercase",
|
|
19491
|
+
isRecommended ? "bg-primary-800 text-white" : "border border-grey-300 bg-grey-50 text-foreground"
|
|
19492
|
+
),
|
|
19493
|
+
children: [
|
|
19494
|
+
isRecommended ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.info, { "data-slot": "icon", className: "size-4" }),
|
|
19495
|
+
pairingLabel
|
|
19496
|
+
]
|
|
19497
|
+
}
|
|
19498
|
+
),
|
|
19499
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
19500
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 4, className: "text-foreground", trim: "normal", children: pair ? `${getPairingColorDisplayName4(pair.foreground)} on ${getPairingColorDisplayName4(pair.background)}` : `${getPairingColorDisplayName4(selectedBackground)} selected` }),
|
|
19501
|
+
pair ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "font-mono text-[0.74rem] break-all text-muted-foreground", children: [
|
|
19502
|
+
pair.foreground.token,
|
|
19503
|
+
" on ",
|
|
19504
|
+
pair.background.token
|
|
19505
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-[0.74rem] break-all text-muted-foreground", children: selectedBackground.token }),
|
|
19506
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: accessibilitySummary }),
|
|
19507
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "max-w-3xl text-grey-700", children: supportText })
|
|
19508
|
+
] })
|
|
19509
|
+
] }),
|
|
19510
|
+
pair ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19511
|
+
Button2,
|
|
19512
|
+
{
|
|
19513
|
+
color: "primary",
|
|
19514
|
+
className: "w-full justify-center lg:w-auto lg:min-w-48",
|
|
19515
|
+
onClick: onCopyPairing,
|
|
19516
|
+
children: copiedKey === "current-pairing" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19517
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" }),
|
|
19518
|
+
"Pairing copied"
|
|
19519
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19520
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
|
|
19521
|
+
"Copy pairing"
|
|
19522
|
+
] })
|
|
19523
|
+
}
|
|
19524
|
+
) : null
|
|
19525
|
+
] }) }),
|
|
19526
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-xl space-y-4", children: [
|
|
19527
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
19528
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "max-w-lg text-3xl leading-tight font-bold text-current sm:text-4xl", children: "Example heading" }),
|
|
19529
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-md text-base/7", children: pair ? getPreviewGuidance4(pair, isRecommended) : "This approved background does not currently have an AAA foreground in this tool. Choose another approved background to continue." })
|
|
19530
|
+
] }),
|
|
19531
|
+
pair && fauxButtonStyle ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19532
|
+
"span",
|
|
19533
|
+
{
|
|
19534
|
+
"aria-hidden": "true",
|
|
19535
|
+
"data-variant": "solid",
|
|
19536
|
+
className: cn(
|
|
19537
|
+
buttonVariants({ variant: "solid", size: "default" }),
|
|
19538
|
+
"pointer-events-none cursor-default self-start px-6 text-[16px] font-[700] select-none sm:px-6 sm:text-[16px] sm:font-[700]"
|
|
19539
|
+
),
|
|
19540
|
+
style: fauxButtonStyle,
|
|
19541
|
+
children: "Primary action"
|
|
19542
|
+
}
|
|
19543
|
+
) : null
|
|
19544
|
+
] })
|
|
19545
|
+
] })
|
|
19546
|
+
}
|
|
19547
|
+
) });
|
|
19548
|
+
}
|
|
19549
|
+
function RecommendationCard2({
|
|
19550
|
+
copiedKey,
|
|
19551
|
+
isSelected,
|
|
19552
|
+
item,
|
|
19553
|
+
onCopyPairing,
|
|
19554
|
+
onSelect
|
|
19555
|
+
}) {
|
|
19556
|
+
const { pair } = item;
|
|
19557
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19558
|
+
"div",
|
|
19559
|
+
{
|
|
19560
|
+
className: cn(
|
|
19561
|
+
"relative rounded-sm border bg-white px-3 py-2.5 text-left transition-colors focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
|
|
19562
|
+
isSelected ? "border-primary-800 bg-primary-50/40" : "border-grey-200 hover:border-grey-400"
|
|
19563
|
+
),
|
|
19564
|
+
children: [
|
|
19565
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19566
|
+
"button",
|
|
19567
|
+
{
|
|
19568
|
+
type: "button",
|
|
19569
|
+
"aria-pressed": isSelected,
|
|
19570
|
+
"aria-label": `Use ${pair.foreground.token} on ${pair.background.token}`,
|
|
19571
|
+
onClick: onSelect,
|
|
19572
|
+
className: "absolute inset-0 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden"
|
|
19573
|
+
}
|
|
19574
|
+
),
|
|
19575
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none relative z-10 flex items-start gap-3", children: [
|
|
19576
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-0.5 w-12 shrink-0 overflow-hidden rounded-[2px] border border-black/10", children: [
|
|
19577
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-9 w-full", style: { backgroundColor: pair.background.hex } }),
|
|
19578
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2.5 w-full", style: { backgroundColor: pair.foreground.hex } })
|
|
19579
|
+
] }),
|
|
19580
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
|
|
19581
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
19582
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm font-semibold text-foreground", children: [
|
|
19583
|
+
getPairingColorDisplayName4(pair.foreground),
|
|
19584
|
+
" on",
|
|
19585
|
+
" ",
|
|
19586
|
+
getPairingColorDisplayName4(pair.background)
|
|
19587
|
+
] }),
|
|
19588
|
+
item.category === "best" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex rounded-sm bg-primary-800 px-2 py-1 text-[0.68rem] font-semibold tracking-[0.12em] text-white uppercase", children: "Default" }) : null,
|
|
19589
|
+
isSelected ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex rounded-sm border border-primary-800 px-2 py-1 text-[0.68rem] font-semibold tracking-[0.12em] text-primary-800 uppercase", children: "Current" }) : null
|
|
19590
|
+
] }),
|
|
19591
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "font-mono text-[0.72rem] break-all text-muted-foreground", children: [
|
|
19592
|
+
pair.foreground.token,
|
|
19593
|
+
" on ",
|
|
19594
|
+
pair.background.token
|
|
19595
|
+
] }),
|
|
19596
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
19597
|
+
pair.contrastRatio.toFixed(2),
|
|
19598
|
+
":1 contrast"
|
|
19599
|
+
] })
|
|
19600
|
+
] }),
|
|
19601
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto shrink-0 self-start", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19602
|
+
Button2,
|
|
19603
|
+
{
|
|
19604
|
+
variant: "ghost",
|
|
19605
|
+
color: "grey",
|
|
19606
|
+
size: "icon",
|
|
19607
|
+
className: "size-8 text-muted-foreground hover:text-foreground",
|
|
19608
|
+
onClick: onCopyPairing,
|
|
19609
|
+
"aria-label": `Copy pairing ${pair.background.token} and ${pair.foreground.token}`,
|
|
19610
|
+
title: copiedKey === `pair:${pair.id}` ? "Copied" : "Copy pairing",
|
|
19611
|
+
children: copiedKey === `pair:${pair.id}` ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-4" })
|
|
19612
|
+
}
|
|
19613
|
+
) })
|
|
19614
|
+
] })
|
|
19615
|
+
]
|
|
19616
|
+
}
|
|
19617
|
+
);
|
|
19618
|
+
}
|
|
19619
|
+
function RecommendationGroupSection({
|
|
19620
|
+
children,
|
|
19621
|
+
description,
|
|
19622
|
+
title
|
|
19623
|
+
}) {
|
|
19624
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-2", children: [
|
|
19625
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
19626
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: title }),
|
|
19627
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "text-muted-foreground", children: description })
|
|
19628
|
+
] }),
|
|
19629
|
+
children
|
|
19630
|
+
] });
|
|
19631
|
+
}
|
|
19632
|
+
function TechnicalDetailsPanel2({
|
|
19633
|
+
color: color2,
|
|
19634
|
+
copiedKey,
|
|
19635
|
+
onCopyValue,
|
|
19636
|
+
title,
|
|
19637
|
+
visibleFormats
|
|
19638
|
+
}) {
|
|
19639
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white", children: [
|
|
19640
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-grey-200 px-4 py-4 sm:px-5", children: [
|
|
19641
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: title }),
|
|
19642
|
+
color2 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19643
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: getPairingColorDisplayName4(color2) }),
|
|
19644
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 overflow-hidden rounded-sm border border-black/10 bg-white", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-20 w-full sm:h-24", style: { backgroundColor: color2.hex } }) })
|
|
19645
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "No AAA foreground available." })
|
|
19646
|
+
] }),
|
|
19647
|
+
color2 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-grey-200", children: formatValueRows2(color2, visibleFormats).map((row) => {
|
|
19648
|
+
const copyKey = `${title}-${row.key}`;
|
|
19649
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19650
|
+
"div",
|
|
19651
|
+
{
|
|
19652
|
+
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",
|
|
19653
|
+
children: [
|
|
19654
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
19655
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: row.label }),
|
|
19656
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19657
|
+
"p",
|
|
19658
|
+
{
|
|
19659
|
+
className: cn(
|
|
19660
|
+
"mt-2 text-sm text-foreground",
|
|
19661
|
+
row.key !== "tone" && "font-mono break-all"
|
|
19662
|
+
),
|
|
19663
|
+
children: row.value
|
|
19664
|
+
}
|
|
19665
|
+
)
|
|
19666
|
+
] }),
|
|
19667
|
+
row.copyable ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19668
|
+
Button2,
|
|
19669
|
+
{
|
|
19670
|
+
variant: "ghost",
|
|
19671
|
+
color: "grey",
|
|
19672
|
+
size: "sm",
|
|
19673
|
+
className: "self-start",
|
|
19674
|
+
onClick: () => onCopyValue(copyKey, row.value, `${row.label} copied`),
|
|
19675
|
+
"aria-label": `Copy ${title.toLowerCase()} ${row.label.toLowerCase()}`,
|
|
19676
|
+
children: copiedKey === copyKey ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19677
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-5" }),
|
|
19678
|
+
"Copied"
|
|
19679
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19680
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
|
|
19681
|
+
"Copy"
|
|
19682
|
+
] })
|
|
19683
|
+
}
|
|
19684
|
+
) : null
|
|
19685
|
+
]
|
|
19686
|
+
},
|
|
19687
|
+
row.key
|
|
19688
|
+
);
|
|
19689
|
+
}) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "No technical values are shown because there is no AAA-compliant foreground for this background." }) })
|
|
19690
|
+
] });
|
|
19691
|
+
}
|
|
19692
|
+
function resolveSelectionState2(nextThemeCategory, nextPrimaryKey, nextAccentKey, preferredBackgroundToken, preferredPairId) {
|
|
19693
|
+
const context = getPairingContext(nextThemeCategory, nextPrimaryKey, nextAccentKey);
|
|
19694
|
+
const selectedBackgroundToken = resolveBackgroundToken4(
|
|
19695
|
+
context,
|
|
19696
|
+
preferredBackgroundToken,
|
|
19697
|
+
getToneFromToken4(preferredBackgroundToken)
|
|
19698
|
+
);
|
|
19699
|
+
const selectedPairId = getPreferredPairForBackground4(
|
|
19700
|
+
context.pairsByBackground[selectedBackgroundToken] ?? [],
|
|
19701
|
+
preferredPairId
|
|
19702
|
+
)?.id ?? "";
|
|
19703
|
+
return {
|
|
19704
|
+
accentKey: context.accent.key,
|
|
19705
|
+
context,
|
|
19706
|
+
primaryKey: context.primary.key,
|
|
19707
|
+
selectedBackgroundToken,
|
|
19708
|
+
selectedPairId,
|
|
19709
|
+
themeCategory: nextThemeCategory
|
|
19710
|
+
};
|
|
19711
|
+
}
|
|
19712
|
+
function ColorPairingToolV4Loading() {
|
|
19713
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 xl:grid-cols-[minmax(18rem,24rem)_minmax(0,1fr)]", children: [
|
|
19714
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
19715
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-52 rounded-sm border border-grey-200 bg-grey-50" }),
|
|
19716
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[32rem] rounded-sm border border-grey-200 bg-grey-50" })
|
|
19717
|
+
] }),
|
|
19718
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
19719
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-96 rounded-sm border border-grey-200 bg-grey-50" }),
|
|
19720
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-64 rounded-sm border border-grey-200 bg-grey-50" }),
|
|
19721
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-72 rounded-sm border border-grey-200 bg-grey-50" })
|
|
19722
|
+
] })
|
|
19723
|
+
] });
|
|
19724
|
+
}
|
|
19725
|
+
function ColorPairingToolV4Content({
|
|
19726
|
+
onAnalyticsEvent,
|
|
19727
|
+
visibleFormats
|
|
19728
|
+
}) {
|
|
19729
|
+
const searchParams = navigation.useSearchParams();
|
|
19730
|
+
const stickyOffset = useStickyOffset(24);
|
|
19731
|
+
const [initialState] = React5.useState(() => getInitialPairingState4(searchParams));
|
|
19732
|
+
const [themeCategory, setThemeCategory] = React5.useState(initialState.themeCategory);
|
|
19733
|
+
const [primaryFamilyKey, setPrimaryFamilyKey] = React5.useState(initialState.primaryKey);
|
|
19734
|
+
const [accentFamilyKey, setAccentFamilyKey] = React5.useState(initialState.accentKey);
|
|
19735
|
+
const [selectedBackgroundToken, setSelectedBackgroundToken] = React5.useState(
|
|
19736
|
+
initialState.selectedBackgroundToken
|
|
19737
|
+
);
|
|
19738
|
+
const [selectedPairId, setSelectedPairId] = React5.useState(initialState.selectedPairId);
|
|
19739
|
+
const [drawerStepIndex, setDrawerStepIndex] = React5.useState(0);
|
|
19740
|
+
const [isCompactControlsOpen, setIsCompactControlsOpen] = React5.useState(false);
|
|
19741
|
+
const [isShowingAllAlternatives, setIsShowingAllAlternatives] = React5.useState(false);
|
|
19742
|
+
const [isTechnicalDetailsOpen, setIsTechnicalDetailsOpen] = React5.useState(false);
|
|
19743
|
+
const [, copyToClipboardRaw] = usehooks.useCopyToClipboard();
|
|
19744
|
+
const [copiedKey, setCopiedKey] = React5.useState(null);
|
|
19745
|
+
const copiedKeyTimeoutRef = React5.useRef(null);
|
|
19746
|
+
const resultSectionRef = React5.useRef(null);
|
|
19747
|
+
const noValidStateRef = React5.useRef(/* @__PURE__ */ new Set());
|
|
19748
|
+
const technicalDetailsViewedRef = React5.useRef(false);
|
|
19749
|
+
const emitAnalyticsEvent = React5.useCallback(
|
|
19750
|
+
(event) => {
|
|
19751
|
+
onAnalyticsEvent(event);
|
|
19752
|
+
if (typeof window !== "undefined") {
|
|
19753
|
+
window.dispatchEvent(
|
|
19754
|
+
new CustomEvent(COLOR_PAIRING_TOOL_V4_ANALYTICS_EVENT, {
|
|
19755
|
+
detail: event
|
|
19756
|
+
})
|
|
19757
|
+
);
|
|
19758
|
+
}
|
|
19759
|
+
},
|
|
19760
|
+
[onAnalyticsEvent]
|
|
19761
|
+
);
|
|
19762
|
+
React5.useEffect(() => {
|
|
19763
|
+
return () => {
|
|
19764
|
+
if (copiedKeyTimeoutRef.current) {
|
|
19765
|
+
clearTimeout(copiedKeyTimeoutRef.current);
|
|
19766
|
+
}
|
|
19767
|
+
};
|
|
19768
|
+
}, []);
|
|
19769
|
+
React5.useEffect(() => {
|
|
19770
|
+
if (typeof window === "undefined") {
|
|
19771
|
+
return;
|
|
19772
|
+
}
|
|
19773
|
+
const mediaQuery = window.matchMedia(PERSISTENT_DRAWER_MIN_WIDTH_QUERY2);
|
|
19774
|
+
const handleChange = (event) => {
|
|
19775
|
+
if (event?.matches ?? mediaQuery.matches) {
|
|
19776
|
+
setIsCompactControlsOpen(false);
|
|
19777
|
+
}
|
|
19778
|
+
};
|
|
19779
|
+
handleChange();
|
|
19780
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
19781
|
+
return () => {
|
|
19782
|
+
mediaQuery.removeEventListener("change", handleChange);
|
|
19783
|
+
};
|
|
19784
|
+
}, []);
|
|
19785
|
+
const themeFamilies = React5.useMemo(() => getPairingFamilies(themeCategory), [themeCategory]);
|
|
19786
|
+
const context = React5.useMemo(
|
|
19787
|
+
() => getPairingContext(themeCategory, primaryFamilyKey, accentFamilyKey),
|
|
19788
|
+
[themeCategory, primaryFamilyKey, accentFamilyKey]
|
|
19789
|
+
);
|
|
19790
|
+
const selectableFamilies = React5.useMemo(
|
|
19791
|
+
() => themeFamilies.filter((family) => family.key !== context.grey.key),
|
|
19792
|
+
[themeFamilies, context.grey.key]
|
|
19793
|
+
);
|
|
19794
|
+
const selectableAccentFamilies = React5.useMemo(
|
|
19795
|
+
() => selectableFamilies.filter((family) => family.key !== context.primary.key),
|
|
19796
|
+
[selectableFamilies, context.primary.key]
|
|
19797
|
+
);
|
|
19798
|
+
const selectedBackground = React5.useMemo(
|
|
19799
|
+
() => context.backgrounds.find((background) => background.token === selectedBackgroundToken) ?? context.backgrounds[0] ?? null,
|
|
19800
|
+
[context.backgrounds, selectedBackgroundToken]
|
|
19801
|
+
);
|
|
19802
|
+
const selectedBackgroundPairs = React5.useMemo(
|
|
19803
|
+
() => selectedBackground ? context.pairsByBackground[selectedBackground.token] ?? [] : [],
|
|
19804
|
+
[context.pairsByBackground, selectedBackground]
|
|
19805
|
+
);
|
|
19806
|
+
const bestRecommendedPair = React5.useMemo(
|
|
19807
|
+
() => getPreferredPairForBackground4(selectedBackgroundPairs),
|
|
19808
|
+
[selectedBackgroundPairs]
|
|
19809
|
+
);
|
|
19810
|
+
const selectedPair = React5.useMemo(
|
|
19811
|
+
() => getPreferredPairForBackground4(selectedBackgroundPairs, selectedPairId),
|
|
19812
|
+
[selectedBackgroundPairs, selectedPairId]
|
|
19813
|
+
);
|
|
19814
|
+
const whiteForegroundExample = React5.useMemo(
|
|
19815
|
+
() => selectedBackground && supportsWhiteForegroundPreview(selectedBackground) ? getWhiteForegroundPair(selectedBackground) : null,
|
|
19816
|
+
[selectedBackground]
|
|
19817
|
+
);
|
|
19818
|
+
const previewPair = selectedPair ?? whiteForegroundExample ?? null;
|
|
19819
|
+
const detailForeground = selectedPair?.foreground ?? whiteForegroundExample?.foreground ?? null;
|
|
19820
|
+
const currentPairSupportText = React5.useMemo(
|
|
19821
|
+
() => getMainPairingSupportCopy(previewPair, bestRecommendedPair, context),
|
|
19822
|
+
[bestRecommendedPair, context, previewPair]
|
|
19823
|
+
);
|
|
19824
|
+
const recommendationItems = React5.useMemo(() => {
|
|
19825
|
+
return selectedBackgroundPairs.map((pair) => {
|
|
19826
|
+
const category = getRecommendationCategory2(pair, bestRecommendedPair, context);
|
|
19827
|
+
return {
|
|
19828
|
+
category,
|
|
19829
|
+
pair
|
|
19830
|
+
};
|
|
19831
|
+
}).sort(
|
|
19832
|
+
(left, right) => getRecommendationSortRank2(left.category) - getRecommendationSortRank2(right.category)
|
|
19833
|
+
);
|
|
19834
|
+
}, [bestRecommendedPair, context, selectedBackgroundPairs]);
|
|
19835
|
+
const alternativeRecommendationGroups = React5.useMemo(
|
|
19836
|
+
() => buildRecommendationGroups(
|
|
19837
|
+
recommendationItems.filter((item) => item.pair.id !== selectedPair?.id)
|
|
19838
|
+
),
|
|
19839
|
+
[recommendationItems, selectedPair?.id]
|
|
19840
|
+
);
|
|
19841
|
+
const visibleAlternativeRecommendationGroups = React5.useMemo(() => {
|
|
19842
|
+
if (isShowingAllAlternatives) {
|
|
19843
|
+
return alternativeRecommendationGroups;
|
|
19844
|
+
}
|
|
19845
|
+
let remaining = INITIAL_VISIBLE_ALTERNATIVES;
|
|
19846
|
+
return alternativeRecommendationGroups.reduce((groups, group) => {
|
|
19847
|
+
if (remaining <= 0) {
|
|
19848
|
+
return groups;
|
|
19849
|
+
}
|
|
19850
|
+
const items = group.items.slice(0, remaining);
|
|
19851
|
+
if (items.length > 0) {
|
|
19852
|
+
groups.push({
|
|
19853
|
+
...group,
|
|
19854
|
+
items
|
|
19855
|
+
});
|
|
19856
|
+
remaining -= items.length;
|
|
19857
|
+
}
|
|
19858
|
+
return groups;
|
|
19859
|
+
}, []);
|
|
19860
|
+
}, [alternativeRecommendationGroups, isShowingAllAlternatives]);
|
|
19861
|
+
const hiddenAlternativeCount = React5.useMemo(() => {
|
|
19862
|
+
const totalAlternatives = alternativeRecommendationGroups.reduce(
|
|
19863
|
+
(count, group) => count + group.items.length,
|
|
19864
|
+
0
|
|
19865
|
+
);
|
|
19866
|
+
const visibleAlternatives = visibleAlternativeRecommendationGroups.reduce(
|
|
19867
|
+
(count, group) => count + group.items.length,
|
|
19868
|
+
0
|
|
19869
|
+
);
|
|
19870
|
+
return Math.max(0, totalAlternatives - visibleAlternatives);
|
|
19871
|
+
}, [alternativeRecommendationGroups, visibleAlternativeRecommendationGroups]);
|
|
19872
|
+
const liveAnnouncement = React5.useMemo(
|
|
19873
|
+
() => getLiveAnnouncement2(previewPair, selectedBackground),
|
|
19874
|
+
[previewPair, selectedBackground]
|
|
19875
|
+
);
|
|
19876
|
+
const shareBackgroundToken = selectedBackground?.token ?? selectedBackgroundToken;
|
|
19877
|
+
const shareUrl = React5.useMemo(() => {
|
|
19878
|
+
const params = new URLSearchParams();
|
|
19879
|
+
params.set("palette", themeCategory);
|
|
19880
|
+
params.set("primary", context.primary.key);
|
|
19881
|
+
params.set("accent", context.accent.key);
|
|
19882
|
+
if (shareBackgroundToken) {
|
|
19883
|
+
params.set("background", shareBackgroundToken);
|
|
19884
|
+
}
|
|
19885
|
+
if (selectedPairId) {
|
|
19886
|
+
params.set("pair", selectedPairId);
|
|
19887
|
+
}
|
|
19888
|
+
const query = params.toString();
|
|
19889
|
+
return `${COLOR_PAIRING_TOOL_V4_PATH}${query ? `?${query}` : ""}`;
|
|
19890
|
+
}, [context.accent.key, context.primary.key, shareBackgroundToken, selectedPairId, themeCategory]);
|
|
19891
|
+
const activeDrawerStep = COLOR_PAIRING_TOOL_DRAWER_STEPS2[drawerStepIndex];
|
|
19892
|
+
const isFirstDrawerStep = drawerStepIndex === 0;
|
|
19893
|
+
const isLastDrawerStep = drawerStepIndex === COLOR_PAIRING_TOOL_DRAWER_STEPS2.length - 1;
|
|
19894
|
+
const desktopSidebarStyle = React5.useMemo(
|
|
19895
|
+
() => ({
|
|
19896
|
+
"--tool-sidebar-max-height": `calc(100vh - ${stickyOffset}px)`,
|
|
19897
|
+
"--tool-sidebar-top": `${stickyOffset}px`
|
|
19898
|
+
}),
|
|
19899
|
+
[stickyOffset]
|
|
19900
|
+
);
|
|
19901
|
+
const goToDrawerStep = React5.useCallback((stepIndex) => {
|
|
19902
|
+
setDrawerStepIndex(Math.max(0, Math.min(stepIndex, COLOR_PAIRING_TOOL_DRAWER_STEPS2.length - 1)));
|
|
19903
|
+
}, []);
|
|
19904
|
+
const goToNextDrawerStep = React5.useCallback(() => {
|
|
19905
|
+
setDrawerStepIndex(
|
|
19906
|
+
(currentStep) => Math.min(currentStep + 1, COLOR_PAIRING_TOOL_DRAWER_STEPS2.length - 1)
|
|
19907
|
+
);
|
|
19908
|
+
}, []);
|
|
19909
|
+
const goToPreviousDrawerStep = React5.useCallback(() => {
|
|
19910
|
+
setDrawerStepIndex((currentStep) => Math.max(currentStep - 1, 0));
|
|
19911
|
+
}, []);
|
|
19912
|
+
const updateUrlParams = React5.useCallback((nextState) => {
|
|
19913
|
+
const params = new URLSearchParams(window.location.search);
|
|
19914
|
+
params.delete("family");
|
|
19915
|
+
params.set("palette", nextState.themeCategory);
|
|
19916
|
+
params.set("primary", nextState.primaryKey);
|
|
19917
|
+
params.set("accent", nextState.accentKey);
|
|
19918
|
+
params.set("background", nextState.selectedBackgroundToken);
|
|
19919
|
+
if (nextState.selectedPairId) {
|
|
19920
|
+
params.set("pair", nextState.selectedPairId);
|
|
19921
|
+
} else {
|
|
19922
|
+
params.delete("pair");
|
|
19923
|
+
}
|
|
19924
|
+
window.history.replaceState(
|
|
19925
|
+
null,
|
|
19926
|
+
"",
|
|
19927
|
+
`${window.location.pathname}?${params.toString()}${window.location.hash}`
|
|
19928
|
+
);
|
|
19929
|
+
}, []);
|
|
19930
|
+
const applyResolvedSelection = React5.useCallback(
|
|
19931
|
+
(nextState) => {
|
|
19932
|
+
setThemeCategory(nextState.themeCategory);
|
|
19933
|
+
setPrimaryFamilyKey(nextState.primaryKey);
|
|
19934
|
+
setAccentFamilyKey(nextState.accentKey);
|
|
19935
|
+
setSelectedBackgroundToken(nextState.selectedBackgroundToken);
|
|
19936
|
+
setSelectedPairId(nextState.selectedPairId);
|
|
19937
|
+
updateUrlParams(nextState);
|
|
19938
|
+
},
|
|
19939
|
+
[updateUrlParams]
|
|
19940
|
+
);
|
|
19941
|
+
const buildAnalyticsContext = React5.useCallback(
|
|
19942
|
+
(overrides) => ({
|
|
19943
|
+
accentKey: context.accent.key,
|
|
19944
|
+
backgroundToken: selectedBackground?.token,
|
|
19945
|
+
foregroundToken: selectedPair?.foreground.token,
|
|
19946
|
+
pairId: selectedPair?.id,
|
|
19947
|
+
palette: themeCategory,
|
|
19948
|
+
primaryKey: context.primary.key,
|
|
19949
|
+
...overrides
|
|
19950
|
+
}),
|
|
19951
|
+
[context.accent.key, context.primary.key, selectedBackground, selectedPair, themeCategory]
|
|
19952
|
+
);
|
|
19953
|
+
const copyValue = React5.useCallback(
|
|
19954
|
+
(copyKey, value, toastLabel, analyticsEvent) => {
|
|
19955
|
+
copyToClipboardRaw(value);
|
|
19956
|
+
setCopiedKey(copyKey);
|
|
19957
|
+
sonner.toast(toastLabel, { duration: 2e3 });
|
|
19958
|
+
if (analyticsEvent) {
|
|
19959
|
+
emitAnalyticsEvent(analyticsEvent);
|
|
19960
|
+
}
|
|
19961
|
+
if (copiedKeyTimeoutRef.current) {
|
|
19962
|
+
clearTimeout(copiedKeyTimeoutRef.current);
|
|
19963
|
+
}
|
|
19964
|
+
copiedKeyTimeoutRef.current = setTimeout(() => {
|
|
19965
|
+
setCopiedKey(null);
|
|
19966
|
+
copiedKeyTimeoutRef.current = null;
|
|
19967
|
+
}, 2e3);
|
|
19968
|
+
},
|
|
19969
|
+
[copyToClipboardRaw, emitAnalyticsEvent]
|
|
19970
|
+
);
|
|
19971
|
+
const handleThemeCategoryChange = (nextThemeCategory) => {
|
|
19972
|
+
const nextState = resolveSelectionState2(
|
|
19973
|
+
nextThemeCategory,
|
|
19974
|
+
primaryFamilyKey,
|
|
19975
|
+
accentFamilyKey,
|
|
19976
|
+
selectedBackgroundToken,
|
|
19977
|
+
null
|
|
19978
|
+
);
|
|
19979
|
+
setIsShowingAllAlternatives(false);
|
|
19980
|
+
applyResolvedSelection(nextState);
|
|
19981
|
+
emitAnalyticsEvent({
|
|
19982
|
+
name: "palette_change",
|
|
19983
|
+
accentKey: nextState.accentKey,
|
|
19984
|
+
backgroundToken: nextState.selectedBackgroundToken,
|
|
19985
|
+
pairId: nextState.selectedPairId,
|
|
19986
|
+
palette: nextState.themeCategory,
|
|
19987
|
+
primaryKey: nextState.primaryKey
|
|
19988
|
+
});
|
|
19989
|
+
};
|
|
19990
|
+
const handlePrimaryColorChange = (nextPrimaryKey) => {
|
|
19991
|
+
const nextAccentKey = nextPrimaryKey === accentFamilyKey ? getDefaultAccentFamilyKey(themeCategory, nextPrimaryKey) : accentFamilyKey;
|
|
19992
|
+
const nextState = resolveSelectionState2(
|
|
19993
|
+
themeCategory,
|
|
19994
|
+
nextPrimaryKey,
|
|
19995
|
+
nextAccentKey,
|
|
19996
|
+
selectedBackgroundToken,
|
|
19997
|
+
null
|
|
19998
|
+
);
|
|
19999
|
+
setIsShowingAllAlternatives(false);
|
|
20000
|
+
applyResolvedSelection(nextState);
|
|
20001
|
+
emitAnalyticsEvent({
|
|
20002
|
+
name: "primary_change",
|
|
20003
|
+
accentKey: nextState.accentKey,
|
|
20004
|
+
backgroundToken: nextState.selectedBackgroundToken,
|
|
20005
|
+
pairId: nextState.selectedPairId,
|
|
20006
|
+
palette: nextState.themeCategory,
|
|
20007
|
+
primaryKey: nextState.primaryKey
|
|
20008
|
+
});
|
|
20009
|
+
};
|
|
20010
|
+
const handleAccentColorChange = (nextAccentKey) => {
|
|
20011
|
+
if (nextAccentKey === primaryFamilyKey) return;
|
|
20012
|
+
const nextState = resolveSelectionState2(
|
|
20013
|
+
themeCategory,
|
|
20014
|
+
primaryFamilyKey,
|
|
20015
|
+
nextAccentKey,
|
|
20016
|
+
selectedBackgroundToken,
|
|
20017
|
+
null
|
|
20018
|
+
);
|
|
20019
|
+
setIsShowingAllAlternatives(false);
|
|
20020
|
+
applyResolvedSelection(nextState);
|
|
20021
|
+
emitAnalyticsEvent({
|
|
20022
|
+
name: "accent_change",
|
|
20023
|
+
accentKey: nextState.accentKey,
|
|
20024
|
+
backgroundToken: nextState.selectedBackgroundToken,
|
|
20025
|
+
pairId: nextState.selectedPairId,
|
|
20026
|
+
palette: nextState.themeCategory,
|
|
20027
|
+
primaryKey: nextState.primaryKey
|
|
20028
|
+
});
|
|
20029
|
+
};
|
|
20030
|
+
const handleBackgroundChange = (nextSelectedBackgroundToken) => {
|
|
20031
|
+
const nextSelectedPairId = getPreferredPairForBackground4(context.pairsByBackground[nextSelectedBackgroundToken] ?? [])?.id ?? "";
|
|
20032
|
+
const nextState = {
|
|
20033
|
+
accentKey: context.accent.key,
|
|
20034
|
+
context,
|
|
20035
|
+
primaryKey: context.primary.key,
|
|
20036
|
+
selectedBackgroundToken: nextSelectedBackgroundToken,
|
|
20037
|
+
selectedPairId: nextSelectedPairId,
|
|
20038
|
+
themeCategory
|
|
20039
|
+
};
|
|
20040
|
+
setIsShowingAllAlternatives(false);
|
|
20041
|
+
applyResolvedSelection(nextState);
|
|
20042
|
+
emitAnalyticsEvent({
|
|
20043
|
+
name: "background_selection",
|
|
20044
|
+
...buildAnalyticsContext({
|
|
20045
|
+
backgroundToken: nextSelectedBackgroundToken,
|
|
20046
|
+
foregroundToken: context.pairsByBackground[nextSelectedBackgroundToken]?.find(
|
|
20047
|
+
(pair) => pair.id === nextSelectedPairId
|
|
20048
|
+
)?.foreground.token,
|
|
20049
|
+
pairId: nextSelectedPairId
|
|
20050
|
+
})
|
|
20051
|
+
});
|
|
20052
|
+
if (typeof window !== "undefined" && window.matchMedia(MOBILE_RESULT_SCROLL_QUERY2).matches) {
|
|
20053
|
+
requestAnimationFrame(() => {
|
|
20054
|
+
resultSectionRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
20055
|
+
});
|
|
20056
|
+
}
|
|
20057
|
+
};
|
|
20058
|
+
const handlePairChange = (nextSelectedPairId, source) => {
|
|
20059
|
+
if (!selectedBackground) return;
|
|
20060
|
+
const nextPair = selectedBackgroundPairs.find((pair) => pair.id === nextSelectedPairId) ?? null;
|
|
20061
|
+
setSelectedPairId(nextSelectedPairId);
|
|
20062
|
+
updateUrlParams({
|
|
20063
|
+
accentKey: context.accent.key,
|
|
20064
|
+
context,
|
|
20065
|
+
primaryKey: context.primary.key,
|
|
20066
|
+
selectedBackgroundToken: selectedBackground.token,
|
|
20067
|
+
selectedPairId: nextSelectedPairId,
|
|
20068
|
+
themeCategory
|
|
20069
|
+
});
|
|
20070
|
+
emitAnalyticsEvent({
|
|
20071
|
+
name: "foreground_selection",
|
|
20072
|
+
...buildAnalyticsContext({
|
|
20073
|
+
foregroundToken: nextPair?.foreground.token,
|
|
20074
|
+
pairId: nextSelectedPairId,
|
|
20075
|
+
source
|
|
20076
|
+
})
|
|
20077
|
+
});
|
|
20078
|
+
if (bestRecommendedPair && nextSelectedPairId !== bestRecommendedPair.id) {
|
|
20079
|
+
emitAnalyticsEvent({
|
|
20080
|
+
name: "alternative_combination_selected",
|
|
20081
|
+
...buildAnalyticsContext({
|
|
20082
|
+
foregroundToken: nextPair?.foreground.token,
|
|
20083
|
+
pairId: nextSelectedPairId,
|
|
20084
|
+
source
|
|
20085
|
+
})
|
|
20086
|
+
});
|
|
20087
|
+
}
|
|
20088
|
+
};
|
|
20089
|
+
React5.useEffect(() => {
|
|
20090
|
+
if (!selectedBackground || selectedBackgroundPairs.length > 0) {
|
|
20091
|
+
return;
|
|
20092
|
+
}
|
|
20093
|
+
const key = `${themeCategory}:${context.primary.key}:${context.accent.key}:${selectedBackground.token}`;
|
|
20094
|
+
if (noValidStateRef.current.has(key)) {
|
|
20095
|
+
return;
|
|
20096
|
+
}
|
|
20097
|
+
noValidStateRef.current.add(key);
|
|
20098
|
+
emitAnalyticsEvent({
|
|
20099
|
+
name: "no_valid_combination_state",
|
|
20100
|
+
...buildAnalyticsContext({
|
|
20101
|
+
backgroundToken: selectedBackground.token
|
|
20102
|
+
})
|
|
20103
|
+
});
|
|
20104
|
+
}, [
|
|
20105
|
+
buildAnalyticsContext,
|
|
20106
|
+
context.accent.key,
|
|
20107
|
+
context.primary.key,
|
|
20108
|
+
emitAnalyticsEvent,
|
|
20109
|
+
selectedBackground,
|
|
20110
|
+
selectedBackgroundPairs.length,
|
|
20111
|
+
themeCategory
|
|
20112
|
+
]);
|
|
20113
|
+
React5.useEffect(() => {
|
|
20114
|
+
if (!isTechnicalDetailsOpen || technicalDetailsViewedRef.current) {
|
|
20115
|
+
return;
|
|
20116
|
+
}
|
|
20117
|
+
technicalDetailsViewedRef.current = true;
|
|
18606
20118
|
emitAnalyticsEvent({
|
|
18607
|
-
name: "
|
|
20119
|
+
name: "technical_details_viewed",
|
|
18608
20120
|
...buildAnalyticsContext({
|
|
18609
20121
|
source: "details"
|
|
18610
20122
|
})
|
|
18611
20123
|
});
|
|
18612
|
-
}, [buildAnalyticsContext, emitAnalyticsEvent]);
|
|
20124
|
+
}, [buildAnalyticsContext, emitAnalyticsEvent, isTechnicalDetailsOpen]);
|
|
18613
20125
|
if (!selectedBackground) {
|
|
18614
20126
|
return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
|
|
18615
20127
|
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "No approved background tones available" }),
|
|
18616
20128
|
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No approved tones are available for the current palette and colour selection." })
|
|
18617
20129
|
] });
|
|
18618
20130
|
}
|
|
18619
|
-
const compactControlsSummary = `${themeCategory === "brand" ? "Brand" : "Aboriginal"} palette, ${context.primary.label} primary, ${context.accent.label} accent, ${
|
|
20131
|
+
const compactControlsSummary = `${themeCategory === "brand" ? "Brand" : "Aboriginal"} palette, ${context.primary.label} primary, ${context.accent.label} accent, ${getPairingColorDisplayName4(
|
|
18620
20132
|
selectedBackground
|
|
18621
20133
|
)} background.`;
|
|
18622
20134
|
const renderControlsPanel = (isOverlay = false) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -18642,7 +20154,7 @@ function ColorPairingToolV3Content({
|
|
|
18642
20154
|
] }) }),
|
|
18643
20155
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-grey-200 px-5 py-4", children: [
|
|
18644
20156
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
18645
|
-
|
|
20157
|
+
COLOR_PAIRING_TOOL_DRAWER_STEPS2.map((step, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
18646
20158
|
"button",
|
|
18647
20159
|
{
|
|
18648
20160
|
type: "button",
|
|
@@ -18682,7 +20194,7 @@ function ColorPairingToolV3Content({
|
|
|
18682
20194
|
const isSelected = themeCategory === palette;
|
|
18683
20195
|
const label = palette === "brand" ? "Brand palette" : "Aboriginal palette";
|
|
18684
20196
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18685
|
-
|
|
20197
|
+
SelectorButton2,
|
|
18686
20198
|
{
|
|
18687
20199
|
label,
|
|
18688
20200
|
isSelected,
|
|
@@ -18695,14 +20207,14 @@ function ColorPairingToolV3Content({
|
|
|
18695
20207
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
18696
20208
|
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Primary colour family" }),
|
|
18697
20209
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableFamilies.map((family) => {
|
|
18698
|
-
const label =
|
|
20210
|
+
const label = getFamilySelectorLabel4(family, themeCategory, "primary colour");
|
|
18699
20211
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18700
|
-
|
|
20212
|
+
SelectorButton2,
|
|
18701
20213
|
{
|
|
18702
20214
|
label,
|
|
18703
20215
|
isSelected: family.key === context.primary.key,
|
|
18704
20216
|
onClick: () => handlePrimaryColorChange(family.key),
|
|
18705
|
-
swatch:
|
|
20217
|
+
swatch: getFamilySwatchColor4(family, 800)
|
|
18706
20218
|
},
|
|
18707
20219
|
family.key
|
|
18708
20220
|
);
|
|
@@ -18711,14 +20223,14 @@ function ColorPairingToolV3Content({
|
|
|
18711
20223
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
18712
20224
|
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Accent colour family" }),
|
|
18713
20225
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableAccentFamilies.map((family) => {
|
|
18714
|
-
const label =
|
|
20226
|
+
const label = getFamilySelectorLabel4(family, themeCategory, "accent colour");
|
|
18715
20227
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18716
|
-
|
|
20228
|
+
SelectorButton2,
|
|
18717
20229
|
{
|
|
18718
20230
|
label,
|
|
18719
20231
|
isSelected: family.key === context.accent.key,
|
|
18720
20232
|
onClick: () => handleAccentColorChange(family.key),
|
|
18721
|
-
swatch:
|
|
20233
|
+
swatch: getFamilySwatchColor4(family, 600)
|
|
18722
20234
|
},
|
|
18723
20235
|
family.key
|
|
18724
20236
|
);
|
|
@@ -18742,7 +20254,7 @@ function ColorPairingToolV3Content({
|
|
|
18742
20254
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: group.label })
|
|
18743
20255
|
] }),
|
|
18744
20256
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3", children: group.backgrounds.map((background) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
18745
|
-
|
|
20257
|
+
BackgroundSwatchButton2,
|
|
18746
20258
|
{
|
|
18747
20259
|
background,
|
|
18748
20260
|
hasPairs: (context.pairsByBackground[background.token]?.length ?? 0) > 0,
|
|
@@ -18755,37 +20267,15 @@ function ColorPairingToolV3Content({
|
|
|
18755
20267
|
},
|
|
18756
20268
|
group.key
|
|
18757
20269
|
)) }) }),
|
|
18758
|
-
/* @__PURE__ */ jsxRuntime.jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4 pr-1", children:
|
|
18759
|
-
|
|
18760
|
-
{
|
|
18761
|
-
|
|
18762
|
-
item,
|
|
18763
|
-
isSelected: item.pair.id === selectedPair?.id,
|
|
18764
|
-
onCopyPairing: () => copyValue(
|
|
18765
|
-
`pair:${item.pair.id}`,
|
|
18766
|
-
getPairingCopyText(item.pair),
|
|
18767
|
-
"Pairing copied",
|
|
18768
|
-
item.pair.id === bestRecommendedPair?.id ? {
|
|
18769
|
-
name: "best_recommendation_copied",
|
|
18770
|
-
...buildAnalyticsContext({
|
|
18771
|
-
foregroundToken: item.pair.foreground.token,
|
|
18772
|
-
pairId: item.pair.id,
|
|
18773
|
-
source: "recommendations-list"
|
|
18774
|
-
})
|
|
18775
|
-
} : void 0
|
|
18776
|
-
),
|
|
18777
|
-
onSelect: () => handlePairChange(item.pair.id, "recommendations-list")
|
|
18778
|
-
},
|
|
18779
|
-
item.pair.id
|
|
18780
|
-
)) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white px-5 py-5", children: [
|
|
18781
|
-
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "No valid combinations available" }),
|
|
18782
|
-
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No AAA-compliant foreground options are available for this background." })
|
|
18783
|
-
] }) }) })
|
|
20270
|
+
/* @__PURE__ */ jsxRuntime.jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4 pr-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-sm border border-grey-200 bg-grey-50 px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
20271
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "Review the result on the right" }),
|
|
20272
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "The right panel shows one recommended pairing first. Use approved alternatives there only when you need a different tone or emphasis." })
|
|
20273
|
+
] }) }) }) })
|
|
18784
20274
|
]
|
|
18785
20275
|
}
|
|
18786
20276
|
) }),
|
|
18787
20277
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-grey-200 px-5 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
18788
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-10 flex-1", children: isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "
|
|
20278
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-10 flex-1", children: isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Review the NSW recommendation in the result panel. Use alternatives there only if you need a different approved treatment." }) : null }),
|
|
18789
20279
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2 sm:w-auto sm:flex-none", children: [
|
|
18790
20280
|
isOverlay && isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
18791
20281
|
Button2,
|
|
@@ -18810,7 +20300,7 @@ function ColorPairingToolV3Content({
|
|
|
18810
20300
|
"data-slot": "tool-sidebar",
|
|
18811
20301
|
className: "hidden xl:sticky xl:top-[var(--tool-sidebar-top)] xl:block xl:self-start",
|
|
18812
20302
|
style: desktopSidebarStyle,
|
|
18813
|
-
children: /* @__PURE__ */ jsxRuntime.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() })
|
|
20303
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "h-[40rem] max-h-[40rem] gap-0 overflow-hidden border-grey-200 bg-grey-50/60 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() })
|
|
18814
20304
|
}
|
|
18815
20305
|
),
|
|
18816
20306
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "tool-results", className: "space-y-6", children: [
|
|
@@ -18818,7 +20308,7 @@ function ColorPairingToolV3Content({
|
|
|
18818
20308
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "gap-4 px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between", children: [
|
|
18819
20309
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
18820
20310
|
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
|
|
18821
|
-
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Open the
|
|
20311
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Open the drawer to set palette, colour families, and background. The result panel shows the NSW recommendation first." }),
|
|
18822
20312
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: compactControlsSummary })
|
|
18823
20313
|
] }),
|
|
18824
20314
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -18850,49 +20340,124 @@ function ColorPairingToolV3Content({
|
|
|
18850
20340
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { ref: resultSectionRef, className: "space-y-6", "aria-label": "Current result", children: [
|
|
18851
20341
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sr-only", "aria-live": "polite", children: liveAnnouncement }),
|
|
18852
20342
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18853
|
-
|
|
20343
|
+
CurrentResultCard2,
|
|
18854
20344
|
{
|
|
18855
20345
|
bestPair: bestRecommendedPair,
|
|
18856
|
-
|
|
20346
|
+
copiedKey,
|
|
20347
|
+
onCopyPairing: () => previewPair ? copyValue(
|
|
20348
|
+
"current-pairing",
|
|
20349
|
+
getPairingCopyText2(previewPair),
|
|
20350
|
+
"Pairing copied",
|
|
20351
|
+
previewPair.id === bestRecommendedPair?.id ? {
|
|
20352
|
+
name: "best_recommendation_copied",
|
|
20353
|
+
...buildAnalyticsContext({
|
|
20354
|
+
foregroundToken: previewPair.foreground.token,
|
|
20355
|
+
pairId: previewPair.id,
|
|
20356
|
+
source: "current-result"
|
|
20357
|
+
})
|
|
20358
|
+
} : void 0
|
|
20359
|
+
) : void 0,
|
|
18857
20360
|
pair: previewPair,
|
|
20361
|
+
supportText: currentPairSupportText,
|
|
18858
20362
|
selectedBackground
|
|
18859
20363
|
}
|
|
18860
20364
|
)
|
|
18861
20365
|
] }),
|
|
18862
|
-
bestRecommendedPair ? /* @__PURE__ */ jsxRuntime.
|
|
18863
|
-
|
|
18864
|
-
|
|
18865
|
-
|
|
18866
|
-
|
|
18867
|
-
|
|
18868
|
-
|
|
18869
|
-
|
|
18870
|
-
"best-pairing",
|
|
18871
|
-
getPairingCopyText(bestRecommendedPair),
|
|
18872
|
-
"Pairing copied",
|
|
20366
|
+
bestRecommendedPair || alternativeRecommendationGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
20367
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
20368
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Approved alternatives" }),
|
|
20369
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "text-muted-foreground", children: "These are approved alternatives for different tone or emphasis." })
|
|
20370
|
+
] }),
|
|
20371
|
+
alternativeRecommendationGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20372
|
+
visibleAlternativeRecommendationGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
20373
|
+
RecommendationGroupSection,
|
|
18873
20374
|
{
|
|
18874
|
-
|
|
18875
|
-
|
|
18876
|
-
|
|
18877
|
-
|
|
18878
|
-
|
|
18879
|
-
|
|
20375
|
+
title: group.title,
|
|
20376
|
+
description: group.description,
|
|
20377
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: group.items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
20378
|
+
RecommendationCard2,
|
|
20379
|
+
{
|
|
20380
|
+
copiedKey,
|
|
20381
|
+
item,
|
|
20382
|
+
isSelected: item.pair.id === selectedPair?.id,
|
|
20383
|
+
onCopyPairing: () => copyValue(
|
|
20384
|
+
`pair:${item.pair.id}`,
|
|
20385
|
+
getPairingCopyText2(item.pair),
|
|
20386
|
+
"Pairing copied",
|
|
20387
|
+
item.pair.id === bestRecommendedPair?.id ? {
|
|
20388
|
+
name: "best_recommendation_copied",
|
|
20389
|
+
...buildAnalyticsContext({
|
|
20390
|
+
foregroundToken: item.pair.foreground.token,
|
|
20391
|
+
pairId: item.pair.id,
|
|
20392
|
+
source: "recommendations-list"
|
|
20393
|
+
})
|
|
20394
|
+
} : void 0
|
|
20395
|
+
),
|
|
20396
|
+
onSelect: () => handlePairChange(item.pair.id, "recommendations-list")
|
|
20397
|
+
},
|
|
20398
|
+
item.pair.id
|
|
20399
|
+
)) })
|
|
20400
|
+
},
|
|
20401
|
+
group.id
|
|
20402
|
+
)),
|
|
20403
|
+
hiddenAlternativeCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20404
|
+
Button2,
|
|
20405
|
+
{
|
|
20406
|
+
variant: "ghost",
|
|
20407
|
+
color: "grey",
|
|
20408
|
+
className: "w-full justify-center border border-grey-200 bg-white sm:w-auto",
|
|
20409
|
+
onClick: () => setIsShowingAllAlternatives(true),
|
|
20410
|
+
children: [
|
|
20411
|
+
"Show ",
|
|
20412
|
+
hiddenAlternativeCount,
|
|
20413
|
+
" more"
|
|
20414
|
+
]
|
|
18880
20415
|
}
|
|
18881
|
-
)
|
|
18882
|
-
|
|
18883
|
-
|
|
18884
|
-
|
|
18885
|
-
|
|
18886
|
-
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
|
|
18890
|
-
|
|
18891
|
-
|
|
18892
|
-
|
|
18893
|
-
|
|
20416
|
+
) : null
|
|
20417
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
|
|
20418
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: "No other AAA alternatives" }),
|
|
20419
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "The NSW recommended pairing is the only AAA-compliant foreground option for this background." })
|
|
20420
|
+
] })
|
|
20421
|
+
] }) : null,
|
|
20422
|
+
/* @__PURE__ */ jsxRuntime.jsx("section", { className: "space-y-3", children: /* @__PURE__ */ jsxRuntime.jsx(Collapsible, { open: isTechnicalDetailsOpen, onOpenChange: setIsTechnicalDetailsOpen, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white", children: [
|
|
20423
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20424
|
+
"button",
|
|
20425
|
+
{
|
|
20426
|
+
type: "button",
|
|
20427
|
+
className: "flex w-full items-center justify-between gap-4 px-4 py-4 text-left transition-colors hover:bg-grey-50 focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden sm:px-5",
|
|
20428
|
+
children: [
|
|
20429
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
20430
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 6, className: "text-foreground", trim: "normal", children: "Technical colour values" }),
|
|
20431
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "text-muted-foreground", children: "Token, tone, HEX, RGB, HSL, and OKLCH values for advanced use." })
|
|
20432
|
+
] }),
|
|
20433
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20434
|
+
"span",
|
|
20435
|
+
{
|
|
20436
|
+
className: cn(
|
|
20437
|
+
"inline-flex items-center gap-2 text-sm font-semibold text-primary-800",
|
|
20438
|
+
isTechnicalDetailsOpen && "text-foreground"
|
|
20439
|
+
),
|
|
20440
|
+
children: [
|
|
20441
|
+
isTechnicalDetailsOpen ? "Hide" : "Show",
|
|
20442
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20443
|
+
Icons.keyboard_arrow_down,
|
|
20444
|
+
{
|
|
20445
|
+
"data-slot": "icon",
|
|
20446
|
+
className: cn(
|
|
20447
|
+
"size-5 transition-transform",
|
|
20448
|
+
isTechnicalDetailsOpen && "rotate-180"
|
|
20449
|
+
)
|
|
20450
|
+
}
|
|
20451
|
+
)
|
|
20452
|
+
]
|
|
20453
|
+
}
|
|
20454
|
+
)
|
|
20455
|
+
]
|
|
20456
|
+
}
|
|
20457
|
+
) }),
|
|
20458
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-grey-200 px-4 py-4 sm:px-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
|
|
18894
20459
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18895
|
-
|
|
20460
|
+
TechnicalDetailsPanel2,
|
|
18896
20461
|
{
|
|
18897
20462
|
title: "Background values",
|
|
18898
20463
|
color: selectedBackground,
|
|
@@ -18902,7 +20467,7 @@ function ColorPairingToolV3Content({
|
|
|
18902
20467
|
}
|
|
18903
20468
|
),
|
|
18904
20469
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18905
|
-
|
|
20470
|
+
TechnicalDetailsPanel2,
|
|
18906
20471
|
{
|
|
18907
20472
|
title: "Foreground values",
|
|
18908
20473
|
color: detailForeground,
|
|
@@ -18911,51 +20476,51 @@ function ColorPairingToolV3Content({
|
|
|
18911
20476
|
onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
|
|
18912
20477
|
}
|
|
18913
20478
|
)
|
|
18914
|
-
] })
|
|
18915
|
-
|
|
18916
|
-
|
|
18917
|
-
|
|
18918
|
-
|
|
18919
|
-
|
|
18920
|
-
|
|
18921
|
-
|
|
18922
|
-
|
|
18923
|
-
|
|
18924
|
-
|
|
18925
|
-
|
|
18926
|
-
|
|
18927
|
-
|
|
18928
|
-
|
|
18929
|
-
|
|
18930
|
-
|
|
18931
|
-
|
|
18932
|
-
|
|
18933
|
-
|
|
18934
|
-
|
|
18935
|
-
|
|
18936
|
-
|
|
18937
|
-
|
|
18938
|
-
|
|
18939
|
-
|
|
18940
|
-
|
|
18941
|
-
}
|
|
18942
|
-
|
|
18943
|
-
|
|
18944
|
-
|
|
18945
|
-
] })
|
|
20479
|
+
] }) }) })
|
|
20480
|
+
] }) }) }),
|
|
20481
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-2", children: [
|
|
20482
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: "Share colour pairing" }),
|
|
20483
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white px-4 py-4", children: [
|
|
20484
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
20485
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Copy a link to this current result." }),
|
|
20486
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20487
|
+
Button2,
|
|
20488
|
+
{
|
|
20489
|
+
variant: "ghost",
|
|
20490
|
+
color: "grey",
|
|
20491
|
+
size: "sm",
|
|
20492
|
+
className: "shrink-0 self-start sm:self-center",
|
|
20493
|
+
onClick: () => copyValue(
|
|
20494
|
+
"share-url",
|
|
20495
|
+
typeof window === "undefined" ? shareUrl : new URL(shareUrl, window.location.origin).toString(),
|
|
20496
|
+
"Colour pairing link copied"
|
|
20497
|
+
),
|
|
20498
|
+
"aria-label": copiedKey === "share-url" ? "Colour pairing URL copied to clipboard" : "Copy colour pairing URL to clipboard",
|
|
20499
|
+
title: copiedKey === "share-url" ? "Copied" : "Copy URL",
|
|
20500
|
+
children: copiedKey === "share-url" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20501
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" }),
|
|
20502
|
+
"Copied"
|
|
20503
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20504
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
|
|
20505
|
+
"Copy URL"
|
|
20506
|
+
] })
|
|
20507
|
+
}
|
|
20508
|
+
)
|
|
20509
|
+
] }),
|
|
20510
|
+
/* @__PURE__ */ jsxRuntime.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 })
|
|
18946
20511
|
] })
|
|
18947
20512
|
] })
|
|
18948
20513
|
] })
|
|
18949
20514
|
] });
|
|
18950
20515
|
}
|
|
18951
|
-
function
|
|
20516
|
+
function ColorPairingToolV4({
|
|
18952
20517
|
onAnalyticsEvent = () => {
|
|
18953
20518
|
},
|
|
18954
|
-
visibleFormats =
|
|
20519
|
+
visibleFormats = DEFAULT_VISIBLE_FORMATS4
|
|
18955
20520
|
} = {}) {
|
|
18956
20521
|
const normalizedVisibleFormats = [...new Set(visibleFormats)];
|
|
18957
|
-
return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18958
|
-
|
|
20522
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolV4Loading, {}), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20523
|
+
ColorPairingToolV4Content,
|
|
18959
20524
|
{
|
|
18960
20525
|
onAnalyticsEvent,
|
|
18961
20526
|
visibleFormats: normalizedVisibleFormats
|
|
@@ -21586,7 +23151,7 @@ function FormatToggle({ format, setFormat }) {
|
|
|
21586
23151
|
|
|
21587
23152
|
// package.json
|
|
21588
23153
|
var package_default = {
|
|
21589
|
-
version: "1.
|
|
23154
|
+
version: "1.105.0"};
|
|
21590
23155
|
function Logo(props) {
|
|
21591
23156
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
21592
23157
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "NSW Government" }),
|
|
@@ -37349,8 +38914,20 @@ function getHeadings(slugify$1 = slugify.slugifyWithCounter()) {
|
|
|
37349
38914
|
});
|
|
37350
38915
|
return result;
|
|
37351
38916
|
}
|
|
38917
|
+
function areHeadingNodesEqual(left, right) {
|
|
38918
|
+
if (left.level !== right.level || left.id !== right.id || left.title !== right.title) {
|
|
38919
|
+
return false;
|
|
38920
|
+
}
|
|
38921
|
+
if (left.children.length !== right.children.length) {
|
|
38922
|
+
return false;
|
|
38923
|
+
}
|
|
38924
|
+
return left.children.every((child, index) => areHeadingNodesEqual(child, right.children[index]));
|
|
38925
|
+
}
|
|
37352
38926
|
function areHeadingTreesEqual(left, right) {
|
|
37353
|
-
|
|
38927
|
+
if (left.length !== right.length) {
|
|
38928
|
+
return false;
|
|
38929
|
+
}
|
|
38930
|
+
return left.every((heading, index) => areHeadingNodesEqual(heading, right[index]));
|
|
37354
38931
|
}
|
|
37355
38932
|
function usePageHeadings(enabled = true) {
|
|
37356
38933
|
const [headings, setHeadings] = React5.useState([]);
|
|
@@ -37557,6 +39134,7 @@ exports.ColorCard = ColorCard;
|
|
|
37557
39134
|
exports.ColorPairingTool = ColorPairingTool;
|
|
37558
39135
|
exports.ColorPairingToolV2 = ColorPairingToolV2;
|
|
37559
39136
|
exports.ColorPairingToolV3 = ColorPairingToolV3;
|
|
39137
|
+
exports.ColorPairingToolV4 = ColorPairingToolV4;
|
|
37560
39138
|
exports.ColorSwatches = ColorSwatches;
|
|
37561
39139
|
exports.ColourScale = ColourScale;
|
|
37562
39140
|
exports.ComboChart = ComboChart;
|