@nswds/app 1.104.0 → 1.105.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 +49 -0
- package/dist/index.cjs +1747 -114
- 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 +1747 -115
- package/dist/index.js.map +1 -1
- package/dist/styles.css +49 -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,16 +18600,1602 @@ 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 COLOR_PAIRING_TOOL_DRAWER_STEPS2 = [
|
|
19007
|
+
{
|
|
19008
|
+
id: "colours",
|
|
19009
|
+
title: "Choose colours",
|
|
19010
|
+
eyebrow: "Step 1 of 3",
|
|
19011
|
+
description: "Select the palette, primary family, and accent family."
|
|
19012
|
+
},
|
|
19013
|
+
{
|
|
19014
|
+
id: "backgrounds",
|
|
19015
|
+
title: "Choose background",
|
|
19016
|
+
eyebrow: "Step 2 of 3",
|
|
19017
|
+
description: "Pick the background tone that you want to pair."
|
|
19018
|
+
},
|
|
19019
|
+
{
|
|
19020
|
+
id: "refine",
|
|
19021
|
+
title: "Refine or override recommendation",
|
|
19022
|
+
eyebrow: "Step 3 of 3",
|
|
19023
|
+
description: "Use the result panel to review the NSW default pairing and override it only when a different approved option is needed."
|
|
19024
|
+
}
|
|
19025
|
+
];
|
|
19026
|
+
var COLOR_PAIRING_TOOL_V4_ANALYTICS_EVENT = "nsw-colour-pairing-tool-v4";
|
|
19027
|
+
function getToneFromToken4(token) {
|
|
19028
|
+
if (!token) return null;
|
|
19029
|
+
const match = token.match(/-(\d+)$/);
|
|
19030
|
+
return match ? Number.parseInt(match[1], 10) : null;
|
|
19031
|
+
}
|
|
19032
|
+
function getFamilySwatchColor4(family, preferredTone = 600) {
|
|
19033
|
+
const exactMatch = family.colors.find((color2) => color2.tone === preferredTone);
|
|
19034
|
+
if (exactMatch) {
|
|
19035
|
+
return exactMatch.hex;
|
|
19036
|
+
}
|
|
19037
|
+
const closestMatch = [...family.colors].sort(
|
|
19038
|
+
(left, right) => Math.abs(left.tone - preferredTone) - Math.abs(right.tone - preferredTone)
|
|
19039
|
+
)[0];
|
|
19040
|
+
return closestMatch?.hex ?? "transparent";
|
|
19041
|
+
}
|
|
19042
|
+
function getFamilySelectorLabel4(family, themeCategory, selectionRole) {
|
|
19043
|
+
if (themeCategory !== "aboriginal") {
|
|
19044
|
+
return family.label;
|
|
19045
|
+
}
|
|
19046
|
+
const preferredTone = selectionRole === "primary colour" ? 800 : 600;
|
|
19047
|
+
return family.colors.find((color2) => color2.tone === preferredTone)?.name ?? family.label;
|
|
19048
|
+
}
|
|
19049
|
+
function getPairingColorDisplayName4(color2) {
|
|
19050
|
+
return color2.name ?? `${color2.familyLabel} ${color2.tone}`;
|
|
19051
|
+
}
|
|
19052
|
+
function isWhiteForegroundPair4(pair) {
|
|
19053
|
+
return pair.foreground.token === "white";
|
|
19054
|
+
}
|
|
19055
|
+
function isLargeTextOnlyPair2(pair) {
|
|
19056
|
+
return pair.passes.aaaLarge && !pair.passes.aaaText;
|
|
19057
|
+
}
|
|
19058
|
+
function getWhiteForegroundGuidance4(pair) {
|
|
19059
|
+
if (pair.passes.aaaText) {
|
|
19060
|
+
return "White is approved for headings, body copy, and calls to action on this background.";
|
|
19061
|
+
}
|
|
19062
|
+
if (pair.passes.aaaLarge) {
|
|
19063
|
+
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.";
|
|
19064
|
+
}
|
|
19065
|
+
return "Do not use white on this background. Choose one of the recommended foregrounds below instead.";
|
|
19066
|
+
}
|
|
19067
|
+
function getPreviewGuidance4(pair, isRecommended) {
|
|
19068
|
+
if (!isWhiteForegroundPair4(pair)) {
|
|
19069
|
+
return "Use only AAA-recommended combinations across your selected primary, accent, and grey families.";
|
|
19070
|
+
}
|
|
19071
|
+
if (isRecommended) {
|
|
19072
|
+
return "Use white text on dark colour only when it meets AAA for headings, body copy, and calls to action.";
|
|
19073
|
+
}
|
|
19074
|
+
return getWhiteForegroundGuidance4(pair);
|
|
19075
|
+
}
|
|
19076
|
+
function getPreferredPairForBackground4(pairs, preferredPairId) {
|
|
19077
|
+
if (preferredPairId) {
|
|
19078
|
+
const preferredPair = pairs.find((pair) => pair.id === preferredPairId);
|
|
19079
|
+
if (preferredPair) {
|
|
19080
|
+
return preferredPair;
|
|
19081
|
+
}
|
|
19082
|
+
}
|
|
19083
|
+
return pairs.find((pair) => !isWhiteForegroundPair4(pair)) ?? pairs[0] ?? null;
|
|
19084
|
+
}
|
|
19085
|
+
function getDefaultBackgroundToken4(context) {
|
|
19086
|
+
for (const tone of PREFERRED_BACKGROUND_TONES4) {
|
|
19087
|
+
for (const group of context.backgroundGroups) {
|
|
19088
|
+
const match = group.backgrounds.find(
|
|
19089
|
+
(background) => background.tone === tone && (context.pairsByBackground[background.token]?.length ?? 0) > 0
|
|
19090
|
+
);
|
|
19091
|
+
if (match) {
|
|
19092
|
+
return match.token;
|
|
19093
|
+
}
|
|
19094
|
+
}
|
|
19095
|
+
}
|
|
19096
|
+
for (const tone of PREFERRED_BACKGROUND_TONES4) {
|
|
19097
|
+
for (const group of context.backgroundGroups) {
|
|
19098
|
+
const match = group.backgrounds.find((background) => background.tone === tone);
|
|
19099
|
+
if (match) {
|
|
19100
|
+
return match.token;
|
|
19101
|
+
}
|
|
19102
|
+
}
|
|
19103
|
+
}
|
|
19104
|
+
return context.backgrounds[0]?.token ?? "";
|
|
19105
|
+
}
|
|
19106
|
+
function resolveBackgroundToken4(context, preferredToken, preferredTone) {
|
|
19107
|
+
if (preferredToken && context.backgrounds.some((background) => background.token === preferredToken)) {
|
|
19108
|
+
return preferredToken;
|
|
19109
|
+
}
|
|
19110
|
+
if (preferredTone !== null && preferredTone !== void 0) {
|
|
19111
|
+
for (const group of context.backgroundGroups) {
|
|
19112
|
+
const match = group.backgrounds.find((background) => background.tone === preferredTone);
|
|
19113
|
+
if (match) {
|
|
19114
|
+
return match.token;
|
|
19115
|
+
}
|
|
19116
|
+
}
|
|
19117
|
+
}
|
|
19118
|
+
return getDefaultBackgroundToken4(context);
|
|
19119
|
+
}
|
|
19120
|
+
function getInitialPairingState4(searchParams) {
|
|
19121
|
+
const paletteParam = searchParams.get("palette");
|
|
19122
|
+
const primaryParam = searchParams.get("primary");
|
|
19123
|
+
const accentParam = searchParams.get("accent");
|
|
19124
|
+
const pairParam = searchParams.get("pair");
|
|
19125
|
+
const backgroundParam = searchParams.get("background");
|
|
19126
|
+
const themeCategory = paletteParam === "brand" || paletteParam === "aboriginal" ? paletteParam : "brand";
|
|
19127
|
+
const context = getPairingContext(themeCategory, primaryParam, accentParam);
|
|
19128
|
+
const shouldUseDefaultBrandExample = !backgroundParam && !pairParam && themeCategory === "brand" && context.primary.key === "blue" && context.accent.key === "red";
|
|
19129
|
+
const defaultBackgroundToken = shouldUseDefaultBrandExample ? context.backgrounds.some(
|
|
19130
|
+
(background) => background.token === DEFAULT_INITIAL_BACKGROUND_TOKEN4
|
|
19131
|
+
) ? DEFAULT_INITIAL_BACKGROUND_TOKEN4 : null : null;
|
|
19132
|
+
const defaultPairId = shouldUseDefaultBrandExample && defaultBackgroundToken && context.pairsByBackground[defaultBackgroundToken]?.some(
|
|
19133
|
+
(pair) => pair.id === DEFAULT_INITIAL_PAIR_ID4
|
|
19134
|
+
) ? DEFAULT_INITIAL_PAIR_ID4 : null;
|
|
19135
|
+
const pairBackgroundToken = context.recommendedPairs.find((pair) => pair.id === pairParam)?.background.token ?? null;
|
|
19136
|
+
const selectedBackgroundToken = resolveBackgroundToken4(
|
|
19137
|
+
context,
|
|
19138
|
+
backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken,
|
|
19139
|
+
getToneFromToken4(backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken)
|
|
19140
|
+
);
|
|
19141
|
+
const selectedPairId = getPreferredPairForBackground4(
|
|
19142
|
+
context.pairsByBackground[selectedBackgroundToken] ?? [],
|
|
19143
|
+
pairParam ?? defaultPairId
|
|
19144
|
+
)?.id ?? "";
|
|
19145
|
+
return {
|
|
19146
|
+
accentKey: context.accent.key,
|
|
19147
|
+
primaryKey: context.primary.key,
|
|
19148
|
+
selectedBackgroundToken,
|
|
19149
|
+
selectedPairId,
|
|
19150
|
+
themeCategory
|
|
19151
|
+
};
|
|
19152
|
+
}
|
|
19153
|
+
function getReadableTextColor3(tone) {
|
|
19154
|
+
return tone >= 600 ? "#ffffff" : "#002664";
|
|
19155
|
+
}
|
|
19156
|
+
function getBackgroundOptionName2(background) {
|
|
19157
|
+
return background.name ?? `${background.familyLabel} ${background.tone}`;
|
|
19158
|
+
}
|
|
19159
|
+
function getMainPairingLabel(pair, bestPair) {
|
|
19160
|
+
if (!pair) {
|
|
19161
|
+
return "No AAA pairing available";
|
|
19162
|
+
}
|
|
19163
|
+
if (pair.id === bestPair?.id) {
|
|
19164
|
+
return "NSW recommended pairing";
|
|
19165
|
+
}
|
|
19166
|
+
if (isWhiteForegroundPair4(pair) && isLargeTextOnlyPair2(pair)) {
|
|
19167
|
+
return "Large-text example only";
|
|
19168
|
+
}
|
|
19169
|
+
if (isWhiteForegroundPair4(pair) && !pair.passes.aaaLarge) {
|
|
19170
|
+
return "Example only";
|
|
19171
|
+
}
|
|
19172
|
+
return "Approved alternative";
|
|
19173
|
+
}
|
|
19174
|
+
function getMainPairingSupportCopy(pair, bestPair, context) {
|
|
19175
|
+
if (!pair) {
|
|
19176
|
+
return "No AAA-compliant foreground available for this background.";
|
|
19177
|
+
}
|
|
19178
|
+
if (pair.id === bestPair?.id) {
|
|
19179
|
+
return getBestRecommendationReason2(pair, context);
|
|
19180
|
+
}
|
|
19181
|
+
if (isWhiteForegroundPair4(pair) && isLargeTextOnlyPair2(pair)) {
|
|
19182
|
+
return "White works here for large text only. Use the NSW default for standard body copy and smaller interface text.";
|
|
19183
|
+
}
|
|
19184
|
+
if (isWhiteForegroundPair4(pair) && !pair.passes.aaaLarge) {
|
|
19185
|
+
return "White does not meet AAA on this background. Choose a different approved background or foreground.";
|
|
19186
|
+
}
|
|
19187
|
+
return "Approved AAA alternative when a different tone or emphasis is needed.";
|
|
19188
|
+
}
|
|
19189
|
+
function getBestRecommendationReason2(pair, context) {
|
|
19190
|
+
if (isWhiteForegroundPair4(pair)) {
|
|
19191
|
+
return "Recommended because this background is dark enough to support white text at AAA contrast.";
|
|
19192
|
+
}
|
|
19193
|
+
if (pair.foreground.familyKey === pair.background.familyKey) {
|
|
19194
|
+
return "Recommended because it stays within the same colour family while keeping clear AAA contrast.";
|
|
19195
|
+
}
|
|
19196
|
+
if (pair.foreground.familyKey === context.grey.key) {
|
|
19197
|
+
return "Recommended because grey provides a strong neutral contrast without competing with the background.";
|
|
19198
|
+
}
|
|
19199
|
+
if (pair.foreground.familyKey === context.accent.key) {
|
|
19200
|
+
return "Recommended because the selected accent family adds emphasis while preserving AAA contrast.";
|
|
19201
|
+
}
|
|
19202
|
+
if (pair.foreground.familyKey === context.primary.key) {
|
|
19203
|
+
return "Recommended because the selected primary family gives the clearest AAA-compliant contrast for this background.";
|
|
19204
|
+
}
|
|
19205
|
+
return "Recommended because it is the clearest NSW-approved AAA pairing for this background.";
|
|
19206
|
+
}
|
|
19207
|
+
function getRecommendationCategory2(pair, bestPair, context) {
|
|
19208
|
+
if (pair.id === bestPair?.id) return "best";
|
|
19209
|
+
if (isWhiteForegroundPair4(pair)) return "white";
|
|
19210
|
+
if (pair.foreground.familyKey === pair.background.familyKey) return "same-family";
|
|
19211
|
+
if (pair.foreground.familyKey === context.accent.key) return "accent-family";
|
|
19212
|
+
if (pair.foreground.familyKey === context.grey.key) return "grey-option";
|
|
19213
|
+
if (pair.foreground.familyKey === context.primary.key) return "primary-family";
|
|
19214
|
+
return "approved";
|
|
19215
|
+
}
|
|
19216
|
+
function getRecommendationCategoryLabel2(category) {
|
|
19217
|
+
switch (category) {
|
|
19218
|
+
case "best":
|
|
19219
|
+
return "Best recommended";
|
|
19220
|
+
case "same-family":
|
|
19221
|
+
return "Same family";
|
|
19222
|
+
case "accent-family":
|
|
19223
|
+
return "Accent family";
|
|
19224
|
+
case "grey-option":
|
|
19225
|
+
return "Grey option";
|
|
19226
|
+
case "primary-family":
|
|
19227
|
+
return "Primary family";
|
|
19228
|
+
case "white":
|
|
19229
|
+
return "White";
|
|
19230
|
+
default:
|
|
19231
|
+
return "Approved option";
|
|
19232
|
+
}
|
|
19233
|
+
}
|
|
19234
|
+
function getRecommendationSortRank2(category) {
|
|
19235
|
+
switch (category) {
|
|
19236
|
+
case "best":
|
|
19237
|
+
return 0;
|
|
19238
|
+
case "same-family":
|
|
19239
|
+
return 1;
|
|
19240
|
+
case "accent-family":
|
|
19241
|
+
return 2;
|
|
19242
|
+
case "grey-option":
|
|
19243
|
+
return 3;
|
|
19244
|
+
case "white":
|
|
19245
|
+
return 4;
|
|
19246
|
+
case "primary-family":
|
|
19247
|
+
return 5;
|
|
19248
|
+
default:
|
|
19249
|
+
return 6;
|
|
19250
|
+
}
|
|
19251
|
+
}
|
|
19252
|
+
function getRecommendationGroupId(category) {
|
|
19253
|
+
switch (category) {
|
|
19254
|
+
case "best":
|
|
19255
|
+
case "same-family":
|
|
19256
|
+
case "accent-family":
|
|
19257
|
+
case "grey-option":
|
|
19258
|
+
case "primary-family":
|
|
19259
|
+
return "good-alternatives";
|
|
19260
|
+
case "white":
|
|
19261
|
+
case "approved":
|
|
19262
|
+
return "edge-options";
|
|
19263
|
+
default:
|
|
19264
|
+
return null;
|
|
19265
|
+
}
|
|
19266
|
+
}
|
|
19267
|
+
function buildRecommendationGroups(items) {
|
|
19268
|
+
const groupedItems = items.reduce(
|
|
19269
|
+
(accumulator, item) => {
|
|
19270
|
+
const groupId = getRecommendationGroupId(item.category);
|
|
19271
|
+
if (!groupId) {
|
|
19272
|
+
return accumulator;
|
|
19273
|
+
}
|
|
19274
|
+
accumulator[groupId].push(item);
|
|
19275
|
+
return accumulator;
|
|
19276
|
+
},
|
|
19277
|
+
{
|
|
19278
|
+
"edge-options": [],
|
|
19279
|
+
"good-alternatives": []
|
|
19280
|
+
}
|
|
19281
|
+
);
|
|
19282
|
+
const groups = [
|
|
19283
|
+
{
|
|
19284
|
+
id: "good-alternatives",
|
|
19285
|
+
title: "Good alternatives",
|
|
19286
|
+
description: "These pairings still meet AAA and stay close to the NSW recommendation in tone, neutrality, or emphasis.",
|
|
19287
|
+
items: groupedItems["good-alternatives"]
|
|
19288
|
+
},
|
|
19289
|
+
{
|
|
19290
|
+
id: "edge-options",
|
|
19291
|
+
title: "Edge and less common options",
|
|
19292
|
+
description: "These are valid AAA pairings, but they are less typical NSW defaults and should be used more deliberately.",
|
|
19293
|
+
items: groupedItems["edge-options"]
|
|
19294
|
+
}
|
|
19295
|
+
];
|
|
19296
|
+
return groups.filter((group) => group.items.length > 0);
|
|
19297
|
+
}
|
|
19298
|
+
function getAvailabilityMeta2(isSelected, hasPairs) {
|
|
19299
|
+
if (isSelected && hasPairs) {
|
|
19300
|
+
return {
|
|
19301
|
+
description: "Selected background with AAA foreground options.",
|
|
19302
|
+
icon: Icons.check_circle,
|
|
19303
|
+
label: "Selected",
|
|
19304
|
+
tone: "selected"
|
|
19305
|
+
};
|
|
19306
|
+
}
|
|
19307
|
+
if (isSelected) {
|
|
19308
|
+
return {
|
|
19309
|
+
description: "Selected background with no AAA-compliant foreground available.",
|
|
19310
|
+
icon: Icons.warning,
|
|
19311
|
+
label: "Selected, no AAA",
|
|
19312
|
+
tone: "unavailable"
|
|
19313
|
+
};
|
|
19314
|
+
}
|
|
19315
|
+
if (hasPairs) {
|
|
19316
|
+
return {
|
|
19317
|
+
description: "AAA foreground options available.",
|
|
19318
|
+
icon: Icons.radio_button_checked,
|
|
19319
|
+
label: "Available",
|
|
19320
|
+
tone: "available"
|
|
19321
|
+
};
|
|
19322
|
+
}
|
|
19323
|
+
return {
|
|
19324
|
+
description: "No AAA-compliant foreground available for this background.",
|
|
19325
|
+
icon: Icons.close,
|
|
19326
|
+
label: "No AAA",
|
|
19327
|
+
tone: "unavailable"
|
|
19328
|
+
};
|
|
19329
|
+
}
|
|
19330
|
+
function getPairingCopyText2(pair) {
|
|
19331
|
+
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";
|
|
19332
|
+
return [
|
|
19333
|
+
`Background: ${pair.background.token} (${pair.background.hex})`,
|
|
19334
|
+
`Foreground: ${pair.foreground.token} (${pair.foreground.hex})`,
|
|
19335
|
+
`Contrast ratio: ${pair.contrastRatio.toFixed(2)}:1`,
|
|
19336
|
+
accessibilityLine
|
|
19337
|
+
].join("\n");
|
|
19338
|
+
}
|
|
19339
|
+
function getLiveAnnouncement2(pair, background) {
|
|
19340
|
+
if (!background) {
|
|
19341
|
+
return "No approved background tones available.";
|
|
19342
|
+
}
|
|
19343
|
+
if (!pair) {
|
|
19344
|
+
return `${background.token} selected. No AAA-compliant foreground options available for this selection.`;
|
|
19345
|
+
}
|
|
19346
|
+
if (isWhiteForegroundPair4(pair) && isLargeTextOnlyPair2(pair)) {
|
|
19347
|
+
return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for large text only.`;
|
|
19348
|
+
}
|
|
19349
|
+
if (isWhiteForegroundPair4(pair) && !pair.passes.aaaLarge) {
|
|
19350
|
+
return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Fails AAA for normal and large text.`;
|
|
19351
|
+
}
|
|
19352
|
+
return `${background.token} with ${pair.foreground.token}. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for normal and large text.`;
|
|
19353
|
+
}
|
|
19354
|
+
function formatValueRows2(color2, visibleFormats) {
|
|
19355
|
+
const hasDisplayTone = color2.token !== "white";
|
|
19356
|
+
return [
|
|
19357
|
+
{ key: "token", label: "Token", value: color2.token, copyable: true },
|
|
19358
|
+
{
|
|
19359
|
+
key: "tone",
|
|
19360
|
+
label: "Tone",
|
|
19361
|
+
value: hasDisplayTone ? String(color2.tone) : "Not applicable",
|
|
19362
|
+
copyable: hasDisplayTone
|
|
19363
|
+
},
|
|
19364
|
+
...visibleFormats.map((format) => ({
|
|
19365
|
+
key: format,
|
|
19366
|
+
label: format.toUpperCase(),
|
|
19367
|
+
value: color2[format],
|
|
19368
|
+
copyable: true
|
|
19369
|
+
}))
|
|
19370
|
+
];
|
|
19371
|
+
}
|
|
19372
|
+
function SelectorButton2({
|
|
19373
|
+
description,
|
|
19374
|
+
isSelected,
|
|
19375
|
+
label,
|
|
19376
|
+
onClick,
|
|
19377
|
+
swatch
|
|
19378
|
+
}) {
|
|
19379
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19380
|
+
"button",
|
|
19381
|
+
{
|
|
19382
|
+
type: "button",
|
|
19383
|
+
"aria-pressed": isSelected,
|
|
19384
|
+
onClick,
|
|
19385
|
+
className: cn(
|
|
19386
|
+
"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",
|
|
19387
|
+
isSelected ? "border-primary-800 bg-primary-50" : "border-grey-300 bg-white hover:border-primary-500 hover:bg-grey-50"
|
|
19388
|
+
),
|
|
19389
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
|
|
19390
|
+
swatch ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19391
|
+
"span",
|
|
19392
|
+
{
|
|
19393
|
+
"aria-hidden": "true",
|
|
19394
|
+
className: "mt-0.5 size-4 shrink-0 rounded-full border border-black/10",
|
|
19395
|
+
style: { backgroundColor: swatch }
|
|
19396
|
+
}
|
|
19397
|
+
) : null,
|
|
19398
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1", children: [
|
|
19399
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: label }),
|
|
19400
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs/5 text-muted-foreground", children: description }) : null
|
|
19401
|
+
] })
|
|
19402
|
+
] })
|
|
19403
|
+
}
|
|
19404
|
+
);
|
|
19405
|
+
}
|
|
19406
|
+
function BackgroundSwatchButton2({
|
|
19407
|
+
background,
|
|
19408
|
+
hasPairs,
|
|
19409
|
+
isSelected,
|
|
19410
|
+
onClick
|
|
19411
|
+
}) {
|
|
19412
|
+
const status = getAvailabilityMeta2(isSelected, hasPairs);
|
|
19413
|
+
const StatusIcon = status.icon;
|
|
19414
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19415
|
+
"button",
|
|
19416
|
+
{
|
|
19417
|
+
type: "button",
|
|
19418
|
+
"aria-pressed": isSelected,
|
|
19419
|
+
"aria-label": `Select ${background.token} background. ${status.description}`,
|
|
19420
|
+
onClick,
|
|
19421
|
+
className: cn(
|
|
19422
|
+
"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",
|
|
19423
|
+
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"
|
|
19424
|
+
),
|
|
19425
|
+
children: [
|
|
19426
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
19427
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
19428
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: getBackgroundOptionName2(background) }),
|
|
19429
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-[0.72rem] break-all text-muted-foreground", children: background.token })
|
|
19430
|
+
] }),
|
|
19431
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
19432
|
+
"span",
|
|
19433
|
+
{
|
|
19434
|
+
className: cn(
|
|
19435
|
+
"inline-flex items-center gap-1 rounded-sm border px-2 py-1 text-[0.68rem] font-semibold uppercase",
|
|
19436
|
+
status.tone === "selected" && "border-primary-800 bg-primary-800 text-white dark:border-primary-500 dark:bg-primary-500",
|
|
19437
|
+
status.tone === "available" && "border-grey-300 bg-grey-50 text-foreground",
|
|
19438
|
+
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"
|
|
19439
|
+
),
|
|
19440
|
+
children: [
|
|
19441
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { "data-slot": "icon", className: "size-4" }),
|
|
19442
|
+
status.label
|
|
19443
|
+
]
|
|
19444
|
+
}
|
|
19445
|
+
)
|
|
19446
|
+
] }),
|
|
19447
|
+
/* @__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 } }) }),
|
|
19448
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-xs/5 text-muted-foreground", children: status.description })
|
|
19449
|
+
]
|
|
19450
|
+
}
|
|
19451
|
+
);
|
|
19452
|
+
}
|
|
19453
|
+
function CompactAccessibilityStatus({ label, passes }) {
|
|
19454
|
+
const status = passes === null ? "unavailable" : passes ? "pass" : "fail";
|
|
19455
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19456
|
+
"div",
|
|
19457
|
+
{
|
|
19458
|
+
className: cn(
|
|
19459
|
+
"flex items-center justify-between gap-3 rounded-sm border px-4 py-3",
|
|
19460
|
+
status === "pass" && "border-success-200 bg-success-50",
|
|
19461
|
+
status === "fail" && "border-danger-200 bg-danger-50",
|
|
19462
|
+
status === "unavailable" && "border-grey-200 bg-white"
|
|
19463
|
+
),
|
|
19464
|
+
children: [
|
|
19465
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: label }),
|
|
19466
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
19467
|
+
"span",
|
|
19468
|
+
{
|
|
19469
|
+
className: cn(
|
|
19470
|
+
"inline-flex items-center gap-1 rounded-sm px-2.5 py-1 text-[0.72rem] font-semibold tracking-[0.12em] uppercase",
|
|
19471
|
+
status === "pass" && "bg-success-700 text-white",
|
|
19472
|
+
status === "fail" && "bg-danger-700 text-white",
|
|
19473
|
+
status === "unavailable" && "bg-grey-100 text-foreground"
|
|
19474
|
+
),
|
|
19475
|
+
children: [
|
|
19476
|
+
status === "pass" ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-4" }) : status === "fail" ? /* @__PURE__ */ jsxRuntime.jsx(Icons.close, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.info, { "data-slot": "icon", className: "size-4" }),
|
|
19477
|
+
status === "pass" ? "Pass" : status === "fail" ? "Fail" : "Unavailable"
|
|
19478
|
+
]
|
|
19479
|
+
}
|
|
19480
|
+
)
|
|
19481
|
+
]
|
|
19482
|
+
}
|
|
19483
|
+
);
|
|
19484
|
+
}
|
|
19485
|
+
function AccessibilitySummaryCard({ pair }) {
|
|
19486
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "gap-4 px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5 lg:flex-row lg:items-start lg:justify-between", children: [
|
|
19487
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
19488
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 6, className: "text-foreground", trim: "normal", children: "Accessibility summary" }),
|
|
19489
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
19490
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-grey-700", children: "Contrast ratio" }),
|
|
19491
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-4xl leading-none font-bold text-foreground", children: pair ? `${pair.contrastRatio.toFixed(2)}:1` : "N/A" })
|
|
19492
|
+
] })
|
|
19493
|
+
] }),
|
|
19494
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-3 lg:max-w-[26rem] lg:min-w-[22rem]", children: [
|
|
19495
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19496
|
+
CompactAccessibilityStatus,
|
|
19497
|
+
{
|
|
19498
|
+
label: "AAA normal text",
|
|
19499
|
+
passes: pair ? pair.passes.aaaText : null
|
|
19500
|
+
}
|
|
19501
|
+
),
|
|
19502
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19503
|
+
CompactAccessibilityStatus,
|
|
19504
|
+
{
|
|
19505
|
+
label: "AAA large text",
|
|
19506
|
+
passes: pair ? pair.passes.aaaLarge : null
|
|
19507
|
+
}
|
|
19508
|
+
)
|
|
19509
|
+
] })
|
|
19510
|
+
] }) });
|
|
19511
|
+
}
|
|
19512
|
+
function CurrentResultCard2({
|
|
19513
|
+
bestPair,
|
|
19514
|
+
copiedKey,
|
|
19515
|
+
onCopyPairing,
|
|
19516
|
+
pair,
|
|
19517
|
+
supportText,
|
|
19518
|
+
selectedBackground
|
|
19519
|
+
}) {
|
|
19520
|
+
const previewForeground = pair?.foreground.hex ?? getReadableTextColor3(selectedBackground.tone);
|
|
19521
|
+
const isRecommended = pair ? pair.id === bestPair?.id : false;
|
|
19522
|
+
const whiteForeground = pair ? isWhiteForegroundPair4(pair) : false;
|
|
19523
|
+
const pairingLabel = getMainPairingLabel(pair, bestPair);
|
|
19524
|
+
const fauxButtonStyle = pair ? {
|
|
19525
|
+
"--btn-bg": pair.foreground.hex,
|
|
19526
|
+
"--btn-border": pair.foreground.hex,
|
|
19527
|
+
"--btn-text": pair.background.hex,
|
|
19528
|
+
"--btn-icon": pair.background.hex,
|
|
19529
|
+
"--btn-hover-overlay": pair.background.hex
|
|
19530
|
+
} : null;
|
|
19531
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: cn("gap-0 overflow-hidden py-0", isRecommended && "border-primary-200"), children: [
|
|
19532
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-grey-200 px-4 py-4 sm:px-6 sm:py-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between", children: [
|
|
19533
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-3", children: [
|
|
19534
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
19535
|
+
"span",
|
|
19536
|
+
{
|
|
19537
|
+
className: cn(
|
|
19538
|
+
"inline-flex items-center gap-2 rounded-sm px-3 py-1 text-[0.72rem] font-semibold tracking-[0.12em] uppercase",
|
|
19539
|
+
isRecommended ? "bg-primary-800 text-white" : "border border-grey-300 bg-grey-50 text-foreground"
|
|
19540
|
+
),
|
|
19541
|
+
children: [
|
|
19542
|
+
isRecommended ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.info, { "data-slot": "icon", className: "size-4" }),
|
|
19543
|
+
pairingLabel
|
|
19544
|
+
]
|
|
19545
|
+
}
|
|
19546
|
+
),
|
|
19547
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
19548
|
+
/* @__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` }),
|
|
19549
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "max-w-3xl text-grey-700", children: supportText })
|
|
19550
|
+
] })
|
|
19551
|
+
] }),
|
|
19552
|
+
pair ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19553
|
+
Button2,
|
|
19554
|
+
{
|
|
19555
|
+
color: "primary",
|
|
19556
|
+
className: "w-full justify-center lg:w-auto lg:min-w-48",
|
|
19557
|
+
onClick: onCopyPairing,
|
|
19558
|
+
children: copiedKey === "current-pairing" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19559
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" }),
|
|
19560
|
+
"Pairing copied"
|
|
19561
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19562
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
|
|
19563
|
+
"Copy pairing"
|
|
19564
|
+
] })
|
|
19565
|
+
}
|
|
19566
|
+
) : null
|
|
19567
|
+
] }) }),
|
|
19568
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19569
|
+
"div",
|
|
19570
|
+
{
|
|
19571
|
+
className: "p-4 sm:min-h-[26rem] sm:p-8",
|
|
19572
|
+
style: {
|
|
19573
|
+
backgroundColor: selectedBackground.hex,
|
|
19574
|
+
color: previewForeground
|
|
19575
|
+
},
|
|
19576
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[18rem] flex-col justify-center gap-6 sm:min-h-[22rem]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-xl space-y-4", children: [
|
|
19577
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold tracking-[0.22em] uppercase", children: pair ? whiteForeground && !isRecommended ? "White on colour example" : whiteForeground ? "White on colour" : "Colour on colour" : "Approved background" }),
|
|
19578
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
19579
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "max-w-lg text-3xl leading-tight font-bold text-current sm:text-5xl sm:leading-none", children: "Pair colour with confidence." }),
|
|
19580
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-full text-base/6 sm:max-w-md sm:text-base/7", children: pair ? getPreviewGuidance4(pair, isRecommended) : "This approved background tone does not currently have a recommended AAA foreground in this tool. Choose another approved background tone to continue." }),
|
|
19581
|
+
pair && fauxButtonStyle ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19582
|
+
"span",
|
|
19583
|
+
{
|
|
19584
|
+
"aria-hidden": "true",
|
|
19585
|
+
"data-variant": "solid",
|
|
19586
|
+
className: cn(
|
|
19587
|
+
buttonVariants({ variant: "solid", size: "default" }),
|
|
19588
|
+
"pointer-events-none cursor-default px-6 text-[16px] font-[700] select-none sm:px-6 sm:text-[16px] sm:font-[700]"
|
|
19589
|
+
),
|
|
19590
|
+
style: fauxButtonStyle,
|
|
19591
|
+
children: "Get started"
|
|
19592
|
+
}
|
|
19593
|
+
) : null
|
|
19594
|
+
] })
|
|
19595
|
+
] }) })
|
|
19596
|
+
}
|
|
19597
|
+
)
|
|
19598
|
+
] });
|
|
19599
|
+
}
|
|
19600
|
+
function RecommendationCard2({
|
|
19601
|
+
copiedKey,
|
|
19602
|
+
isSelected,
|
|
19603
|
+
item,
|
|
19604
|
+
onCopyPairing,
|
|
19605
|
+
onSelect
|
|
19606
|
+
}) {
|
|
19607
|
+
const { pair } = item;
|
|
19608
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19609
|
+
"div",
|
|
19610
|
+
{
|
|
19611
|
+
className: cn(
|
|
19612
|
+
"relative rounded-sm border bg-white p-4 text-left transition-colors focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
|
|
19613
|
+
isSelected ? "border-primary-800 bg-primary-50/60 ring-1 ring-primary-700" : "border-grey-200 hover:border-primary-500 hover:bg-grey-50"
|
|
19614
|
+
),
|
|
19615
|
+
children: [
|
|
19616
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19617
|
+
"button",
|
|
19618
|
+
{
|
|
19619
|
+
type: "button",
|
|
19620
|
+
"aria-pressed": isSelected,
|
|
19621
|
+
"aria-label": `Use ${pair.foreground.token} on ${pair.background.token}`,
|
|
19622
|
+
onClick: onSelect,
|
|
19623
|
+
className: "absolute inset-0 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden"
|
|
19624
|
+
}
|
|
19625
|
+
),
|
|
19626
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none relative z-10", children: [
|
|
19627
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
19628
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
19629
|
+
"span",
|
|
19630
|
+
{
|
|
19631
|
+
className: cn(
|
|
19632
|
+
"inline-flex items-center gap-2 rounded-sm px-2.5 py-1 text-[0.68rem] font-semibold tracking-[0.12em] uppercase",
|
|
19633
|
+
item.category === "best" ? "bg-primary-800 text-white" : "border border-grey-300 bg-grey-50 text-foreground"
|
|
19634
|
+
),
|
|
19635
|
+
children: [
|
|
19636
|
+
item.category === "best" ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.info, { "data-slot": "icon", className: "size-4" }),
|
|
19637
|
+
item.categoryLabel
|
|
19638
|
+
]
|
|
19639
|
+
}
|
|
19640
|
+
),
|
|
19641
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto shrink-0 self-start", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19642
|
+
Button2,
|
|
19643
|
+
{
|
|
19644
|
+
variant: "ghost",
|
|
19645
|
+
color: "grey",
|
|
19646
|
+
size: "sm",
|
|
19647
|
+
onClick: onCopyPairing,
|
|
19648
|
+
"aria-label": `Copy pairing ${pair.background.token} and ${pair.foreground.token}`,
|
|
19649
|
+
children: [
|
|
19650
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
|
|
19651
|
+
copiedKey === `pair:${pair.id}` ? "Copied" : "Copy"
|
|
19652
|
+
]
|
|
19653
|
+
}
|
|
19654
|
+
) })
|
|
19655
|
+
] }),
|
|
19656
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4", children: [
|
|
19657
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 sm:grid-cols-[7.5rem_minmax(0,1fr)]", children: [
|
|
19658
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-[2px] border border-black/10", children: [
|
|
19659
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-20 w-full", style: { backgroundColor: pair.background.hex } }),
|
|
19660
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 w-full", style: { backgroundColor: pair.foreground.hex } })
|
|
19661
|
+
] }),
|
|
19662
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-2", children: [
|
|
19663
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
19664
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-semibold text-foreground", children: getPairingColorDisplayName4(pair.foreground) }),
|
|
19665
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-[0.74rem] break-all text-muted-foreground", children: pair.foreground.token })
|
|
19666
|
+
] }),
|
|
19667
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
19668
|
+
pair.foreground.familyLabel,
|
|
19669
|
+
" on ",
|
|
19670
|
+
pair.background.familyLabel
|
|
19671
|
+
] })
|
|
19672
|
+
] })
|
|
19673
|
+
] }),
|
|
19674
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex flex-col items-start gap-3 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between", children: [
|
|
19675
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
19676
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex rounded-sm border border-grey-300 px-2.5 py-1 text-sm font-semibold text-foreground", children: [
|
|
19677
|
+
pair.contrastRatio.toFixed(2),
|
|
19678
|
+
":1"
|
|
19679
|
+
] }),
|
|
19680
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex rounded-sm bg-success-700 px-2.5 py-1 text-[0.72rem] font-semibold tracking-[0.12em] text-white uppercase", children: "AAA" })
|
|
19681
|
+
] }),
|
|
19682
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-primary-800", children: isSelected ? "Selected answer" : "Use pairing" })
|
|
19683
|
+
] })
|
|
19684
|
+
] })
|
|
19685
|
+
] })
|
|
19686
|
+
]
|
|
19687
|
+
}
|
|
19688
|
+
);
|
|
19689
|
+
}
|
|
19690
|
+
function RecommendationGroupSection({
|
|
19691
|
+
children,
|
|
19692
|
+
description,
|
|
19693
|
+
title
|
|
19694
|
+
}) {
|
|
19695
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
19696
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
19697
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: title }),
|
|
19698
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: description })
|
|
19699
|
+
] }),
|
|
19700
|
+
children
|
|
19701
|
+
] });
|
|
19702
|
+
}
|
|
19703
|
+
function DrawerSummaryItem({ label, value }) {
|
|
19704
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 border-t border-grey-200 pt-3 first:border-t-0 first:pt-0", children: [
|
|
19705
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: label }),
|
|
19706
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: value })
|
|
19707
|
+
] });
|
|
19708
|
+
}
|
|
19709
|
+
function TechnicalDetailsPanel2({
|
|
19710
|
+
color: color2,
|
|
19711
|
+
copiedKey,
|
|
19712
|
+
onCopyValue,
|
|
19713
|
+
title,
|
|
19714
|
+
visibleFormats
|
|
19715
|
+
}) {
|
|
19716
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white", children: [
|
|
19717
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-grey-200 px-4 py-4 sm:px-5", children: [
|
|
19718
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: title }),
|
|
19719
|
+
color2 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19720
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: getPairingColorDisplayName4(color2) }),
|
|
19721
|
+
/* @__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 } }) })
|
|
19722
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "No AAA foreground available." })
|
|
19723
|
+
] }),
|
|
19724
|
+
color2 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-grey-200", children: formatValueRows2(color2, visibleFormats).map((row) => {
|
|
19725
|
+
const copyKey = `${title}-${row.key}`;
|
|
19726
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19727
|
+
"div",
|
|
19728
|
+
{
|
|
19729
|
+
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",
|
|
19730
|
+
children: [
|
|
19731
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
19732
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: row.label }),
|
|
19733
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19734
|
+
"p",
|
|
19735
|
+
{
|
|
19736
|
+
className: cn(
|
|
19737
|
+
"mt-2 text-sm text-foreground",
|
|
19738
|
+
row.key !== "tone" && "font-mono break-all"
|
|
19739
|
+
),
|
|
19740
|
+
children: row.value
|
|
19741
|
+
}
|
|
19742
|
+
)
|
|
19743
|
+
] }),
|
|
19744
|
+
row.copyable ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
19745
|
+
Button2,
|
|
19746
|
+
{
|
|
19747
|
+
variant: "ghost",
|
|
19748
|
+
color: "grey",
|
|
19749
|
+
size: "sm",
|
|
19750
|
+
className: "self-start",
|
|
19751
|
+
onClick: () => onCopyValue(copyKey, row.value, `${row.label} copied`),
|
|
19752
|
+
"aria-label": `Copy ${title.toLowerCase()} ${row.label.toLowerCase()}`,
|
|
19753
|
+
children: copiedKey === copyKey ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19754
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-5" }),
|
|
19755
|
+
"Copied"
|
|
19756
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19757
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
|
|
19758
|
+
"Copy"
|
|
19759
|
+
] })
|
|
19760
|
+
}
|
|
19761
|
+
) : null
|
|
19762
|
+
]
|
|
19763
|
+
},
|
|
19764
|
+
row.key
|
|
19765
|
+
);
|
|
19766
|
+
}) }) : /* @__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." }) })
|
|
19767
|
+
] });
|
|
19768
|
+
}
|
|
19769
|
+
function resolveSelectionState2(nextThemeCategory, nextPrimaryKey, nextAccentKey, preferredBackgroundToken, preferredPairId) {
|
|
19770
|
+
const context = getPairingContext(nextThemeCategory, nextPrimaryKey, nextAccentKey);
|
|
19771
|
+
const selectedBackgroundToken = resolveBackgroundToken4(
|
|
19772
|
+
context,
|
|
19773
|
+
preferredBackgroundToken,
|
|
19774
|
+
getToneFromToken4(preferredBackgroundToken)
|
|
19775
|
+
);
|
|
19776
|
+
const selectedPairId = getPreferredPairForBackground4(
|
|
19777
|
+
context.pairsByBackground[selectedBackgroundToken] ?? [],
|
|
19778
|
+
preferredPairId
|
|
19779
|
+
)?.id ?? "";
|
|
19780
|
+
return {
|
|
19781
|
+
accentKey: context.accent.key,
|
|
19782
|
+
context,
|
|
19783
|
+
primaryKey: context.primary.key,
|
|
19784
|
+
selectedBackgroundToken,
|
|
19785
|
+
selectedPairId,
|
|
19786
|
+
themeCategory: nextThemeCategory
|
|
19787
|
+
};
|
|
19788
|
+
}
|
|
19789
|
+
function ColorPairingToolV4Loading() {
|
|
19790
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 xl:grid-cols-[minmax(18rem,24rem)_minmax(0,1fr)]", children: [
|
|
19791
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
19792
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-52 rounded-sm border border-grey-200 bg-grey-50" }),
|
|
19793
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[32rem] rounded-sm border border-grey-200 bg-grey-50" })
|
|
19794
|
+
] }),
|
|
19795
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
19796
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-96 rounded-sm border border-grey-200 bg-grey-50" }),
|
|
19797
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-64 rounded-sm border border-grey-200 bg-grey-50" }),
|
|
19798
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-72 rounded-sm border border-grey-200 bg-grey-50" })
|
|
19799
|
+
] })
|
|
19800
|
+
] });
|
|
19801
|
+
}
|
|
19802
|
+
function ColorPairingToolV4Content({
|
|
19803
|
+
onAnalyticsEvent,
|
|
19804
|
+
visibleFormats
|
|
19805
|
+
}) {
|
|
19806
|
+
const searchParams = navigation.useSearchParams();
|
|
19807
|
+
const stickyOffset = useStickyOffset(24);
|
|
19808
|
+
const [initialState] = React5.useState(() => getInitialPairingState4(searchParams));
|
|
19809
|
+
const [themeCategory, setThemeCategory] = React5.useState(initialState.themeCategory);
|
|
19810
|
+
const [primaryFamilyKey, setPrimaryFamilyKey] = React5.useState(initialState.primaryKey);
|
|
19811
|
+
const [accentFamilyKey, setAccentFamilyKey] = React5.useState(initialState.accentKey);
|
|
19812
|
+
const [selectedBackgroundToken, setSelectedBackgroundToken] = React5.useState(
|
|
19813
|
+
initialState.selectedBackgroundToken
|
|
19814
|
+
);
|
|
19815
|
+
const [selectedPairId, setSelectedPairId] = React5.useState(initialState.selectedPairId);
|
|
19816
|
+
const [drawerStepIndex, setDrawerStepIndex] = React5.useState(0);
|
|
19817
|
+
const [isCompactControlsOpen, setIsCompactControlsOpen] = React5.useState(false);
|
|
19818
|
+
const [, copyToClipboardRaw] = usehooks.useCopyToClipboard();
|
|
19819
|
+
const [copiedKey, setCopiedKey] = React5.useState(null);
|
|
19820
|
+
const copiedKeyTimeoutRef = React5.useRef(null);
|
|
19821
|
+
const resultSectionRef = React5.useRef(null);
|
|
19822
|
+
const technicalDetailsSectionRef = React5.useRef(null);
|
|
19823
|
+
const noValidStateRef = React5.useRef(/* @__PURE__ */ new Set());
|
|
19824
|
+
const technicalDetailsViewedRef = React5.useRef(false);
|
|
19825
|
+
const emitAnalyticsEvent = React5.useCallback(
|
|
19826
|
+
(event) => {
|
|
19827
|
+
onAnalyticsEvent(event);
|
|
19828
|
+
if (typeof window !== "undefined") {
|
|
19829
|
+
window.dispatchEvent(
|
|
19830
|
+
new CustomEvent(COLOR_PAIRING_TOOL_V4_ANALYTICS_EVENT, {
|
|
19831
|
+
detail: event
|
|
19832
|
+
})
|
|
19833
|
+
);
|
|
19834
|
+
}
|
|
19835
|
+
},
|
|
19836
|
+
[onAnalyticsEvent]
|
|
19837
|
+
);
|
|
19838
|
+
React5.useEffect(() => {
|
|
19839
|
+
return () => {
|
|
19840
|
+
if (copiedKeyTimeoutRef.current) {
|
|
19841
|
+
clearTimeout(copiedKeyTimeoutRef.current);
|
|
19842
|
+
}
|
|
19843
|
+
};
|
|
19844
|
+
}, []);
|
|
19845
|
+
React5.useEffect(() => {
|
|
19846
|
+
if (typeof window === "undefined") {
|
|
19847
|
+
return;
|
|
19848
|
+
}
|
|
19849
|
+
const mediaQuery = window.matchMedia(PERSISTENT_DRAWER_MIN_WIDTH_QUERY2);
|
|
19850
|
+
const handleChange = (event) => {
|
|
19851
|
+
if (event?.matches ?? mediaQuery.matches) {
|
|
19852
|
+
setIsCompactControlsOpen(false);
|
|
19853
|
+
}
|
|
19854
|
+
};
|
|
19855
|
+
handleChange();
|
|
19856
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
19857
|
+
return () => {
|
|
19858
|
+
mediaQuery.removeEventListener("change", handleChange);
|
|
19859
|
+
};
|
|
19860
|
+
}, []);
|
|
19861
|
+
const themeFamilies = React5.useMemo(() => getPairingFamilies(themeCategory), [themeCategory]);
|
|
19862
|
+
const context = React5.useMemo(
|
|
19863
|
+
() => getPairingContext(themeCategory, primaryFamilyKey, accentFamilyKey),
|
|
19864
|
+
[themeCategory, primaryFamilyKey, accentFamilyKey]
|
|
19865
|
+
);
|
|
19866
|
+
const selectableFamilies = React5.useMemo(
|
|
19867
|
+
() => themeFamilies.filter((family) => family.key !== context.grey.key),
|
|
19868
|
+
[themeFamilies, context.grey.key]
|
|
19869
|
+
);
|
|
19870
|
+
const selectableAccentFamilies = React5.useMemo(
|
|
19871
|
+
() => selectableFamilies.filter((family) => family.key !== context.primary.key),
|
|
19872
|
+
[selectableFamilies, context.primary.key]
|
|
19873
|
+
);
|
|
19874
|
+
const selectedBackground = React5.useMemo(
|
|
19875
|
+
() => context.backgrounds.find((background) => background.token === selectedBackgroundToken) ?? context.backgrounds[0] ?? null,
|
|
19876
|
+
[context.backgrounds, selectedBackgroundToken]
|
|
19877
|
+
);
|
|
19878
|
+
const selectedBackgroundPairs = React5.useMemo(
|
|
19879
|
+
() => selectedBackground ? context.pairsByBackground[selectedBackground.token] ?? [] : [],
|
|
19880
|
+
[context.pairsByBackground, selectedBackground]
|
|
19881
|
+
);
|
|
19882
|
+
const bestRecommendedPair = React5.useMemo(
|
|
19883
|
+
() => getPreferredPairForBackground4(selectedBackgroundPairs),
|
|
19884
|
+
[selectedBackgroundPairs]
|
|
19885
|
+
);
|
|
19886
|
+
const selectedPair = React5.useMemo(
|
|
19887
|
+
() => getPreferredPairForBackground4(selectedBackgroundPairs, selectedPairId),
|
|
19888
|
+
[selectedBackgroundPairs, selectedPairId]
|
|
19889
|
+
);
|
|
19890
|
+
const whiteForegroundExample = React5.useMemo(
|
|
19891
|
+
() => selectedBackground && supportsWhiteForegroundPreview(selectedBackground) ? getWhiteForegroundPair(selectedBackground) : null,
|
|
19892
|
+
[selectedBackground]
|
|
19893
|
+
);
|
|
19894
|
+
const previewPair = selectedPair ?? whiteForegroundExample ?? null;
|
|
19895
|
+
const detailForeground = selectedPair?.foreground ?? whiteForegroundExample?.foreground ?? null;
|
|
19896
|
+
const currentPairSupportText = React5.useMemo(
|
|
19897
|
+
() => getMainPairingSupportCopy(previewPair, bestRecommendedPair, context),
|
|
19898
|
+
[bestRecommendedPair, context, previewPair]
|
|
19899
|
+
);
|
|
19900
|
+
const recommendationItems = React5.useMemo(() => {
|
|
19901
|
+
return selectedBackgroundPairs.map((pair) => {
|
|
19902
|
+
const category = getRecommendationCategory2(pair, bestRecommendedPair, context);
|
|
19903
|
+
return {
|
|
19904
|
+
category,
|
|
19905
|
+
categoryLabel: getRecommendationCategoryLabel2(category),
|
|
19906
|
+
pair
|
|
19907
|
+
};
|
|
19908
|
+
}).sort(
|
|
19909
|
+
(left, right) => getRecommendationSortRank2(left.category) - getRecommendationSortRank2(right.category)
|
|
19910
|
+
);
|
|
19911
|
+
}, [bestRecommendedPair, context, selectedBackgroundPairs]);
|
|
19912
|
+
const alternativeRecommendationGroups = React5.useMemo(
|
|
19913
|
+
() => buildRecommendationGroups(
|
|
19914
|
+
recommendationItems.filter((item) => item.pair.id !== selectedPair?.id)
|
|
19915
|
+
),
|
|
19916
|
+
[recommendationItems, selectedPair?.id]
|
|
19917
|
+
);
|
|
19918
|
+
const liveAnnouncement = React5.useMemo(
|
|
19919
|
+
() => getLiveAnnouncement2(previewPair, selectedBackground),
|
|
19920
|
+
[previewPair, selectedBackground]
|
|
19921
|
+
);
|
|
19922
|
+
const shareBackgroundToken = selectedBackground?.token ?? selectedBackgroundToken;
|
|
19923
|
+
const shareUrl = React5.useMemo(() => {
|
|
19924
|
+
const params = new URLSearchParams();
|
|
19925
|
+
params.set("palette", themeCategory);
|
|
19926
|
+
params.set("primary", context.primary.key);
|
|
19927
|
+
params.set("accent", context.accent.key);
|
|
19928
|
+
if (shareBackgroundToken) {
|
|
19929
|
+
params.set("background", shareBackgroundToken);
|
|
19930
|
+
}
|
|
19931
|
+
if (selectedPairId) {
|
|
19932
|
+
params.set("pair", selectedPairId);
|
|
19933
|
+
}
|
|
19934
|
+
const query = params.toString();
|
|
19935
|
+
return `${COLOR_PAIRING_TOOL_V4_PATH}${query ? `?${query}` : ""}`;
|
|
19936
|
+
}, [context.accent.key, context.primary.key, shareBackgroundToken, selectedPairId, themeCategory]);
|
|
19937
|
+
const activeDrawerStep = COLOR_PAIRING_TOOL_DRAWER_STEPS2[drawerStepIndex];
|
|
19938
|
+
const isFirstDrawerStep = drawerStepIndex === 0;
|
|
19939
|
+
const isLastDrawerStep = drawerStepIndex === COLOR_PAIRING_TOOL_DRAWER_STEPS2.length - 1;
|
|
19940
|
+
const desktopSidebarStyle = React5.useMemo(
|
|
19941
|
+
() => ({
|
|
19942
|
+
"--tool-sidebar-max-height": `calc(100vh - ${stickyOffset}px)`,
|
|
19943
|
+
"--tool-sidebar-top": `${stickyOffset}px`
|
|
19944
|
+
}),
|
|
19945
|
+
[stickyOffset]
|
|
19946
|
+
);
|
|
19947
|
+
const goToDrawerStep = React5.useCallback((stepIndex) => {
|
|
19948
|
+
setDrawerStepIndex(Math.max(0, Math.min(stepIndex, COLOR_PAIRING_TOOL_DRAWER_STEPS2.length - 1)));
|
|
19949
|
+
}, []);
|
|
19950
|
+
const goToNextDrawerStep = React5.useCallback(() => {
|
|
19951
|
+
setDrawerStepIndex(
|
|
19952
|
+
(currentStep) => Math.min(currentStep + 1, COLOR_PAIRING_TOOL_DRAWER_STEPS2.length - 1)
|
|
19953
|
+
);
|
|
19954
|
+
}, []);
|
|
19955
|
+
const goToPreviousDrawerStep = React5.useCallback(() => {
|
|
19956
|
+
setDrawerStepIndex((currentStep) => Math.max(currentStep - 1, 0));
|
|
19957
|
+
}, []);
|
|
19958
|
+
const updateUrlParams = React5.useCallback((nextState) => {
|
|
19959
|
+
const params = new URLSearchParams(window.location.search);
|
|
19960
|
+
params.delete("family");
|
|
19961
|
+
params.set("palette", nextState.themeCategory);
|
|
19962
|
+
params.set("primary", nextState.primaryKey);
|
|
19963
|
+
params.set("accent", nextState.accentKey);
|
|
19964
|
+
params.set("background", nextState.selectedBackgroundToken);
|
|
19965
|
+
if (nextState.selectedPairId) {
|
|
19966
|
+
params.set("pair", nextState.selectedPairId);
|
|
19967
|
+
} else {
|
|
19968
|
+
params.delete("pair");
|
|
19969
|
+
}
|
|
19970
|
+
window.history.replaceState(
|
|
19971
|
+
null,
|
|
19972
|
+
"",
|
|
19973
|
+
`${window.location.pathname}?${params.toString()}${window.location.hash}`
|
|
19974
|
+
);
|
|
19975
|
+
}, []);
|
|
19976
|
+
const applyResolvedSelection = React5.useCallback(
|
|
19977
|
+
(nextState) => {
|
|
19978
|
+
setThemeCategory(nextState.themeCategory);
|
|
19979
|
+
setPrimaryFamilyKey(nextState.primaryKey);
|
|
19980
|
+
setAccentFamilyKey(nextState.accentKey);
|
|
19981
|
+
setSelectedBackgroundToken(nextState.selectedBackgroundToken);
|
|
19982
|
+
setSelectedPairId(nextState.selectedPairId);
|
|
19983
|
+
updateUrlParams(nextState);
|
|
19984
|
+
},
|
|
19985
|
+
[updateUrlParams]
|
|
19986
|
+
);
|
|
19987
|
+
const buildAnalyticsContext = React5.useCallback(
|
|
19988
|
+
(overrides) => ({
|
|
19989
|
+
accentKey: context.accent.key,
|
|
19990
|
+
backgroundToken: selectedBackground?.token,
|
|
19991
|
+
foregroundToken: selectedPair?.foreground.token,
|
|
19992
|
+
pairId: selectedPair?.id,
|
|
19993
|
+
palette: themeCategory,
|
|
19994
|
+
primaryKey: context.primary.key,
|
|
19995
|
+
...overrides
|
|
19996
|
+
}),
|
|
19997
|
+
[context.accent.key, context.primary.key, selectedBackground, selectedPair, themeCategory]
|
|
19998
|
+
);
|
|
19999
|
+
const copyValue = React5.useCallback(
|
|
20000
|
+
(copyKey, value, toastLabel, analyticsEvent) => {
|
|
20001
|
+
copyToClipboardRaw(value);
|
|
20002
|
+
setCopiedKey(copyKey);
|
|
20003
|
+
sonner.toast(toastLabel, { duration: 2e3 });
|
|
20004
|
+
if (analyticsEvent) {
|
|
20005
|
+
emitAnalyticsEvent(analyticsEvent);
|
|
20006
|
+
}
|
|
20007
|
+
if (copiedKeyTimeoutRef.current) {
|
|
20008
|
+
clearTimeout(copiedKeyTimeoutRef.current);
|
|
20009
|
+
}
|
|
20010
|
+
copiedKeyTimeoutRef.current = setTimeout(() => {
|
|
20011
|
+
setCopiedKey(null);
|
|
20012
|
+
copiedKeyTimeoutRef.current = null;
|
|
20013
|
+
}, 2e3);
|
|
20014
|
+
},
|
|
20015
|
+
[copyToClipboardRaw, emitAnalyticsEvent]
|
|
20016
|
+
);
|
|
20017
|
+
const handleThemeCategoryChange = (nextThemeCategory) => {
|
|
20018
|
+
const nextState = resolveSelectionState2(
|
|
20019
|
+
nextThemeCategory,
|
|
20020
|
+
primaryFamilyKey,
|
|
20021
|
+
accentFamilyKey,
|
|
20022
|
+
selectedBackgroundToken,
|
|
20023
|
+
null
|
|
20024
|
+
);
|
|
20025
|
+
applyResolvedSelection(nextState);
|
|
20026
|
+
emitAnalyticsEvent({
|
|
20027
|
+
name: "palette_change",
|
|
20028
|
+
accentKey: nextState.accentKey,
|
|
20029
|
+
backgroundToken: nextState.selectedBackgroundToken,
|
|
20030
|
+
pairId: nextState.selectedPairId,
|
|
20031
|
+
palette: nextState.themeCategory,
|
|
20032
|
+
primaryKey: nextState.primaryKey
|
|
20033
|
+
});
|
|
20034
|
+
};
|
|
20035
|
+
const handlePrimaryColorChange = (nextPrimaryKey) => {
|
|
20036
|
+
const nextAccentKey = nextPrimaryKey === accentFamilyKey ? getDefaultAccentFamilyKey(themeCategory, nextPrimaryKey) : accentFamilyKey;
|
|
20037
|
+
const nextState = resolveSelectionState2(
|
|
20038
|
+
themeCategory,
|
|
20039
|
+
nextPrimaryKey,
|
|
20040
|
+
nextAccentKey,
|
|
20041
|
+
selectedBackgroundToken,
|
|
20042
|
+
null
|
|
20043
|
+
);
|
|
20044
|
+
applyResolvedSelection(nextState);
|
|
20045
|
+
emitAnalyticsEvent({
|
|
20046
|
+
name: "primary_change",
|
|
20047
|
+
accentKey: nextState.accentKey,
|
|
20048
|
+
backgroundToken: nextState.selectedBackgroundToken,
|
|
20049
|
+
pairId: nextState.selectedPairId,
|
|
20050
|
+
palette: nextState.themeCategory,
|
|
20051
|
+
primaryKey: nextState.primaryKey
|
|
20052
|
+
});
|
|
20053
|
+
};
|
|
20054
|
+
const handleAccentColorChange = (nextAccentKey) => {
|
|
20055
|
+
if (nextAccentKey === primaryFamilyKey) return;
|
|
20056
|
+
const nextState = resolveSelectionState2(
|
|
20057
|
+
themeCategory,
|
|
20058
|
+
primaryFamilyKey,
|
|
20059
|
+
nextAccentKey,
|
|
20060
|
+
selectedBackgroundToken,
|
|
20061
|
+
null
|
|
20062
|
+
);
|
|
20063
|
+
applyResolvedSelection(nextState);
|
|
20064
|
+
emitAnalyticsEvent({
|
|
20065
|
+
name: "accent_change",
|
|
20066
|
+
accentKey: nextState.accentKey,
|
|
20067
|
+
backgroundToken: nextState.selectedBackgroundToken,
|
|
20068
|
+
pairId: nextState.selectedPairId,
|
|
20069
|
+
palette: nextState.themeCategory,
|
|
20070
|
+
primaryKey: nextState.primaryKey
|
|
20071
|
+
});
|
|
20072
|
+
};
|
|
20073
|
+
const handleBackgroundChange = (nextSelectedBackgroundToken) => {
|
|
20074
|
+
const nextSelectedPairId = getPreferredPairForBackground4(context.pairsByBackground[nextSelectedBackgroundToken] ?? [])?.id ?? "";
|
|
20075
|
+
const nextState = {
|
|
20076
|
+
accentKey: context.accent.key,
|
|
20077
|
+
context,
|
|
20078
|
+
primaryKey: context.primary.key,
|
|
20079
|
+
selectedBackgroundToken: nextSelectedBackgroundToken,
|
|
20080
|
+
selectedPairId: nextSelectedPairId,
|
|
20081
|
+
themeCategory
|
|
20082
|
+
};
|
|
20083
|
+
applyResolvedSelection(nextState);
|
|
20084
|
+
emitAnalyticsEvent({
|
|
20085
|
+
name: "background_selection",
|
|
20086
|
+
...buildAnalyticsContext({
|
|
20087
|
+
backgroundToken: nextSelectedBackgroundToken,
|
|
20088
|
+
foregroundToken: context.pairsByBackground[nextSelectedBackgroundToken]?.find(
|
|
20089
|
+
(pair) => pair.id === nextSelectedPairId
|
|
20090
|
+
)?.foreground.token,
|
|
20091
|
+
pairId: nextSelectedPairId
|
|
20092
|
+
})
|
|
20093
|
+
});
|
|
20094
|
+
if (typeof window !== "undefined" && window.matchMedia(MOBILE_RESULT_SCROLL_QUERY2).matches) {
|
|
20095
|
+
requestAnimationFrame(() => {
|
|
20096
|
+
resultSectionRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
20097
|
+
});
|
|
20098
|
+
}
|
|
20099
|
+
};
|
|
20100
|
+
const handlePairChange = (nextSelectedPairId, source) => {
|
|
20101
|
+
if (!selectedBackground) return;
|
|
20102
|
+
const nextPair = selectedBackgroundPairs.find((pair) => pair.id === nextSelectedPairId) ?? null;
|
|
20103
|
+
setSelectedPairId(nextSelectedPairId);
|
|
20104
|
+
updateUrlParams({
|
|
20105
|
+
accentKey: context.accent.key,
|
|
20106
|
+
context,
|
|
20107
|
+
primaryKey: context.primary.key,
|
|
20108
|
+
selectedBackgroundToken: selectedBackground.token,
|
|
20109
|
+
selectedPairId: nextSelectedPairId,
|
|
20110
|
+
themeCategory
|
|
20111
|
+
});
|
|
20112
|
+
emitAnalyticsEvent({
|
|
20113
|
+
name: "foreground_selection",
|
|
20114
|
+
...buildAnalyticsContext({
|
|
20115
|
+
foregroundToken: nextPair?.foreground.token,
|
|
20116
|
+
pairId: nextSelectedPairId,
|
|
20117
|
+
source
|
|
20118
|
+
})
|
|
20119
|
+
});
|
|
20120
|
+
if (bestRecommendedPair && nextSelectedPairId !== bestRecommendedPair.id) {
|
|
20121
|
+
emitAnalyticsEvent({
|
|
20122
|
+
name: "alternative_combination_selected",
|
|
20123
|
+
...buildAnalyticsContext({
|
|
20124
|
+
foregroundToken: nextPair?.foreground.token,
|
|
20125
|
+
pairId: nextSelectedPairId,
|
|
20126
|
+
source
|
|
20127
|
+
})
|
|
20128
|
+
});
|
|
20129
|
+
}
|
|
20130
|
+
};
|
|
20131
|
+
React5.useEffect(() => {
|
|
20132
|
+
if (!selectedBackground || selectedBackgroundPairs.length > 0) {
|
|
20133
|
+
return;
|
|
20134
|
+
}
|
|
20135
|
+
const key = `${themeCategory}:${context.primary.key}:${context.accent.key}:${selectedBackground.token}`;
|
|
20136
|
+
if (noValidStateRef.current.has(key)) {
|
|
20137
|
+
return;
|
|
20138
|
+
}
|
|
20139
|
+
noValidStateRef.current.add(key);
|
|
18606
20140
|
emitAnalyticsEvent({
|
|
18607
|
-
name: "
|
|
20141
|
+
name: "no_valid_combination_state",
|
|
18608
20142
|
...buildAnalyticsContext({
|
|
18609
|
-
|
|
20143
|
+
backgroundToken: selectedBackground.token
|
|
18610
20144
|
})
|
|
18611
20145
|
});
|
|
20146
|
+
}, [
|
|
20147
|
+
buildAnalyticsContext,
|
|
20148
|
+
context.accent.key,
|
|
20149
|
+
context.primary.key,
|
|
20150
|
+
emitAnalyticsEvent,
|
|
20151
|
+
selectedBackground,
|
|
20152
|
+
selectedBackgroundPairs.length,
|
|
20153
|
+
themeCategory
|
|
20154
|
+
]);
|
|
20155
|
+
React5.useEffect(() => {
|
|
20156
|
+
if (technicalDetailsViewedRef.current) {
|
|
20157
|
+
return;
|
|
20158
|
+
}
|
|
20159
|
+
const section = technicalDetailsSectionRef.current;
|
|
20160
|
+
if (!section) {
|
|
20161
|
+
return;
|
|
20162
|
+
}
|
|
20163
|
+
const emitViewedEvent = () => {
|
|
20164
|
+
if (technicalDetailsViewedRef.current) {
|
|
20165
|
+
return;
|
|
20166
|
+
}
|
|
20167
|
+
technicalDetailsViewedRef.current = true;
|
|
20168
|
+
emitAnalyticsEvent({
|
|
20169
|
+
name: "technical_details_viewed",
|
|
20170
|
+
...buildAnalyticsContext({
|
|
20171
|
+
source: "details"
|
|
20172
|
+
})
|
|
20173
|
+
});
|
|
20174
|
+
};
|
|
20175
|
+
if (typeof IntersectionObserver === "undefined") {
|
|
20176
|
+
const rect = section.getBoundingClientRect();
|
|
20177
|
+
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
20178
|
+
if (rect.top < viewportHeight && rect.bottom > 0) {
|
|
20179
|
+
emitViewedEvent();
|
|
20180
|
+
}
|
|
20181
|
+
return;
|
|
20182
|
+
}
|
|
20183
|
+
const observer = new IntersectionObserver(
|
|
20184
|
+
(entries) => {
|
|
20185
|
+
const [entry] = entries;
|
|
20186
|
+
if (entry?.isIntersecting) {
|
|
20187
|
+
emitViewedEvent();
|
|
20188
|
+
observer.disconnect();
|
|
20189
|
+
}
|
|
20190
|
+
},
|
|
20191
|
+
{
|
|
20192
|
+
threshold: 0.2
|
|
20193
|
+
}
|
|
20194
|
+
);
|
|
20195
|
+
observer.observe(section);
|
|
20196
|
+
return () => {
|
|
20197
|
+
observer.disconnect();
|
|
20198
|
+
};
|
|
18612
20199
|
}, [buildAnalyticsContext, emitAnalyticsEvent]);
|
|
18613
20200
|
if (!selectedBackground) {
|
|
18614
20201
|
return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
|
|
@@ -18616,7 +20203,7 @@ function ColorPairingToolV3Content({
|
|
|
18616
20203
|
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No approved tones are available for the current palette and colour selection." })
|
|
18617
20204
|
] });
|
|
18618
20205
|
}
|
|
18619
|
-
const compactControlsSummary = `${themeCategory === "brand" ? "Brand" : "Aboriginal"} palette, ${context.primary.label} primary, ${context.accent.label} accent, ${
|
|
20206
|
+
const compactControlsSummary = `${themeCategory === "brand" ? "Brand" : "Aboriginal"} palette, ${context.primary.label} primary, ${context.accent.label} accent, ${getPairingColorDisplayName4(
|
|
18620
20207
|
selectedBackground
|
|
18621
20208
|
)} background.`;
|
|
18622
20209
|
const renderControlsPanel = (isOverlay = false) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -18642,7 +20229,7 @@ function ColorPairingToolV3Content({
|
|
|
18642
20229
|
] }) }),
|
|
18643
20230
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-grey-200 px-5 py-4", children: [
|
|
18644
20231
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
18645
|
-
|
|
20232
|
+
COLOR_PAIRING_TOOL_DRAWER_STEPS2.map((step, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
18646
20233
|
"button",
|
|
18647
20234
|
{
|
|
18648
20235
|
type: "button",
|
|
@@ -18682,7 +20269,7 @@ function ColorPairingToolV3Content({
|
|
|
18682
20269
|
const isSelected = themeCategory === palette;
|
|
18683
20270
|
const label = palette === "brand" ? "Brand palette" : "Aboriginal palette";
|
|
18684
20271
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18685
|
-
|
|
20272
|
+
SelectorButton2,
|
|
18686
20273
|
{
|
|
18687
20274
|
label,
|
|
18688
20275
|
isSelected,
|
|
@@ -18695,14 +20282,14 @@ function ColorPairingToolV3Content({
|
|
|
18695
20282
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
18696
20283
|
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Primary colour family" }),
|
|
18697
20284
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableFamilies.map((family) => {
|
|
18698
|
-
const label =
|
|
20285
|
+
const label = getFamilySelectorLabel4(family, themeCategory, "primary colour");
|
|
18699
20286
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18700
|
-
|
|
20287
|
+
SelectorButton2,
|
|
18701
20288
|
{
|
|
18702
20289
|
label,
|
|
18703
20290
|
isSelected: family.key === context.primary.key,
|
|
18704
20291
|
onClick: () => handlePrimaryColorChange(family.key),
|
|
18705
|
-
swatch:
|
|
20292
|
+
swatch: getFamilySwatchColor4(family, 800)
|
|
18706
20293
|
},
|
|
18707
20294
|
family.key
|
|
18708
20295
|
);
|
|
@@ -18711,14 +20298,14 @@ function ColorPairingToolV3Content({
|
|
|
18711
20298
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
18712
20299
|
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Accent colour family" }),
|
|
18713
20300
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableAccentFamilies.map((family) => {
|
|
18714
|
-
const label =
|
|
20301
|
+
const label = getFamilySelectorLabel4(family, themeCategory, "accent colour");
|
|
18715
20302
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18716
|
-
|
|
20303
|
+
SelectorButton2,
|
|
18717
20304
|
{
|
|
18718
20305
|
label,
|
|
18719
20306
|
isSelected: family.key === context.accent.key,
|
|
18720
20307
|
onClick: () => handleAccentColorChange(family.key),
|
|
18721
|
-
swatch:
|
|
20308
|
+
swatch: getFamilySwatchColor4(family, 600)
|
|
18722
20309
|
},
|
|
18723
20310
|
family.key
|
|
18724
20311
|
);
|
|
@@ -18742,7 +20329,7 @@ function ColorPairingToolV3Content({
|
|
|
18742
20329
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: group.label })
|
|
18743
20330
|
] }),
|
|
18744
20331
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3", children: group.backgrounds.map((background) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
18745
|
-
|
|
20332
|
+
BackgroundSwatchButton2,
|
|
18746
20333
|
{
|
|
18747
20334
|
background,
|
|
18748
20335
|
hasPairs: (context.pairsByBackground[background.token]?.length ?? 0) > 0,
|
|
@@ -18755,37 +20342,41 @@ function ColorPairingToolV3Content({
|
|
|
18755
20342
|
},
|
|
18756
20343
|
group.key
|
|
18757
20344
|
)) }) }),
|
|
18758
|
-
/* @__PURE__ */ jsxRuntime.jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsxRuntime.
|
|
18759
|
-
|
|
18760
|
-
|
|
18761
|
-
|
|
18762
|
-
|
|
18763
|
-
|
|
18764
|
-
|
|
18765
|
-
|
|
18766
|
-
|
|
18767
|
-
|
|
18768
|
-
|
|
18769
|
-
|
|
18770
|
-
|
|
18771
|
-
|
|
18772
|
-
|
|
18773
|
-
|
|
18774
|
-
|
|
18775
|
-
|
|
18776
|
-
|
|
18777
|
-
|
|
18778
|
-
|
|
18779
|
-
|
|
18780
|
-
|
|
18781
|
-
|
|
18782
|
-
|
|
18783
|
-
|
|
20345
|
+
/* @__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: [
|
|
20346
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white px-4 py-4", children: [
|
|
20347
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
20348
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "Current configuration" }),
|
|
20349
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "The drawer only sets the palette, families, and background. The result panel is where the pairing is shown and, if needed, overridden." })
|
|
20350
|
+
] }),
|
|
20351
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-5 space-y-3", children: [
|
|
20352
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20353
|
+
DrawerSummaryItem,
|
|
20354
|
+
{
|
|
20355
|
+
label: "Palette",
|
|
20356
|
+
value: themeCategory === "brand" ? "Brand palette" : "Aboriginal palette"
|
|
20357
|
+
}
|
|
20358
|
+
),
|
|
20359
|
+
/* @__PURE__ */ jsxRuntime.jsx(DrawerSummaryItem, { label: "Primary family", value: context.primary.label }),
|
|
20360
|
+
/* @__PURE__ */ jsxRuntime.jsx(DrawerSummaryItem, { label: "Accent family", value: context.accent.label }),
|
|
20361
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20362
|
+
DrawerSummaryItem,
|
|
20363
|
+
{
|
|
20364
|
+
label: "Background",
|
|
20365
|
+
value: getPairingColorDisplayName4(selectedBackground)
|
|
20366
|
+
}
|
|
20367
|
+
)
|
|
20368
|
+
] })
|
|
20369
|
+
] }),
|
|
20370
|
+
/* @__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: [
|
|
20371
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "Review the result on the right" }),
|
|
20372
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "The right panel always shows the current NSW default pairing for this selection. Alternative AAA options stay there as a secondary override path." })
|
|
20373
|
+
] }) })
|
|
20374
|
+
] }) })
|
|
18784
20375
|
]
|
|
18785
20376
|
}
|
|
18786
20377
|
) }),
|
|
18787
20378
|
/* @__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: "
|
|
20379
|
+
/* @__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
20380
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2 sm:w-auto sm:flex-none", children: [
|
|
18790
20381
|
isOverlay && isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
18791
20382
|
Button2,
|
|
@@ -18810,7 +20401,7 @@ function ColorPairingToolV3Content({
|
|
|
18810
20401
|
"data-slot": "tool-sidebar",
|
|
18811
20402
|
className: "hidden xl:sticky xl:top-[var(--tool-sidebar-top)] xl:block xl:self-start",
|
|
18812
20403
|
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() })
|
|
20404
|
+
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
20405
|
}
|
|
18815
20406
|
),
|
|
18816
20407
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "tool-results", className: "space-y-6", children: [
|
|
@@ -18818,7 +20409,7 @@ function ColorPairingToolV3Content({
|
|
|
18818
20409
|
/* @__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
20410
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
18820
20411
|
/* @__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
|
|
20412
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Open the drawer to change palette, colour families, or background. The result panel always shows the current NSW pairing for this selection." }),
|
|
18822
20413
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: compactControlsSummary })
|
|
18823
20414
|
] }),
|
|
18824
20415
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -18850,49 +20441,78 @@ function ColorPairingToolV3Content({
|
|
|
18850
20441
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { ref: resultSectionRef, className: "space-y-6", "aria-label": "Current result", children: [
|
|
18851
20442
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sr-only", "aria-live": "polite", children: liveAnnouncement }),
|
|
18852
20443
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18853
|
-
|
|
20444
|
+
CurrentResultCard2,
|
|
18854
20445
|
{
|
|
18855
20446
|
bestPair: bestRecommendedPair,
|
|
18856
|
-
|
|
20447
|
+
copiedKey,
|
|
20448
|
+
onCopyPairing: () => previewPair ? copyValue(
|
|
20449
|
+
"current-pairing",
|
|
20450
|
+
getPairingCopyText2(previewPair),
|
|
20451
|
+
"Pairing copied",
|
|
20452
|
+
previewPair.id === bestRecommendedPair?.id ? {
|
|
20453
|
+
name: "best_recommendation_copied",
|
|
20454
|
+
...buildAnalyticsContext({
|
|
20455
|
+
foregroundToken: previewPair.foreground.token,
|
|
20456
|
+
pairId: previewPair.id,
|
|
20457
|
+
source: "current-result"
|
|
20458
|
+
})
|
|
20459
|
+
} : void 0
|
|
20460
|
+
) : void 0,
|
|
18857
20461
|
pair: previewPair,
|
|
20462
|
+
supportText: currentPairSupportText,
|
|
18858
20463
|
selectedBackground
|
|
18859
20464
|
}
|
|
18860
20465
|
)
|
|
18861
20466
|
] }),
|
|
18862
|
-
|
|
18863
|
-
|
|
18864
|
-
{
|
|
18865
|
-
copiedKey,
|
|
18866
|
-
isCurrentSelection: selectedPair?.id === bestRecommendedPair.id,
|
|
18867
|
-
pair: bestRecommendedPair,
|
|
18868
|
-
reason: getBestRecommendationReason(bestRecommendedPair, context),
|
|
18869
|
-
onCopyPairing: () => copyValue(
|
|
18870
|
-
"best-pairing",
|
|
18871
|
-
getPairingCopyText(bestRecommendedPair),
|
|
18872
|
-
"Pairing copied",
|
|
18873
|
-
{
|
|
18874
|
-
name: "best_recommendation_copied",
|
|
18875
|
-
...buildAnalyticsContext({
|
|
18876
|
-
foregroundToken: bestRecommendedPair.foreground.token,
|
|
18877
|
-
pairId: bestRecommendedPair.id,
|
|
18878
|
-
source: "best-recommendation"
|
|
18879
|
-
})
|
|
18880
|
-
}
|
|
18881
|
-
),
|
|
18882
|
-
onUsePairing: () => handlePairChange(bestRecommendedPair.id, "best-recommendation")
|
|
18883
|
-
}
|
|
18884
|
-
) }) : /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
|
|
18885
|
-
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Best recommended pairing" }),
|
|
18886
|
-
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No AAA-compliant foreground options available for this selection." })
|
|
18887
|
-
] }),
|
|
18888
|
-
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
20467
|
+
/* @__PURE__ */ jsxRuntime.jsx("section", { children: /* @__PURE__ */ jsxRuntime.jsx(AccessibilitySummaryCard, { pair: previewPair }) }),
|
|
20468
|
+
bestRecommendedPair || alternativeRecommendationGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-6", children: [
|
|
18889
20469
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
20470
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Alternative AAA options" }),
|
|
20471
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "These approved alternatives can be used when a different tone, stronger emphasis, or a more neutral system treatment is needed." })
|
|
20472
|
+
] }),
|
|
20473
|
+
alternativeRecommendationGroups.length > 0 ? alternativeRecommendationGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
20474
|
+
RecommendationGroupSection,
|
|
20475
|
+
{
|
|
20476
|
+
title: group.title,
|
|
20477
|
+
description: group.description,
|
|
20478
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: group.items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
20479
|
+
RecommendationCard2,
|
|
20480
|
+
{
|
|
20481
|
+
copiedKey,
|
|
20482
|
+
item,
|
|
20483
|
+
isSelected: item.pair.id === selectedPair?.id,
|
|
20484
|
+
onCopyPairing: () => copyValue(
|
|
20485
|
+
`pair:${item.pair.id}`,
|
|
20486
|
+
getPairingCopyText2(item.pair),
|
|
20487
|
+
"Pairing copied",
|
|
20488
|
+
item.pair.id === bestRecommendedPair?.id ? {
|
|
20489
|
+
name: "best_recommendation_copied",
|
|
20490
|
+
...buildAnalyticsContext({
|
|
20491
|
+
foregroundToken: item.pair.foreground.token,
|
|
20492
|
+
pairId: item.pair.id,
|
|
20493
|
+
source: "recommendations-list"
|
|
20494
|
+
})
|
|
20495
|
+
} : void 0
|
|
20496
|
+
),
|
|
20497
|
+
onSelect: () => handlePairChange(item.pair.id, "recommendations-list")
|
|
20498
|
+
},
|
|
20499
|
+
item.pair.id
|
|
20500
|
+
)) })
|
|
20501
|
+
},
|
|
20502
|
+
group.id
|
|
20503
|
+
)) : /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
|
|
20504
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: "No other AAA alternatives" }),
|
|
20505
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "The NSW recommended pairing is the only AAA-compliant foreground option for this background." })
|
|
20506
|
+
] })
|
|
20507
|
+
] }) : null,
|
|
20508
|
+
/* @__PURE__ */ jsxRuntime.jsx("section", { ref: technicalDetailsSectionRef, className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white", children: [
|
|
20509
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 border-b border-grey-200 px-4 py-4 sm:px-5", children: [
|
|
18890
20510
|
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Technical colour values" }),
|
|
18891
20511
|
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Token, tone, HEX, RGB, HSL, and OKLCH values for the current selection." })
|
|
18892
20512
|
] }),
|
|
18893
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
|
|
20513
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-4 sm:px-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
|
|
18894
20514
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18895
|
-
|
|
20515
|
+
TechnicalDetailsPanel2,
|
|
18896
20516
|
{
|
|
18897
20517
|
title: "Background values",
|
|
18898
20518
|
color: selectedBackground,
|
|
@@ -18902,7 +20522,7 @@ function ColorPairingToolV3Content({
|
|
|
18902
20522
|
}
|
|
18903
20523
|
),
|
|
18904
20524
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18905
|
-
|
|
20525
|
+
TechnicalDetailsPanel2,
|
|
18906
20526
|
{
|
|
18907
20527
|
title: "Foreground values",
|
|
18908
20528
|
color: detailForeground,
|
|
@@ -18911,51 +20531,51 @@ function ColorPairingToolV3Content({
|
|
|
18911
20531
|
onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
|
|
18912
20532
|
}
|
|
18913
20533
|
)
|
|
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
|
-
] })
|
|
20534
|
+
] }) })
|
|
20535
|
+
] }) }),
|
|
20536
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
20537
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "mb-4 text-foreground", trim: "normal", children: "Share colour pairing" }),
|
|
20538
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white p-4", children: [
|
|
20539
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-row items-center justify-between", children: [
|
|
20540
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Copy this URL to share your current colour pairing:" }),
|
|
20541
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20542
|
+
Button2,
|
|
20543
|
+
{
|
|
20544
|
+
variant: "ghost",
|
|
20545
|
+
color: "grey",
|
|
20546
|
+
size: "sm",
|
|
20547
|
+
className: "shrink-0 self-center",
|
|
20548
|
+
onClick: () => copyValue(
|
|
20549
|
+
"share-url",
|
|
20550
|
+
typeof window === "undefined" ? shareUrl : new URL(shareUrl, window.location.origin).toString(),
|
|
20551
|
+
"Colour pairing link copied"
|
|
20552
|
+
),
|
|
20553
|
+
"aria-label": copiedKey === "share-url" ? "Colour pairing URL copied to clipboard" : "Copy colour pairing URL to clipboard",
|
|
20554
|
+
title: copiedKey === "share-url" ? "Copied" : "Copy URL",
|
|
20555
|
+
children: copiedKey === "share-url" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20556
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" }),
|
|
20557
|
+
"Copied"
|
|
20558
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20559
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
|
|
20560
|
+
"Copy URL"
|
|
20561
|
+
] })
|
|
20562
|
+
}
|
|
20563
|
+
)
|
|
20564
|
+
] }),
|
|
20565
|
+
/* @__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
20566
|
] })
|
|
18947
20567
|
] })
|
|
18948
20568
|
] })
|
|
18949
20569
|
] });
|
|
18950
20570
|
}
|
|
18951
|
-
function
|
|
20571
|
+
function ColorPairingToolV4({
|
|
18952
20572
|
onAnalyticsEvent = () => {
|
|
18953
20573
|
},
|
|
18954
|
-
visibleFormats =
|
|
20574
|
+
visibleFormats = DEFAULT_VISIBLE_FORMATS4
|
|
18955
20575
|
} = {}) {
|
|
18956
20576
|
const normalizedVisibleFormats = [...new Set(visibleFormats)];
|
|
18957
|
-
return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18958
|
-
|
|
20577
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolV4Loading, {}), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20578
|
+
ColorPairingToolV4Content,
|
|
18959
20579
|
{
|
|
18960
20580
|
onAnalyticsEvent,
|
|
18961
20581
|
visibleFormats: normalizedVisibleFormats
|
|
@@ -21586,7 +23206,7 @@ function FormatToggle({ format, setFormat }) {
|
|
|
21586
23206
|
|
|
21587
23207
|
// package.json
|
|
21588
23208
|
var package_default = {
|
|
21589
|
-
version: "1.
|
|
23209
|
+
version: "1.104.0"};
|
|
21590
23210
|
function Logo(props) {
|
|
21591
23211
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
21592
23212
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "NSW Government" }),
|
|
@@ -37349,8 +38969,20 @@ function getHeadings(slugify$1 = slugify.slugifyWithCounter()) {
|
|
|
37349
38969
|
});
|
|
37350
38970
|
return result;
|
|
37351
38971
|
}
|
|
38972
|
+
function areHeadingNodesEqual(left, right) {
|
|
38973
|
+
if (left.level !== right.level || left.id !== right.id || left.title !== right.title) {
|
|
38974
|
+
return false;
|
|
38975
|
+
}
|
|
38976
|
+
if (left.children.length !== right.children.length) {
|
|
38977
|
+
return false;
|
|
38978
|
+
}
|
|
38979
|
+
return left.children.every((child, index) => areHeadingNodesEqual(child, right.children[index]));
|
|
38980
|
+
}
|
|
37352
38981
|
function areHeadingTreesEqual(left, right) {
|
|
37353
|
-
|
|
38982
|
+
if (left.length !== right.length) {
|
|
38983
|
+
return false;
|
|
38984
|
+
}
|
|
38985
|
+
return left.every((heading, index) => areHeadingNodesEqual(heading, right[index]));
|
|
37354
38986
|
}
|
|
37355
38987
|
function usePageHeadings(enabled = true) {
|
|
37356
38988
|
const [headings, setHeadings] = React5.useState([]);
|
|
@@ -37557,6 +39189,7 @@ exports.ColorCard = ColorCard;
|
|
|
37557
39189
|
exports.ColorPairingTool = ColorPairingTool;
|
|
37558
39190
|
exports.ColorPairingToolV2 = ColorPairingToolV2;
|
|
37559
39191
|
exports.ColorPairingToolV3 = ColorPairingToolV3;
|
|
39192
|
+
exports.ColorPairingToolV4 = ColorPairingToolV4;
|
|
37560
39193
|
exports.ColorSwatches = ColorSwatches;
|
|
37561
39194
|
exports.ColourScale = ColourScale;
|
|
37562
39195
|
exports.ComboChart = ComboChart;
|