@nswds/app 1.103.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 +306 -0
- package/dist/index.cjs +3624 -379
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -2
- package/dist/index.d.ts +36 -2
- package/dist/index.js +3621 -378
- package/dist/index.js.map +1 -1
- package/dist/styles.css +306 -0
- package/dist/styles.css.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -40,8 +40,8 @@ var LabelPrimitive = require('@radix-ui/react-label');
|
|
|
40
40
|
var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
|
|
41
41
|
var TabsPrimitives = require('@radix-ui/react-tabs');
|
|
42
42
|
var CollapsiblePrimitive = require('@radix-ui/react-collapsible');
|
|
43
|
+
var SheetPrimitive = require('@radix-ui/react-dialog');
|
|
43
44
|
var cmdk = require('cmdk');
|
|
44
|
-
var DialogPrimitive = require('@radix-ui/react-dialog');
|
|
45
45
|
var ContextMenuPrimitive = require('@radix-ui/react-context-menu');
|
|
46
46
|
var reactTable = require('@tanstack/react-table');
|
|
47
47
|
var SeparatorPrimitive = require('@radix-ui/react-separator');
|
|
@@ -110,7 +110,7 @@ var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespace(LabelPrimitive);
|
|
|
110
110
|
var RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(RadioGroupPrimitive);
|
|
111
111
|
var TabsPrimitives__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitives);
|
|
112
112
|
var CollapsiblePrimitive__namespace = /*#__PURE__*/_interopNamespace(CollapsiblePrimitive);
|
|
113
|
-
var
|
|
113
|
+
var SheetPrimitive__namespace = /*#__PURE__*/_interopNamespace(SheetPrimitive);
|
|
114
114
|
var ContextMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(ContextMenuPrimitive);
|
|
115
115
|
var SeparatorPrimitive__namespace = /*#__PURE__*/_interopNamespace(SeparatorPrimitive);
|
|
116
116
|
var ToggleGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(ToggleGroupPrimitive);
|
|
@@ -16914,18 +16914,35 @@ function ColorPairingToolV2Content({ visibleFormats }) {
|
|
|
16914
16914
|
initialState.selectedBackgroundToken
|
|
16915
16915
|
);
|
|
16916
16916
|
const [selectedPairId, setSelectedPairId] = React5.useState(initialState.selectedPairId);
|
|
16917
|
-
const themeFamilies = getPairingFamilies(themeCategory);
|
|
16918
|
-
const context =
|
|
16919
|
-
|
|
16920
|
-
|
|
16921
|
-
|
|
16922
|
-
|
|
16923
|
-
|
|
16924
|
-
|
|
16925
|
-
|
|
16917
|
+
const themeFamilies = React5.useMemo(() => getPairingFamilies(themeCategory), [themeCategory]);
|
|
16918
|
+
const context = React5.useMemo(
|
|
16919
|
+
() => getPairingContext(themeCategory, primaryFamilyKey, accentFamilyKey),
|
|
16920
|
+
[themeCategory, primaryFamilyKey, accentFamilyKey]
|
|
16921
|
+
);
|
|
16922
|
+
const selectableFamilies = React5.useMemo(
|
|
16923
|
+
() => themeFamilies.filter((family) => family.key !== context.grey.key),
|
|
16924
|
+
[themeFamilies, context.grey.key]
|
|
16925
|
+
);
|
|
16926
|
+
const selectableAccentFamilies = React5.useMemo(
|
|
16927
|
+
() => selectableFamilies.filter((family) => family.key !== context.primary.key),
|
|
16928
|
+
[selectableFamilies, context.primary.key]
|
|
16929
|
+
);
|
|
16930
|
+
const selectedBackground = React5.useMemo(
|
|
16931
|
+
() => context.backgrounds.find((background) => background.token === selectedBackgroundToken) ?? context.backgrounds[0] ?? null,
|
|
16932
|
+
[context.backgrounds, selectedBackgroundToken]
|
|
16933
|
+
);
|
|
16934
|
+
const selectedBackgroundPairs = React5.useMemo(
|
|
16935
|
+
() => selectedBackground ? context.pairsByBackground[selectedBackground.token] ?? [] : [],
|
|
16936
|
+
[context.pairsByBackground, selectedBackground]
|
|
16937
|
+
);
|
|
16938
|
+
const selectedPair = React5.useMemo(
|
|
16939
|
+
() => getPreferredPairForBackground2(selectedBackgroundPairs, selectedPairId),
|
|
16940
|
+
[selectedBackgroundPairs, selectedPairId]
|
|
16941
|
+
);
|
|
16926
16942
|
const detailForeground = selectedPair?.foreground ?? null;
|
|
16927
|
-
const familySummary =
|
|
16928
|
-
" + "
|
|
16943
|
+
const familySummary = React5.useMemo(
|
|
16944
|
+
() => [context.primary.label, context.accent.label, context.grey.label].join(" + "),
|
|
16945
|
+
[context.primary.label, context.accent.label, context.grey.label]
|
|
16929
16946
|
);
|
|
16930
16947
|
const updateUrlParams = (nextThemeCategory, nextPrimaryKey, nextAccentKey, nextSelectedBackgroundToken, nextSelectedPairId) => {
|
|
16931
16948
|
const params = new URLSearchParams(window.location.search);
|
|
@@ -16944,289 +16961,3626 @@ function ColorPairingToolV2Content({ visibleFormats }) {
|
|
|
16944
16961
|
"",
|
|
16945
16962
|
`${window.location.pathname}?${params.toString()}${window.location.hash}`
|
|
16946
16963
|
);
|
|
16947
|
-
};
|
|
16948
|
-
const syncSelection = (nextThemeCategory, nextPrimaryKey, nextAccentKey, preferredBackgroundToken, preferredPairId) => {
|
|
16949
|
-
const nextContext = getPairingContext(nextThemeCategory, nextPrimaryKey, nextAccentKey);
|
|
16950
|
-
const nextSelectedBackgroundToken = resolveBackgroundToken2(
|
|
16951
|
-
nextContext,
|
|
16952
|
-
preferredBackgroundToken,
|
|
16953
|
-
getToneFromToken2(preferredBackgroundToken)
|
|
16954
|
-
);
|
|
16955
|
-
const nextSelectedPairId = getPreferredPairForBackground2(
|
|
16956
|
-
nextContext.pairsByBackground[nextSelectedBackgroundToken] ?? [],
|
|
16957
|
-
preferredPairId
|
|
16958
|
-
)?.id ?? "";
|
|
16959
|
-
setThemeCategory(nextThemeCategory);
|
|
16960
|
-
setPrimaryFamilyKey(nextContext.primary.key);
|
|
16961
|
-
setAccentFamilyKey(nextContext.accent.key);
|
|
16962
|
-
setSelectedBackgroundToken(nextSelectedBackgroundToken);
|
|
16963
|
-
setSelectedPairId(nextSelectedPairId);
|
|
16964
|
-
updateUrlParams(
|
|
16965
|
-
nextThemeCategory,
|
|
16966
|
-
nextContext.primary.key,
|
|
16967
|
-
nextContext.accent.key,
|
|
16968
|
-
nextSelectedBackgroundToken,
|
|
16969
|
-
nextSelectedPairId
|
|
16970
|
-
);
|
|
16971
|
-
};
|
|
16964
|
+
};
|
|
16965
|
+
const syncSelection = (nextThemeCategory, nextPrimaryKey, nextAccentKey, preferredBackgroundToken, preferredPairId) => {
|
|
16966
|
+
const nextContext = getPairingContext(nextThemeCategory, nextPrimaryKey, nextAccentKey);
|
|
16967
|
+
const nextSelectedBackgroundToken = resolveBackgroundToken2(
|
|
16968
|
+
nextContext,
|
|
16969
|
+
preferredBackgroundToken,
|
|
16970
|
+
getToneFromToken2(preferredBackgroundToken)
|
|
16971
|
+
);
|
|
16972
|
+
const nextSelectedPairId = getPreferredPairForBackground2(
|
|
16973
|
+
nextContext.pairsByBackground[nextSelectedBackgroundToken] ?? [],
|
|
16974
|
+
preferredPairId
|
|
16975
|
+
)?.id ?? "";
|
|
16976
|
+
setThemeCategory(nextThemeCategory);
|
|
16977
|
+
setPrimaryFamilyKey(nextContext.primary.key);
|
|
16978
|
+
setAccentFamilyKey(nextContext.accent.key);
|
|
16979
|
+
setSelectedBackgroundToken(nextSelectedBackgroundToken);
|
|
16980
|
+
setSelectedPairId(nextSelectedPairId);
|
|
16981
|
+
updateUrlParams(
|
|
16982
|
+
nextThemeCategory,
|
|
16983
|
+
nextContext.primary.key,
|
|
16984
|
+
nextContext.accent.key,
|
|
16985
|
+
nextSelectedBackgroundToken,
|
|
16986
|
+
nextSelectedPairId
|
|
16987
|
+
);
|
|
16988
|
+
};
|
|
16989
|
+
const handleThemeCategoryChange = (nextThemeCategory) => {
|
|
16990
|
+
syncSelection(
|
|
16991
|
+
nextThemeCategory,
|
|
16992
|
+
primaryFamilyKey,
|
|
16993
|
+
accentFamilyKey,
|
|
16994
|
+
selectedBackgroundToken,
|
|
16995
|
+
selectedPairId
|
|
16996
|
+
);
|
|
16997
|
+
};
|
|
16998
|
+
const handlePrimaryColorChange = (nextPrimaryKey) => {
|
|
16999
|
+
const nextAccentKey = nextPrimaryKey === accentFamilyKey ? getDefaultAccentFamilyKey(themeCategory, nextPrimaryKey) : accentFamilyKey;
|
|
17000
|
+
syncSelection(
|
|
17001
|
+
themeCategory,
|
|
17002
|
+
nextPrimaryKey,
|
|
17003
|
+
nextAccentKey,
|
|
17004
|
+
selectedBackgroundToken,
|
|
17005
|
+
selectedPairId
|
|
17006
|
+
);
|
|
17007
|
+
};
|
|
17008
|
+
const handleAccentColorChange = (nextAccentKey) => {
|
|
17009
|
+
if (nextAccentKey === primaryFamilyKey) return;
|
|
17010
|
+
syncSelection(
|
|
17011
|
+
themeCategory,
|
|
17012
|
+
primaryFamilyKey,
|
|
17013
|
+
nextAccentKey,
|
|
17014
|
+
selectedBackgroundToken,
|
|
17015
|
+
selectedPairId
|
|
17016
|
+
);
|
|
17017
|
+
};
|
|
17018
|
+
const handleBackgroundChange = (nextSelectedBackgroundToken) => {
|
|
17019
|
+
const nextSelectedPairId = getPreferredPairForBackground2(
|
|
17020
|
+
context.pairsByBackground[nextSelectedBackgroundToken] ?? [],
|
|
17021
|
+
selectedPairId
|
|
17022
|
+
)?.id ?? "";
|
|
17023
|
+
setSelectedBackgroundToken(nextSelectedBackgroundToken);
|
|
17024
|
+
setSelectedPairId(nextSelectedPairId);
|
|
17025
|
+
updateUrlParams(
|
|
17026
|
+
themeCategory,
|
|
17027
|
+
context.primary.key,
|
|
17028
|
+
context.accent.key,
|
|
17029
|
+
nextSelectedBackgroundToken,
|
|
17030
|
+
nextSelectedPairId
|
|
17031
|
+
);
|
|
17032
|
+
};
|
|
17033
|
+
const handlePairChange = (nextSelectedPairId) => {
|
|
17034
|
+
if (!selectedBackground) return;
|
|
17035
|
+
setSelectedPairId(nextSelectedPairId);
|
|
17036
|
+
updateUrlParams(
|
|
17037
|
+
themeCategory,
|
|
17038
|
+
context.primary.key,
|
|
17039
|
+
context.accent.key,
|
|
17040
|
+
selectedBackground.token,
|
|
17041
|
+
nextSelectedPairId
|
|
17042
|
+
);
|
|
17043
|
+
};
|
|
17044
|
+
if (!selectedBackground) {
|
|
17045
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Card, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6", children: [
|
|
17046
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: "No approved background tones available" }),
|
|
17047
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-base text-muted-foreground", children: "No approved tones are available for the current palette." })
|
|
17048
|
+
] }) });
|
|
17049
|
+
}
|
|
17050
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 lg:grid-cols-[18rem_minmax(0,1fr)]", children: [
|
|
17051
|
+
/* @__PURE__ */ jsxRuntime.jsx("aside", { className: "bg-grey-50/60 p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-8", children: [
|
|
17052
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
17053
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
|
|
17054
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Choose a palette, set your primary and accent families, then select an approved background." })
|
|
17055
|
+
] }),
|
|
17056
|
+
/* @__PURE__ */ jsxRuntime.jsx(SidebarStep, { step: 1, title: "Select your palette", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-2", children: ["brand", "aboriginal"].map((palette) => {
|
|
17057
|
+
const isSelected = themeCategory === palette;
|
|
17058
|
+
const label = palette === "brand" ? "Brand palette" : "Aboriginal palette";
|
|
17059
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17060
|
+
"button",
|
|
17061
|
+
{
|
|
17062
|
+
type: "button",
|
|
17063
|
+
"aria-label": `Select ${label}`,
|
|
17064
|
+
"aria-pressed": isSelected,
|
|
17065
|
+
onClick: () => handleThemeCategoryChange(palette),
|
|
17066
|
+
className: cn(
|
|
17067
|
+
"rounded-sm border px-3 py-2.5 text-left text-sm font-semibold transition-colors",
|
|
17068
|
+
isSelected ? "border-primary-800 bg-primary-800 text-white" : "border-grey-300 bg-background text-foreground hover:border-primary-800 hover:bg-primary-50"
|
|
17069
|
+
),
|
|
17070
|
+
children: label
|
|
17071
|
+
},
|
|
17072
|
+
palette
|
|
17073
|
+
);
|
|
17074
|
+
}) }) }),
|
|
17075
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17076
|
+
SidebarStep,
|
|
17077
|
+
{
|
|
17078
|
+
step: 2,
|
|
17079
|
+
title: "Choose your colours",
|
|
17080
|
+
description: "Grey is added automatically from the selected palette.",
|
|
17081
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
|
|
17082
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
17083
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: "Primary colour" }),
|
|
17084
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-2", children: selectableFamilies.map((family) => {
|
|
17085
|
+
const swatchTone = 800;
|
|
17086
|
+
const isSelected = family.key === context.primary.key;
|
|
17087
|
+
const label = getFamilySelectorLabel2(family, themeCategory, "primary colour");
|
|
17088
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17089
|
+
"button",
|
|
17090
|
+
{
|
|
17091
|
+
type: "button",
|
|
17092
|
+
"aria-label": `Select ${label} as primary colour`,
|
|
17093
|
+
"aria-pressed": isSelected,
|
|
17094
|
+
onClick: () => handlePrimaryColorChange(family.key),
|
|
17095
|
+
className: cn(
|
|
17096
|
+
"min-h-11 rounded-sm border px-2 py-2 text-center text-[0.8rem] leading-5 font-semibold transition-transform",
|
|
17097
|
+
isSelected ? "ring-2 ring-primary-700 ring-offset-2 ring-offset-grey-50/60" : "hover:-translate-y-px"
|
|
17098
|
+
),
|
|
17099
|
+
style: {
|
|
17100
|
+
backgroundColor: getFamilySwatchColor2(family, swatchTone),
|
|
17101
|
+
color: getReadableTextColor(swatchTone),
|
|
17102
|
+
borderColor: "rgba(0, 0, 0, 0.12)"
|
|
17103
|
+
},
|
|
17104
|
+
title: label,
|
|
17105
|
+
children: label
|
|
17106
|
+
},
|
|
17107
|
+
family.key
|
|
17108
|
+
);
|
|
17109
|
+
}) })
|
|
17110
|
+
] }),
|
|
17111
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
17112
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: "Accent colour" }),
|
|
17113
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-2", children: selectableAccentFamilies.map((family) => {
|
|
17114
|
+
const swatchTone = 600;
|
|
17115
|
+
const isSelected = family.key === context.accent.key;
|
|
17116
|
+
const label = getFamilySelectorLabel2(family, themeCategory, "accent colour");
|
|
17117
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17118
|
+
"button",
|
|
17119
|
+
{
|
|
17120
|
+
type: "button",
|
|
17121
|
+
"aria-label": `Select ${label} as accent colour`,
|
|
17122
|
+
"aria-pressed": isSelected,
|
|
17123
|
+
onClick: () => handleAccentColorChange(family.key),
|
|
17124
|
+
className: cn(
|
|
17125
|
+
"min-h-11 rounded-sm border px-2 py-2 text-center text-[0.8rem] leading-5 font-semibold transition-transform",
|
|
17126
|
+
isSelected ? "ring-2 ring-primary-700 ring-offset-2 ring-offset-grey-50/60" : "hover:-translate-y-px"
|
|
17127
|
+
),
|
|
17128
|
+
style: {
|
|
17129
|
+
backgroundColor: getFamilySwatchColor2(family, swatchTone),
|
|
17130
|
+
color: getReadableTextColor(swatchTone),
|
|
17131
|
+
borderColor: "rgba(0, 0, 0, 0.12)"
|
|
17132
|
+
},
|
|
17133
|
+
title: label,
|
|
17134
|
+
children: label
|
|
17135
|
+
},
|
|
17136
|
+
family.key
|
|
17137
|
+
);
|
|
17138
|
+
}) })
|
|
17139
|
+
] })
|
|
17140
|
+
] })
|
|
17141
|
+
}
|
|
17142
|
+
),
|
|
17143
|
+
/* @__PURE__ */ jsxRuntime.jsx(SidebarStep, { step: 3, title: "Pick a background", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
17144
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
17145
|
+
"Selected:",
|
|
17146
|
+
" ",
|
|
17147
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: selectedBackground.token })
|
|
17148
|
+
] }),
|
|
17149
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-4 gap-2", children: context.backgrounds.map((background) => {
|
|
17150
|
+
const hasPairs = (context.pairsByBackground[background.token]?.length ?? 0) > 0;
|
|
17151
|
+
const isSelected = selectedBackground.token === background.token;
|
|
17152
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17153
|
+
"button",
|
|
17154
|
+
{
|
|
17155
|
+
type: "button",
|
|
17156
|
+
"aria-label": hasPairs ? `Select ${background.token} background` : `Select ${background.token} background with no AAA pairings`,
|
|
17157
|
+
"aria-pressed": isSelected,
|
|
17158
|
+
onClick: () => handleBackgroundChange(background.token),
|
|
17159
|
+
className: cn(
|
|
17160
|
+
"relative aspect-square rounded-sm border transition-transform",
|
|
17161
|
+
isSelected ? "ring-2 ring-primary-700 ring-offset-2 ring-offset-grey-50/60" : "hover:-translate-y-px",
|
|
17162
|
+
!hasPairs && "opacity-80"
|
|
17163
|
+
),
|
|
17164
|
+
style: {
|
|
17165
|
+
backgroundColor: background.hex,
|
|
17166
|
+
borderColor: "rgba(0, 0, 0, 0.14)"
|
|
17167
|
+
},
|
|
17168
|
+
title: background.token,
|
|
17169
|
+
children: !hasPairs ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-1/2 left-1/2 h-0.5 w-5 -translate-x-1/2 -translate-y-1/2 rotate-45 rounded-full bg-white shadow-[0_0_0_1px_rgba(0,0,0,0.28)]" }) : null
|
|
17170
|
+
},
|
|
17171
|
+
background.token
|
|
17172
|
+
);
|
|
17173
|
+
}) })
|
|
17174
|
+
] }) })
|
|
17175
|
+
] }) }),
|
|
17176
|
+
/* @__PURE__ */ jsxRuntime.jsxs("main", { className: "space-y-8", children: [
|
|
17177
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
17178
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: "Live Preview & Results" }),
|
|
17179
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Review the selected pairing in context, then compare the available AAA combinations for your chosen background." })
|
|
17180
|
+
] }),
|
|
17181
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
|
|
17182
|
+
selectedPair ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
17183
|
+
PreviewHeroCard,
|
|
17184
|
+
{
|
|
17185
|
+
familySummary,
|
|
17186
|
+
isRecommended: Boolean(selectedPair),
|
|
17187
|
+
pair: selectedPair
|
|
17188
|
+
}
|
|
17189
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(PreviewFallbackCard2, { background: selectedBackground }),
|
|
17190
|
+
/* @__PURE__ */ jsxRuntime.jsx(AccessibilityScoreCard, { pair: selectedPair })
|
|
17191
|
+
] }),
|
|
17192
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
17193
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
17194
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: "Recommended Combinations" }),
|
|
17195
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-base text-muted-foreground", children: [
|
|
17196
|
+
"AAA-recommended foregrounds for",
|
|
17197
|
+
" ",
|
|
17198
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: selectedBackground.token }),
|
|
17199
|
+
"."
|
|
17200
|
+
] })
|
|
17201
|
+
] }),
|
|
17202
|
+
selectedBackgroundPairs.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-4 md:grid-cols-2 xl:grid-cols-3", children: selectedBackgroundPairs.map((pair) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
17203
|
+
RecommendedPairCard,
|
|
17204
|
+
{
|
|
17205
|
+
pair,
|
|
17206
|
+
isSelected: selectedPair?.id === pair.id,
|
|
17207
|
+
onSelect: () => handlePairChange(pair.id)
|
|
17208
|
+
},
|
|
17209
|
+
pair.id
|
|
17210
|
+
)) }) : /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "gap-0 py-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-6", children: [
|
|
17211
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "No recommended combinations" }),
|
|
17212
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-base text-muted-foreground", children: "Choose another approved background tone to review available AAA pairings." })
|
|
17213
|
+
] }) })
|
|
17214
|
+
] }),
|
|
17215
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
|
|
17216
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17217
|
+
PairDetailCard2,
|
|
17218
|
+
{
|
|
17219
|
+
color: selectedBackground,
|
|
17220
|
+
role: "Background",
|
|
17221
|
+
visibleFormats
|
|
17222
|
+
}
|
|
17223
|
+
),
|
|
17224
|
+
detailForeground ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
17225
|
+
PairDetailCard2,
|
|
17226
|
+
{
|
|
17227
|
+
color: detailForeground,
|
|
17228
|
+
role: "Foreground",
|
|
17229
|
+
visibleFormats
|
|
17230
|
+
}
|
|
17231
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "gap-4", children: [
|
|
17232
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardHeader, { className: "gap-3 border-b", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
17233
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardTitle, { children: "Foreground" }),
|
|
17234
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: "No recommended foreground available" })
|
|
17235
|
+
] }) }),
|
|
17236
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Choose another approved tone or review the recommended foregrounds for the same background." }) })
|
|
17237
|
+
] })
|
|
17238
|
+
] })
|
|
17239
|
+
] })
|
|
17240
|
+
] });
|
|
17241
|
+
}
|
|
17242
|
+
function ColorPairingToolV2({
|
|
17243
|
+
visibleFormats = DEFAULT_VISIBLE_FORMATS2
|
|
17244
|
+
} = {}) {
|
|
17245
|
+
const normalizedVisibleFormats = [...new Set(visibleFormats)];
|
|
17246
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolV2Loading, {}), children: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolV2Content, { visibleFormats: normalizedVisibleFormats }) });
|
|
17247
|
+
}
|
|
17248
|
+
function Sheet({ ...props }) {
|
|
17249
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Root, { "data-slot": "sheet", ...props });
|
|
17250
|
+
}
|
|
17251
|
+
function SheetTrigger({ ...props }) {
|
|
17252
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Trigger, { "data-slot": "sheet-trigger", ...props });
|
|
17253
|
+
}
|
|
17254
|
+
function SheetClose({ ...props }) {
|
|
17255
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Close, { "data-slot": "sheet-close", ...props });
|
|
17256
|
+
}
|
|
17257
|
+
function SheetPortal({ ...props }) {
|
|
17258
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Portal, { "data-slot": "sheet-portal", ...props });
|
|
17259
|
+
}
|
|
17260
|
+
function SheetOverlay({
|
|
17261
|
+
className,
|
|
17262
|
+
...props
|
|
17263
|
+
}) {
|
|
17264
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17265
|
+
SheetPrimitive__namespace.Overlay,
|
|
17266
|
+
{
|
|
17267
|
+
"data-slot": "sheet-overlay",
|
|
17268
|
+
className: cn(
|
|
17269
|
+
"fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
|
|
17270
|
+
className
|
|
17271
|
+
),
|
|
17272
|
+
...props
|
|
17273
|
+
}
|
|
17274
|
+
);
|
|
17275
|
+
}
|
|
17276
|
+
function SheetContent({
|
|
17277
|
+
className,
|
|
17278
|
+
children,
|
|
17279
|
+
side = "right",
|
|
17280
|
+
showClose = true,
|
|
17281
|
+
...props
|
|
17282
|
+
}) {
|
|
17283
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(SheetPortal, { children: [
|
|
17284
|
+
/* @__PURE__ */ jsxRuntime.jsx(SheetOverlay, {}),
|
|
17285
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17286
|
+
SheetPrimitive__namespace.Content,
|
|
17287
|
+
{
|
|
17288
|
+
"data-slot": "sheet-content",
|
|
17289
|
+
className: cn(
|
|
17290
|
+
"fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=closed]:animate-out data-[state=open]:duration-500 data-[state=open]:animate-in",
|
|
17291
|
+
side === "right" && "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
|
17292
|
+
side === "left" && "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
|
17293
|
+
side === "top" && "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
|
17294
|
+
side === "bottom" && "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
|
17295
|
+
className
|
|
17296
|
+
),
|
|
17297
|
+
...props,
|
|
17298
|
+
children: [
|
|
17299
|
+
children,
|
|
17300
|
+
showClose && /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Close, { "data-slot": "sheet-close", className: "absolute top-4 right-4", asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button2, { variant: "ghost", size: "icon", children: [
|
|
17301
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.close, { className: "size-6", "aria-hidden": "true" }),
|
|
17302
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
|
|
17303
|
+
] }) })
|
|
17304
|
+
]
|
|
17305
|
+
}
|
|
17306
|
+
)
|
|
17307
|
+
] });
|
|
17308
|
+
}
|
|
17309
|
+
function SheetHeader({ className, ...props }) {
|
|
17310
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17311
|
+
"div",
|
|
17312
|
+
{
|
|
17313
|
+
"data-slot": "sheet-header",
|
|
17314
|
+
className: cn("flex flex-col gap-1.5 p-4", className),
|
|
17315
|
+
...props
|
|
17316
|
+
}
|
|
17317
|
+
);
|
|
17318
|
+
}
|
|
17319
|
+
function SheetFooter({ className, ...props }) {
|
|
17320
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17321
|
+
"div",
|
|
17322
|
+
{
|
|
17323
|
+
"data-slot": "sheet-footer",
|
|
17324
|
+
className: cn("mt-auto flex flex-col gap-2 p-4", className),
|
|
17325
|
+
...props
|
|
17326
|
+
}
|
|
17327
|
+
);
|
|
17328
|
+
}
|
|
17329
|
+
function SheetTitle({ className, ...props }) {
|
|
17330
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17331
|
+
SheetPrimitive__namespace.Title,
|
|
17332
|
+
{
|
|
17333
|
+
"data-slot": "sheet-title",
|
|
17334
|
+
className: cn("font-semibold text-foreground", className),
|
|
17335
|
+
...props
|
|
17336
|
+
}
|
|
17337
|
+
);
|
|
17338
|
+
}
|
|
17339
|
+
function SheetDescription({
|
|
17340
|
+
className,
|
|
17341
|
+
...props
|
|
17342
|
+
}) {
|
|
17343
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17344
|
+
SheetPrimitive__namespace.Description,
|
|
17345
|
+
{
|
|
17346
|
+
"data-slot": "sheet-description",
|
|
17347
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
17348
|
+
...props
|
|
17349
|
+
}
|
|
17350
|
+
);
|
|
17351
|
+
}
|
|
17352
|
+
function useSelectorHeight(selector = "header") {
|
|
17353
|
+
const [height, setHeight] = React5.useState(0);
|
|
17354
|
+
const elementRef = React5.useRef(null);
|
|
17355
|
+
const resizeObserverRef = React5.useRef(null);
|
|
17356
|
+
React5.useEffect(() => {
|
|
17357
|
+
const element = document.querySelector(selector);
|
|
17358
|
+
if (!element) return;
|
|
17359
|
+
elementRef.current = element;
|
|
17360
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
17361
|
+
const entry = entries[0];
|
|
17362
|
+
const target = entry?.target ?? elementRef.current;
|
|
17363
|
+
if (!target) return;
|
|
17364
|
+
setHeight(target.offsetHeight);
|
|
17365
|
+
});
|
|
17366
|
+
resizeObserverRef.current = resizeObserver;
|
|
17367
|
+
resizeObserver.observe(element);
|
|
17368
|
+
return () => {
|
|
17369
|
+
resizeObserverRef.current?.disconnect();
|
|
17370
|
+
};
|
|
17371
|
+
}, [selector]);
|
|
17372
|
+
return height;
|
|
17373
|
+
}
|
|
17374
|
+
|
|
17375
|
+
// src/hooks/useStickyOffset.ts
|
|
17376
|
+
function useStickyOffset(extraPadding = 0) {
|
|
17377
|
+
const headerHeight = useSelectorHeight("#nsw-header");
|
|
17378
|
+
const navigationHeight = useSelectorHeight("#nsw-main-navigation");
|
|
17379
|
+
return React5.useMemo(() => {
|
|
17380
|
+
const total = headerHeight + navigationHeight + extraPadding;
|
|
17381
|
+
return total > 0 ? total : 0;
|
|
17382
|
+
}, [extraPadding, headerHeight, navigationHeight]);
|
|
17383
|
+
}
|
|
17384
|
+
var PREFERRED_BACKGROUND_TONES3 = [400, 600, 200, 800, 100, 50];
|
|
17385
|
+
var DEFAULT_VISIBLE_FORMATS3 = ["hex", "rgb", "hsl", "oklch"];
|
|
17386
|
+
var DEFAULT_INITIAL_BACKGROUND_TOKEN3 = "nsw-blue-800";
|
|
17387
|
+
var DEFAULT_INITIAL_PAIR_ID3 = "nsw-blue-800:nsw-blue-200";
|
|
17388
|
+
var COLOR_PAIRING_TOOL_V3_PATH = "/core/colour/colour-pairing-tool-3";
|
|
17389
|
+
var AAA_NORMAL_TEXT_THRESHOLD2 = "7.0:1 for text below the WCAG large-text threshold. Sentence-case body copy should generally stay at 16px+ unless it is microcopy.";
|
|
17390
|
+
var AAA_LARGE_TEXT_THRESHOLD2 = "4.5:1 for WCAG large text: 24px+, or 18.5px+ bold";
|
|
17391
|
+
var MOBILE_RESULT_SCROLL_QUERY = "(max-width: 1023px)";
|
|
17392
|
+
var PERSISTENT_DRAWER_MIN_WIDTH_QUERY = "(min-width: 1280px)";
|
|
17393
|
+
var COLOR_PAIRING_TOOL_DRAWER_STEPS = [
|
|
17394
|
+
{
|
|
17395
|
+
id: "colours",
|
|
17396
|
+
title: "Choose colours",
|
|
17397
|
+
eyebrow: "Step 1 of 3",
|
|
17398
|
+
description: "Select the palette, primary family, and accent family."
|
|
17399
|
+
},
|
|
17400
|
+
{
|
|
17401
|
+
id: "backgrounds",
|
|
17402
|
+
title: "Choose background",
|
|
17403
|
+
eyebrow: "Step 2 of 3",
|
|
17404
|
+
description: "Pick the background tone that you want to pair."
|
|
17405
|
+
},
|
|
17406
|
+
{
|
|
17407
|
+
id: "combinations",
|
|
17408
|
+
title: "Choose recommended combinations",
|
|
17409
|
+
eyebrow: "Step 3 of 3",
|
|
17410
|
+
description: "Select the foreground pairing that should drive the example."
|
|
17411
|
+
}
|
|
17412
|
+
];
|
|
17413
|
+
var COLOR_PAIRING_TOOL_V3_ANALYTICS_EVENT = "nsw-colour-pairing-tool-v3";
|
|
17414
|
+
function getToneFromToken3(token) {
|
|
17415
|
+
if (!token) return null;
|
|
17416
|
+
const match = token.match(/-(\d+)$/);
|
|
17417
|
+
return match ? Number.parseInt(match[1], 10) : null;
|
|
17418
|
+
}
|
|
17419
|
+
function getFamilySwatchColor3(family, preferredTone = 600) {
|
|
17420
|
+
const exactMatch = family.colors.find((color2) => color2.tone === preferredTone);
|
|
17421
|
+
if (exactMatch) {
|
|
17422
|
+
return exactMatch.hex;
|
|
17423
|
+
}
|
|
17424
|
+
const closestMatch = [...family.colors].sort(
|
|
17425
|
+
(left, right) => Math.abs(left.tone - preferredTone) - Math.abs(right.tone - preferredTone)
|
|
17426
|
+
)[0];
|
|
17427
|
+
return closestMatch?.hex ?? "transparent";
|
|
17428
|
+
}
|
|
17429
|
+
function getFamilySelectorLabel3(family, themeCategory, selectionRole) {
|
|
17430
|
+
if (themeCategory !== "aboriginal") {
|
|
17431
|
+
return family.label;
|
|
17432
|
+
}
|
|
17433
|
+
const preferredTone = selectionRole === "primary colour" ? 800 : 600;
|
|
17434
|
+
return family.colors.find((color2) => color2.tone === preferredTone)?.name ?? family.label;
|
|
17435
|
+
}
|
|
17436
|
+
function getPairingColorDisplayName3(color2) {
|
|
17437
|
+
return color2.name ?? `${color2.familyLabel} ${color2.tone}`;
|
|
17438
|
+
}
|
|
17439
|
+
function isWhiteForegroundPair3(pair) {
|
|
17440
|
+
return pair.foreground.token === "white";
|
|
17441
|
+
}
|
|
17442
|
+
function isLargeTextOnlyPair(pair) {
|
|
17443
|
+
return pair.passes.aaaLarge && !pair.passes.aaaText;
|
|
17444
|
+
}
|
|
17445
|
+
function getWhiteForegroundGuidance3(pair) {
|
|
17446
|
+
if (pair.passes.aaaText) {
|
|
17447
|
+
return "White is approved for headings, body copy, and calls to action on this background.";
|
|
17448
|
+
}
|
|
17449
|
+
if (pair.passes.aaaLarge) {
|
|
17450
|
+
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.";
|
|
17451
|
+
}
|
|
17452
|
+
return "Do not use white on this background. Choose one of the recommended foregrounds below instead.";
|
|
17453
|
+
}
|
|
17454
|
+
function getPreviewGuidance3(pair, isRecommended) {
|
|
17455
|
+
if (!isWhiteForegroundPair3(pair)) {
|
|
17456
|
+
return "Use only AAA-recommended combinations across your selected primary, accent, and grey families.";
|
|
17457
|
+
}
|
|
17458
|
+
if (isRecommended) {
|
|
17459
|
+
return "Use white text on dark colour only when it meets AAA for headings, body copy, and calls to action.";
|
|
17460
|
+
}
|
|
17461
|
+
return getWhiteForegroundGuidance3(pair);
|
|
17462
|
+
}
|
|
17463
|
+
function getPreferredPairForBackground3(pairs, preferredPairId) {
|
|
17464
|
+
if (preferredPairId) {
|
|
17465
|
+
const preferredPair = pairs.find((pair) => pair.id === preferredPairId);
|
|
17466
|
+
if (preferredPair) {
|
|
17467
|
+
return preferredPair;
|
|
17468
|
+
}
|
|
17469
|
+
}
|
|
17470
|
+
return pairs.find((pair) => !isWhiteForegroundPair3(pair)) ?? pairs[0] ?? null;
|
|
17471
|
+
}
|
|
17472
|
+
function getDefaultBackgroundToken3(context) {
|
|
17473
|
+
for (const tone of PREFERRED_BACKGROUND_TONES3) {
|
|
17474
|
+
for (const group of context.backgroundGroups) {
|
|
17475
|
+
const match = group.backgrounds.find(
|
|
17476
|
+
(background) => background.tone === tone && (context.pairsByBackground[background.token]?.length ?? 0) > 0
|
|
17477
|
+
);
|
|
17478
|
+
if (match) {
|
|
17479
|
+
return match.token;
|
|
17480
|
+
}
|
|
17481
|
+
}
|
|
17482
|
+
}
|
|
17483
|
+
for (const tone of PREFERRED_BACKGROUND_TONES3) {
|
|
17484
|
+
for (const group of context.backgroundGroups) {
|
|
17485
|
+
const match = group.backgrounds.find((background) => background.tone === tone);
|
|
17486
|
+
if (match) {
|
|
17487
|
+
return match.token;
|
|
17488
|
+
}
|
|
17489
|
+
}
|
|
17490
|
+
}
|
|
17491
|
+
return context.backgrounds[0]?.token ?? "";
|
|
17492
|
+
}
|
|
17493
|
+
function resolveBackgroundToken3(context, preferredToken, preferredTone) {
|
|
17494
|
+
if (preferredToken && context.backgrounds.some((background) => background.token === preferredToken)) {
|
|
17495
|
+
return preferredToken;
|
|
17496
|
+
}
|
|
17497
|
+
if (preferredTone !== null && preferredTone !== void 0) {
|
|
17498
|
+
for (const group of context.backgroundGroups) {
|
|
17499
|
+
const match = group.backgrounds.find((background) => background.tone === preferredTone);
|
|
17500
|
+
if (match) {
|
|
17501
|
+
return match.token;
|
|
17502
|
+
}
|
|
17503
|
+
}
|
|
17504
|
+
}
|
|
17505
|
+
return getDefaultBackgroundToken3(context);
|
|
17506
|
+
}
|
|
17507
|
+
function getInitialPairingState3(searchParams) {
|
|
17508
|
+
const paletteParam = searchParams.get("palette");
|
|
17509
|
+
const primaryParam = searchParams.get("primary");
|
|
17510
|
+
const accentParam = searchParams.get("accent");
|
|
17511
|
+
const pairParam = searchParams.get("pair");
|
|
17512
|
+
const backgroundParam = searchParams.get("background");
|
|
17513
|
+
const themeCategory = paletteParam === "brand" || paletteParam === "aboriginal" ? paletteParam : "brand";
|
|
17514
|
+
const context = getPairingContext(themeCategory, primaryParam, accentParam);
|
|
17515
|
+
const shouldUseDefaultBrandExample = !backgroundParam && !pairParam && themeCategory === "brand" && context.primary.key === "blue" && context.accent.key === "red";
|
|
17516
|
+
const defaultBackgroundToken = shouldUseDefaultBrandExample ? context.backgrounds.some(
|
|
17517
|
+
(background) => background.token === DEFAULT_INITIAL_BACKGROUND_TOKEN3
|
|
17518
|
+
) ? DEFAULT_INITIAL_BACKGROUND_TOKEN3 : null : null;
|
|
17519
|
+
const defaultPairId = shouldUseDefaultBrandExample && defaultBackgroundToken && context.pairsByBackground[defaultBackgroundToken]?.some(
|
|
17520
|
+
(pair) => pair.id === DEFAULT_INITIAL_PAIR_ID3
|
|
17521
|
+
) ? DEFAULT_INITIAL_PAIR_ID3 : null;
|
|
17522
|
+
const pairBackgroundToken = context.recommendedPairs.find((pair) => pair.id === pairParam)?.background.token ?? null;
|
|
17523
|
+
const selectedBackgroundToken = resolveBackgroundToken3(
|
|
17524
|
+
context,
|
|
17525
|
+
backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken,
|
|
17526
|
+
getToneFromToken3(backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken)
|
|
17527
|
+
);
|
|
17528
|
+
const selectedPairId = getPreferredPairForBackground3(
|
|
17529
|
+
context.pairsByBackground[selectedBackgroundToken] ?? [],
|
|
17530
|
+
pairParam ?? defaultPairId
|
|
17531
|
+
)?.id ?? "";
|
|
17532
|
+
return {
|
|
17533
|
+
accentKey: context.accent.key,
|
|
17534
|
+
primaryKey: context.primary.key,
|
|
17535
|
+
selectedBackgroundToken,
|
|
17536
|
+
selectedPairId,
|
|
17537
|
+
themeCategory
|
|
17538
|
+
};
|
|
17539
|
+
}
|
|
17540
|
+
function getReadableTextColor2(tone) {
|
|
17541
|
+
return tone >= 600 ? "#ffffff" : "#002664";
|
|
17542
|
+
}
|
|
17543
|
+
function getBackgroundOptionName(background) {
|
|
17544
|
+
return background.name ?? `${background.familyLabel} ${background.tone}`;
|
|
17545
|
+
}
|
|
17546
|
+
function getResultExplanation(pair, bestPair) {
|
|
17547
|
+
if (!pair) {
|
|
17548
|
+
return "No AAA-compliant foreground options available for this selection.";
|
|
17549
|
+
}
|
|
17550
|
+
if (pair.id === bestPair?.id) {
|
|
17551
|
+
return "Meets AAA for normal and large text. This is the NSW-recommended starting point for this background.";
|
|
17552
|
+
}
|
|
17553
|
+
if (isWhiteForegroundPair3(pair) && isLargeTextOnlyPair(pair)) {
|
|
17554
|
+
return "White meets AAA for large text on this background only. Use a darker foreground for standard body copy and smaller interface text.";
|
|
17555
|
+
}
|
|
17556
|
+
if (isWhiteForegroundPair3(pair) && !pair.passes.aaaLarge) {
|
|
17557
|
+
return "White does not meet AAA for normal or large text on this background. Use another approved background or a darker foreground where one is available.";
|
|
17558
|
+
}
|
|
17559
|
+
return "Meets AAA for normal and large text. This is a valid alternative, while the recommended pairing remains the clearest default.";
|
|
17560
|
+
}
|
|
17561
|
+
function getBestRecommendationReason(pair, context) {
|
|
17562
|
+
if (isWhiteForegroundPair3(pair)) {
|
|
17563
|
+
return "Recommended because this background is dark enough to support white text at AAA contrast.";
|
|
17564
|
+
}
|
|
17565
|
+
if (pair.foreground.familyKey === pair.background.familyKey) {
|
|
17566
|
+
return "Recommended because it stays within the same colour family while keeping clear AAA contrast.";
|
|
17567
|
+
}
|
|
17568
|
+
if (pair.foreground.familyKey === context.grey.key) {
|
|
17569
|
+
return "Recommended because grey provides a strong neutral contrast without competing with the background.";
|
|
17570
|
+
}
|
|
17571
|
+
if (pair.foreground.familyKey === context.accent.key) {
|
|
17572
|
+
return "Recommended because the selected accent family adds emphasis while preserving AAA contrast.";
|
|
17573
|
+
}
|
|
17574
|
+
if (pair.foreground.familyKey === context.primary.key) {
|
|
17575
|
+
return "Recommended because the selected primary family gives the clearest AAA-compliant contrast for this background.";
|
|
17576
|
+
}
|
|
17577
|
+
return "Recommended because it is the clearest NSW-approved AAA pairing for this background.";
|
|
17578
|
+
}
|
|
17579
|
+
function getRecommendationCategory(pair, bestPair, context) {
|
|
17580
|
+
if (pair.id === bestPair?.id) return "best";
|
|
17581
|
+
if (isWhiteForegroundPair3(pair)) return "white";
|
|
17582
|
+
if (pair.foreground.familyKey === pair.background.familyKey) return "same-family";
|
|
17583
|
+
if (pair.foreground.familyKey === context.accent.key) return "accent-family";
|
|
17584
|
+
if (pair.foreground.familyKey === context.grey.key) return "grey-option";
|
|
17585
|
+
if (pair.foreground.familyKey === context.primary.key) return "primary-family";
|
|
17586
|
+
return "approved";
|
|
17587
|
+
}
|
|
17588
|
+
function getRecommendationCategoryLabel(category) {
|
|
17589
|
+
switch (category) {
|
|
17590
|
+
case "best":
|
|
17591
|
+
return "Best recommended";
|
|
17592
|
+
case "same-family":
|
|
17593
|
+
return "Same family";
|
|
17594
|
+
case "accent-family":
|
|
17595
|
+
return "Accent family";
|
|
17596
|
+
case "grey-option":
|
|
17597
|
+
return "Grey option";
|
|
17598
|
+
case "primary-family":
|
|
17599
|
+
return "Primary family";
|
|
17600
|
+
case "white":
|
|
17601
|
+
return "White";
|
|
17602
|
+
default:
|
|
17603
|
+
return "Approved option";
|
|
17604
|
+
}
|
|
17605
|
+
}
|
|
17606
|
+
function getRecommendationSortRank(category) {
|
|
17607
|
+
switch (category) {
|
|
17608
|
+
case "best":
|
|
17609
|
+
return 0;
|
|
17610
|
+
case "same-family":
|
|
17611
|
+
return 1;
|
|
17612
|
+
case "accent-family":
|
|
17613
|
+
return 2;
|
|
17614
|
+
case "grey-option":
|
|
17615
|
+
return 3;
|
|
17616
|
+
case "white":
|
|
17617
|
+
return 4;
|
|
17618
|
+
case "primary-family":
|
|
17619
|
+
return 5;
|
|
17620
|
+
default:
|
|
17621
|
+
return 6;
|
|
17622
|
+
}
|
|
17623
|
+
}
|
|
17624
|
+
function getAvailabilityMeta(isSelected, hasPairs) {
|
|
17625
|
+
if (isSelected && hasPairs) {
|
|
17626
|
+
return {
|
|
17627
|
+
description: "Selected background with AAA foreground options.",
|
|
17628
|
+
icon: Icons.check_circle,
|
|
17629
|
+
label: "Selected",
|
|
17630
|
+
tone: "selected"
|
|
17631
|
+
};
|
|
17632
|
+
}
|
|
17633
|
+
if (isSelected) {
|
|
17634
|
+
return {
|
|
17635
|
+
description: "Selected background with no AAA foreground options.",
|
|
17636
|
+
icon: Icons.warning,
|
|
17637
|
+
label: "Selected, no AAA",
|
|
17638
|
+
tone: "unavailable"
|
|
17639
|
+
};
|
|
17640
|
+
}
|
|
17641
|
+
if (hasPairs) {
|
|
17642
|
+
return {
|
|
17643
|
+
description: "AAA foreground options available.",
|
|
17644
|
+
icon: Icons.radio_button_checked,
|
|
17645
|
+
label: "Available",
|
|
17646
|
+
tone: "available"
|
|
17647
|
+
};
|
|
17648
|
+
}
|
|
17649
|
+
return {
|
|
17650
|
+
description: "No AAA foreground available.",
|
|
17651
|
+
icon: Icons.close,
|
|
17652
|
+
label: "No AAA",
|
|
17653
|
+
tone: "unavailable"
|
|
17654
|
+
};
|
|
17655
|
+
}
|
|
17656
|
+
function getPairingCopyText(pair) {
|
|
17657
|
+
return [
|
|
17658
|
+
`Background: ${pair.background.token} (${pair.background.hex})`,
|
|
17659
|
+
`Foreground: ${pair.foreground.token} (${pair.foreground.hex})`,
|
|
17660
|
+
`Contrast ratio: ${pair.contrastRatio.toFixed(2)}:1`,
|
|
17661
|
+
"Accessibility: Meets AAA for normal and large text"
|
|
17662
|
+
].join("\n");
|
|
17663
|
+
}
|
|
17664
|
+
function getLiveAnnouncement(pair, background) {
|
|
17665
|
+
if (!background) {
|
|
17666
|
+
return "No approved background tones available.";
|
|
17667
|
+
}
|
|
17668
|
+
if (!pair) {
|
|
17669
|
+
return `${background.token} selected. No AAA-compliant foreground options available for this selection.`;
|
|
17670
|
+
}
|
|
17671
|
+
if (isWhiteForegroundPair3(pair) && isLargeTextOnlyPair(pair)) {
|
|
17672
|
+
return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for large text only.`;
|
|
17673
|
+
}
|
|
17674
|
+
if (isWhiteForegroundPair3(pair) && !pair.passes.aaaLarge) {
|
|
17675
|
+
return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Fails AAA for normal and large text.`;
|
|
17676
|
+
}
|
|
17677
|
+
return `${background.token} with ${pair.foreground.token}. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for normal and large text.`;
|
|
17678
|
+
}
|
|
17679
|
+
function formatValueRows(color2, visibleFormats) {
|
|
17680
|
+
const hasDisplayTone = color2.token !== "white";
|
|
17681
|
+
return [
|
|
17682
|
+
{ key: "token", label: "Token", value: color2.token, copyable: true },
|
|
17683
|
+
{
|
|
17684
|
+
key: "tone",
|
|
17685
|
+
label: "Tone",
|
|
17686
|
+
value: hasDisplayTone ? String(color2.tone) : "Not applicable",
|
|
17687
|
+
copyable: hasDisplayTone
|
|
17688
|
+
},
|
|
17689
|
+
...visibleFormats.map((format) => ({
|
|
17690
|
+
key: format,
|
|
17691
|
+
label: format.toUpperCase(),
|
|
17692
|
+
value: color2[format],
|
|
17693
|
+
copyable: true
|
|
17694
|
+
}))
|
|
17695
|
+
];
|
|
17696
|
+
}
|
|
17697
|
+
function SelectorButton({
|
|
17698
|
+
description,
|
|
17699
|
+
isSelected,
|
|
17700
|
+
label,
|
|
17701
|
+
onClick,
|
|
17702
|
+
swatch
|
|
17703
|
+
}) {
|
|
17704
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17705
|
+
"button",
|
|
17706
|
+
{
|
|
17707
|
+
type: "button",
|
|
17708
|
+
"aria-pressed": isSelected,
|
|
17709
|
+
onClick,
|
|
17710
|
+
className: cn(
|
|
17711
|
+
"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",
|
|
17712
|
+
isSelected ? "border-primary-800 bg-primary-50" : "border-grey-300 bg-white hover:border-primary-500 hover:bg-grey-50"
|
|
17713
|
+
),
|
|
17714
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
|
|
17715
|
+
swatch ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
17716
|
+
"span",
|
|
17717
|
+
{
|
|
17718
|
+
"aria-hidden": "true",
|
|
17719
|
+
className: "mt-0.5 size-4 shrink-0 rounded-full border border-black/10",
|
|
17720
|
+
style: { backgroundColor: swatch }
|
|
17721
|
+
}
|
|
17722
|
+
) : null,
|
|
17723
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1", children: [
|
|
17724
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: label }),
|
|
17725
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs/5 text-muted-foreground", children: description }) : null
|
|
17726
|
+
] })
|
|
17727
|
+
] })
|
|
17728
|
+
}
|
|
17729
|
+
);
|
|
17730
|
+
}
|
|
17731
|
+
function BackgroundSwatchButton({
|
|
17732
|
+
background,
|
|
17733
|
+
hasPairs,
|
|
17734
|
+
isSelected,
|
|
17735
|
+
onClick
|
|
17736
|
+
}) {
|
|
17737
|
+
const status = getAvailabilityMeta(isSelected, hasPairs);
|
|
17738
|
+
const StatusIcon = status.icon;
|
|
17739
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17740
|
+
"button",
|
|
17741
|
+
{
|
|
17742
|
+
type: "button",
|
|
17743
|
+
"aria-pressed": isSelected,
|
|
17744
|
+
"aria-label": `Select ${background.token} background. ${status.description}`,
|
|
17745
|
+
onClick,
|
|
17746
|
+
className: cn(
|
|
17747
|
+
"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",
|
|
17748
|
+
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"
|
|
17749
|
+
),
|
|
17750
|
+
children: [
|
|
17751
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
17752
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
17753
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: getBackgroundOptionName(background) }),
|
|
17754
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-[0.72rem] break-all text-muted-foreground", children: background.token })
|
|
17755
|
+
] }),
|
|
17756
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17757
|
+
"span",
|
|
17758
|
+
{
|
|
17759
|
+
className: cn(
|
|
17760
|
+
"inline-flex items-center gap-1 rounded-sm border px-2 py-1 text-[0.68rem] font-semibold uppercase",
|
|
17761
|
+
status.tone === "selected" && "border-primary-800 bg-primary-800 text-white dark:border-primary-500 dark:bg-primary-500",
|
|
17762
|
+
status.tone === "available" && "border-grey-300 bg-grey-50 text-foreground",
|
|
17763
|
+
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"
|
|
17764
|
+
),
|
|
17765
|
+
children: [
|
|
17766
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { "data-slot": "icon", className: "size-4" }),
|
|
17767
|
+
status.label
|
|
17768
|
+
]
|
|
17769
|
+
}
|
|
17770
|
+
)
|
|
17771
|
+
] }),
|
|
17772
|
+
/* @__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 } }) }),
|
|
17773
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-xs/5 text-muted-foreground", children: status.description })
|
|
17774
|
+
]
|
|
17775
|
+
}
|
|
17776
|
+
);
|
|
17777
|
+
}
|
|
17778
|
+
function ResultSummaryTile({
|
|
17779
|
+
children,
|
|
17780
|
+
className,
|
|
17781
|
+
label
|
|
17782
|
+
}) {
|
|
17783
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("rounded-sm border border-grey-200 bg-white px-4 py-4 sm:px-5", className), children: [
|
|
17784
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-grey-700", children: label }),
|
|
17785
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3", children })
|
|
17786
|
+
] });
|
|
17787
|
+
}
|
|
17788
|
+
function AccessibilityCheckTile({
|
|
17789
|
+
className,
|
|
17790
|
+
label,
|
|
17791
|
+
passes,
|
|
17792
|
+
threshold
|
|
17793
|
+
}) {
|
|
17794
|
+
const status = passes === null ? "unavailable" : passes ? "pass" : "fail";
|
|
17795
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17796
|
+
"div",
|
|
17797
|
+
{
|
|
17798
|
+
className: cn(
|
|
17799
|
+
"rounded-sm border px-4 py-4 sm:px-5",
|
|
17800
|
+
className,
|
|
17801
|
+
status === "pass" && "border-success-200 bg-success-50",
|
|
17802
|
+
status === "fail" && "border-danger-200 bg-danger-50",
|
|
17803
|
+
status === "unavailable" && "border-grey-200 bg-white"
|
|
17804
|
+
),
|
|
17805
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between sm:gap-4", children: [
|
|
17806
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
17807
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: label }),
|
|
17808
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm/6 text-muted-foreground", children: status === "unavailable" ? "No contrast ratio available for this result." : threshold })
|
|
17809
|
+
] }),
|
|
17810
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17811
|
+
"span",
|
|
17812
|
+
{
|
|
17813
|
+
className: cn(
|
|
17814
|
+
"inline-flex items-center gap-1 rounded-sm px-2.5 py-1 text-[0.72rem] font-semibold tracking-[0.12em] uppercase",
|
|
17815
|
+
status === "pass" && "bg-success-700 text-white",
|
|
17816
|
+
status === "fail" && "bg-danger-700 text-white",
|
|
17817
|
+
status === "unavailable" && "bg-grey-100 text-foreground"
|
|
17818
|
+
),
|
|
17819
|
+
children: [
|
|
17820
|
+
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" }),
|
|
17821
|
+
status === "pass" ? "Pass" : status === "fail" ? "Fail" : "Unavailable"
|
|
17822
|
+
]
|
|
17823
|
+
}
|
|
17824
|
+
)
|
|
17825
|
+
] })
|
|
17826
|
+
}
|
|
17827
|
+
);
|
|
17828
|
+
}
|
|
17829
|
+
function ResultColorSummary({
|
|
17830
|
+
color: color2,
|
|
17831
|
+
fallbackLabel
|
|
17832
|
+
}) {
|
|
17833
|
+
if (!color2) {
|
|
17834
|
+
return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: fallbackLabel ?? "Not available" });
|
|
17835
|
+
}
|
|
17836
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-4", children: [
|
|
17837
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17838
|
+
"span",
|
|
17839
|
+
{
|
|
17840
|
+
"aria-hidden": "true",
|
|
17841
|
+
className: "mt-1 size-6 shrink-0 rounded-full border border-black/10",
|
|
17842
|
+
style: { backgroundColor: color2.hex }
|
|
17843
|
+
}
|
|
17844
|
+
),
|
|
17845
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
17846
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "leading-7 font-semibold text-foreground", children: getPairingColorDisplayName3(color2) }),
|
|
17847
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-sm break-all text-muted-foreground", children: color2.token })
|
|
17848
|
+
] })
|
|
17849
|
+
] });
|
|
17850
|
+
}
|
|
17851
|
+
function CurrentResultCard({
|
|
17852
|
+
bestPair,
|
|
17853
|
+
familySummary,
|
|
17854
|
+
pair,
|
|
17855
|
+
selectedBackground
|
|
17856
|
+
}) {
|
|
17857
|
+
const previewForeground = pair?.foreground.hex ?? getReadableTextColor2(selectedBackground.tone);
|
|
17858
|
+
const isRecommended = pair ? pair.id === bestPair?.id : false;
|
|
17859
|
+
const whiteForeground = pair ? isWhiteForegroundPair3(pair) : false;
|
|
17860
|
+
const statusLabel = pair ? pair.passes.aaaText ? "Pass" : pair.passes.aaaLarge ? "Large text only" : "Example only" : "No recommendation";
|
|
17861
|
+
const fauxButtonStyle = pair ? {
|
|
17862
|
+
"--btn-bg": pair.foreground.hex,
|
|
17863
|
+
"--btn-border": pair.foreground.hex,
|
|
17864
|
+
"--btn-text": pair.background.hex,
|
|
17865
|
+
"--btn-icon": pair.background.hex,
|
|
17866
|
+
"--btn-hover-overlay": pair.background.hex
|
|
17867
|
+
} : null;
|
|
17868
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "gap-0 overflow-hidden py-0", children: [
|
|
17869
|
+
/* @__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: "space-y-3", children: [
|
|
17870
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
17871
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: "Current result" }),
|
|
17872
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 4, className: "text-foreground", trim: "normal", children: pair ? `${getPairingColorDisplayName3(pair.foreground)} on ${getPairingColorDisplayName3(pair.background)}` : `${getPairingColorDisplayName3(selectedBackground)} selected` })
|
|
17873
|
+
] }),
|
|
17874
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "max-w-3xl text-grey-700", children: getResultExplanation(pair, bestPair) })
|
|
17875
|
+
] }) }),
|
|
17876
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17877
|
+
"div",
|
|
17878
|
+
{
|
|
17879
|
+
className: "p-4 sm:min-h-[26rem] sm:p-8",
|
|
17880
|
+
style: {
|
|
17881
|
+
backgroundColor: selectedBackground.hex,
|
|
17882
|
+
color: previewForeground
|
|
17883
|
+
},
|
|
17884
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[18rem] flex-col justify-between gap-6 sm:min-h-[22rem] sm:gap-8", children: [
|
|
17885
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
17886
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17887
|
+
"span",
|
|
17888
|
+
{
|
|
17889
|
+
className: "inline-flex items-center gap-2 rounded-full border px-3 py-1 text-[0.68rem] font-semibold tracking-[0.16em] uppercase sm:text-[0.72rem]",
|
|
17890
|
+
style: {
|
|
17891
|
+
borderColor: pair ? pair.foreground.hex : "currentColor",
|
|
17892
|
+
backgroundColor: pair ? pair.foreground.hex : "transparent",
|
|
17893
|
+
color: pair ? pair.background.hex : "currentColor"
|
|
17894
|
+
},
|
|
17895
|
+
children: [
|
|
17896
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.palette, { "data-slot": "icon", className: "size-4" }),
|
|
17897
|
+
familySummary
|
|
17898
|
+
]
|
|
17899
|
+
}
|
|
17900
|
+
),
|
|
17901
|
+
pair ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17902
|
+
"span",
|
|
17903
|
+
{
|
|
17904
|
+
className: "inline-flex rounded-full border px-3 py-1 text-[0.68rem] font-semibold tracking-[0.16em] uppercase sm:text-[0.72rem]",
|
|
17905
|
+
style: {
|
|
17906
|
+
borderColor: pair.foreground.hex
|
|
17907
|
+
},
|
|
17908
|
+
children: [
|
|
17909
|
+
pair.rating,
|
|
17910
|
+
" ",
|
|
17911
|
+
pair.contrastRatio.toFixed(2),
|
|
17912
|
+
":1"
|
|
17913
|
+
]
|
|
17914
|
+
}
|
|
17915
|
+
) : null
|
|
17916
|
+
] }),
|
|
17917
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-xl space-y-4 pb-8 sm:pb-16", children: [
|
|
17918
|
+
/* @__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" }),
|
|
17919
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
17920
|
+
/* @__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." }),
|
|
17921
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-full text-base/6 sm:max-w-md sm:text-base/7", children: pair ? getPreviewGuidance3(pair, isRecommended) : "This approved background tone does not currently have a recommended AAA foreground in this tool. Choose another approved background tone to continue." }),
|
|
17922
|
+
pair && fauxButtonStyle ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
17923
|
+
"span",
|
|
17924
|
+
{
|
|
17925
|
+
"aria-hidden": "true",
|
|
17926
|
+
"data-variant": "solid",
|
|
17927
|
+
className: cn(
|
|
17928
|
+
buttonVariants({ variant: "solid", size: "default" }),
|
|
17929
|
+
"pointer-events-none cursor-default px-6 text-[16px] font-[700] select-none sm:px-6 sm:text-[16px] sm:font-[700]"
|
|
17930
|
+
),
|
|
17931
|
+
style: fauxButtonStyle,
|
|
17932
|
+
children: "Get started"
|
|
17933
|
+
}
|
|
17934
|
+
) : null
|
|
17935
|
+
] })
|
|
17936
|
+
] }),
|
|
17937
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
17938
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17939
|
+
"span",
|
|
17940
|
+
{
|
|
17941
|
+
className: "inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm font-semibold",
|
|
17942
|
+
style: pair ? {
|
|
17943
|
+
backgroundColor: pair.foreground.hex,
|
|
17944
|
+
color: pair.background.hex
|
|
17945
|
+
} : {
|
|
17946
|
+
backgroundColor: "rgb(255 255 255 / 0.14)",
|
|
17947
|
+
color: "currentColor"
|
|
17948
|
+
},
|
|
17949
|
+
children: [
|
|
17950
|
+
statusLabel,
|
|
17951
|
+
pair && pair.passes.aaaText ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.info, { "data-slot": "icon", className: "size-4" })
|
|
17952
|
+
]
|
|
17953
|
+
}
|
|
17954
|
+
),
|
|
17955
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17956
|
+
"span",
|
|
17957
|
+
{
|
|
17958
|
+
className: "inline-flex max-w-full rounded-full border px-4 py-2 text-[0.82rem] break-all sm:text-sm",
|
|
17959
|
+
style: {
|
|
17960
|
+
borderColor: pair ? pair.foreground.hex : "currentColor"
|
|
17961
|
+
},
|
|
17962
|
+
children: pair ? `${pair.background.token} / ${pair.foreground.token}` : selectedBackground.token
|
|
17963
|
+
}
|
|
17964
|
+
)
|
|
17965
|
+
] })
|
|
17966
|
+
] })
|
|
17967
|
+
}
|
|
17968
|
+
),
|
|
17969
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-5 border-t border-grey-200 bg-grey-50 px-4 py-5 sm:px-6 sm:py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
|
|
17970
|
+
/* @__PURE__ */ jsxRuntime.jsx(ResultSummaryTile, { label: "Background", children: /* @__PURE__ */ jsxRuntime.jsx(ResultColorSummary, { color: selectedBackground }) }),
|
|
17971
|
+
/* @__PURE__ */ jsxRuntime.jsx(ResultSummaryTile, { label: "Foreground", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17972
|
+
ResultColorSummary,
|
|
17973
|
+
{
|
|
17974
|
+
color: pair?.foreground,
|
|
17975
|
+
fallbackLabel: "No AAA foreground available"
|
|
17976
|
+
}
|
|
17977
|
+
) }),
|
|
17978
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ResultSummaryTile, { label: "Contrast ratio", className: "lg:col-span-2", children: [
|
|
17979
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-4xl leading-none font-bold text-foreground", children: pair ? `${pair.contrastRatio.toFixed(2)}:1` : "N/A" }),
|
|
17980
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: pair ? pair.passes.aaaText ? "Meets AAA accessibility" : pair.passes.aaaLarge ? "Meets AAA for large text only" : "Does not meet accessibility requirements" : "Does not meet accessibility requirements" })
|
|
17981
|
+
] }),
|
|
17982
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17983
|
+
AccessibilityCheckTile,
|
|
17984
|
+
{
|
|
17985
|
+
className: "lg:col-span-2",
|
|
17986
|
+
label: "AAA normal text",
|
|
17987
|
+
passes: pair ? pair.passes.aaaText : null,
|
|
17988
|
+
threshold: AAA_NORMAL_TEXT_THRESHOLD2
|
|
17989
|
+
}
|
|
17990
|
+
),
|
|
17991
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17992
|
+
AccessibilityCheckTile,
|
|
17993
|
+
{
|
|
17994
|
+
className: "lg:col-span-2",
|
|
17995
|
+
label: "AAA large text",
|
|
17996
|
+
passes: pair ? pair.passes.aaaLarge : null,
|
|
17997
|
+
threshold: AAA_LARGE_TEXT_THRESHOLD2
|
|
17998
|
+
}
|
|
17999
|
+
)
|
|
18000
|
+
] }) })
|
|
18001
|
+
] });
|
|
18002
|
+
}
|
|
18003
|
+
function BestRecommendationCard({
|
|
18004
|
+
copiedKey,
|
|
18005
|
+
isCurrentSelection,
|
|
18006
|
+
onCopyPairing,
|
|
18007
|
+
onUsePairing,
|
|
18008
|
+
pair,
|
|
18009
|
+
reason
|
|
18010
|
+
}) {
|
|
18011
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "gap-5 border-primary-200 bg-primary-50/60 px-6 py-6", children: [
|
|
18012
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
|
|
18013
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
18014
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
18015
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-2 rounded-sm bg-primary-800 px-3 py-1 text-[0.72rem] font-semibold tracking-[0.12em] text-white uppercase", children: [
|
|
18016
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-4" }),
|
|
18017
|
+
"Best recommended pairing"
|
|
18018
|
+
] }),
|
|
18019
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex rounded-sm border border-primary-300 px-3 py-1 text-[0.72rem] font-semibold tracking-[0.12em] text-primary-900 uppercase", children: [
|
|
18020
|
+
pair.contrastRatio.toFixed(2),
|
|
18021
|
+
":1"
|
|
18022
|
+
] })
|
|
18023
|
+
] }),
|
|
18024
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
18025
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: [
|
|
18026
|
+
pair.background.token,
|
|
18027
|
+
" / ",
|
|
18028
|
+
pair.foreground.token
|
|
18029
|
+
] }),
|
|
18030
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "max-w-3xl text-grey-700", children: reason })
|
|
18031
|
+
] })
|
|
18032
|
+
] }),
|
|
18033
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center", children: [
|
|
18034
|
+
isCurrentSelection ? null : /* @__PURE__ */ jsxRuntime.jsx(
|
|
18035
|
+
Button2,
|
|
18036
|
+
{
|
|
18037
|
+
className: "w-full justify-center sm:w-auto sm:min-w-56",
|
|
18038
|
+
color: "primary",
|
|
18039
|
+
onClick: onUsePairing,
|
|
18040
|
+
"aria-label": `Use ${pair.foreground.token} on ${pair.background.token}`,
|
|
18041
|
+
children: "Use best recommendation"
|
|
18042
|
+
}
|
|
18043
|
+
),
|
|
18044
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
18045
|
+
Button2,
|
|
18046
|
+
{
|
|
18047
|
+
className: "w-full justify-center sm:w-auto sm:min-w-48",
|
|
18048
|
+
variant: "outline",
|
|
18049
|
+
color: "grey",
|
|
18050
|
+
onClick: onCopyPairing,
|
|
18051
|
+
children: [
|
|
18052
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
|
|
18053
|
+
copiedKey === "best-pairing" ? "Pairing copied" : "Copy pairing"
|
|
18054
|
+
]
|
|
18055
|
+
}
|
|
18056
|
+
)
|
|
18057
|
+
] })
|
|
18058
|
+
] }),
|
|
18059
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
|
|
18060
|
+
/* @__PURE__ */ jsxRuntime.jsx(ResultSummaryTile, { label: "Background", children: /* @__PURE__ */ jsxRuntime.jsx(ResultColorSummary, { color: pair.background }) }),
|
|
18061
|
+
/* @__PURE__ */ jsxRuntime.jsx(ResultSummaryTile, { label: "Foreground", children: /* @__PURE__ */ jsxRuntime.jsx(ResultColorSummary, { color: pair.foreground }) }),
|
|
18062
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ResultSummaryTile, { label: "Accessibility", className: "md:col-span-2", children: [
|
|
18063
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xl leading-8 font-semibold text-foreground", children: "Meets AAA accessibility" }),
|
|
18064
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-base/7 text-muted-foreground", children: "Best NSW default for this background." })
|
|
18065
|
+
] })
|
|
18066
|
+
] })
|
|
18067
|
+
] });
|
|
18068
|
+
}
|
|
18069
|
+
function RecommendationCard({
|
|
18070
|
+
copiedKey,
|
|
18071
|
+
isSelected,
|
|
18072
|
+
item,
|
|
18073
|
+
onCopyPairing,
|
|
18074
|
+
onSelect
|
|
18075
|
+
}) {
|
|
18076
|
+
const { pair } = item;
|
|
18077
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18078
|
+
"div",
|
|
18079
|
+
{
|
|
18080
|
+
className: cn(
|
|
18081
|
+
"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",
|
|
18082
|
+
isSelected ? "border-primary-800 bg-primary-50/50" : "border-grey-200 hover:border-primary-500 hover:bg-grey-50"
|
|
18083
|
+
),
|
|
18084
|
+
children: [
|
|
18085
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18086
|
+
"button",
|
|
18087
|
+
{
|
|
18088
|
+
type: "button",
|
|
18089
|
+
"aria-pressed": isSelected,
|
|
18090
|
+
"aria-label": `Use ${pair.foreground.token} on ${pair.background.token}`,
|
|
18091
|
+
onClick: onSelect,
|
|
18092
|
+
className: "absolute inset-0 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden"
|
|
18093
|
+
}
|
|
18094
|
+
),
|
|
18095
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none relative z-10", children: [
|
|
18096
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
18097
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
18098
|
+
"span",
|
|
18099
|
+
{
|
|
18100
|
+
className: cn(
|
|
18101
|
+
"inline-flex items-center gap-2 rounded-sm px-2.5 py-1 text-[0.68rem] font-semibold tracking-[0.12em] uppercase",
|
|
18102
|
+
item.category === "best" ? "bg-primary-800 text-white" : "border border-grey-300 bg-grey-50 text-foreground"
|
|
18103
|
+
),
|
|
18104
|
+
children: [
|
|
18105
|
+
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" }),
|
|
18106
|
+
item.categoryLabel
|
|
18107
|
+
]
|
|
18108
|
+
}
|
|
18109
|
+
),
|
|
18110
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto shrink-0 self-start", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18111
|
+
Button2,
|
|
18112
|
+
{
|
|
18113
|
+
variant: "ghost",
|
|
18114
|
+
color: "grey",
|
|
18115
|
+
size: "sm",
|
|
18116
|
+
onClick: onCopyPairing,
|
|
18117
|
+
"aria-label": `Copy pairing ${pair.background.token} and ${pair.foreground.token}`,
|
|
18118
|
+
children: [
|
|
18119
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
|
|
18120
|
+
copiedKey === `pair:${pair.id}` ? "Copied" : "Copy"
|
|
18121
|
+
]
|
|
18122
|
+
}
|
|
18123
|
+
) })
|
|
18124
|
+
] }),
|
|
18125
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4", children: [
|
|
18126
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 sm:grid-cols-[4rem_minmax(0,1fr)]", children: [
|
|
18127
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-[2px] border border-black/10", children: [
|
|
18128
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-16 w-full", style: { backgroundColor: pair.background.hex } }),
|
|
18129
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 w-full", style: { backgroundColor: pair.foreground.hex } })
|
|
18130
|
+
] }),
|
|
18131
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-2", children: [
|
|
18132
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
18133
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-semibold text-foreground", children: getPairingColorDisplayName3(pair.foreground) }),
|
|
18134
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-[0.74rem] break-all text-muted-foreground", children: pair.foreground.token })
|
|
18135
|
+
] }),
|
|
18136
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
18137
|
+
pair.foreground.familyLabel,
|
|
18138
|
+
" on ",
|
|
18139
|
+
pair.background.familyLabel
|
|
18140
|
+
] })
|
|
18141
|
+
] })
|
|
18142
|
+
] }),
|
|
18143
|
+
/* @__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: [
|
|
18144
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
18145
|
+
/* @__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: [
|
|
18146
|
+
pair.contrastRatio.toFixed(2),
|
|
18147
|
+
":1"
|
|
18148
|
+
] }),
|
|
18149
|
+
/* @__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" })
|
|
18150
|
+
] }),
|
|
18151
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-primary-800", children: isSelected ? "Selected" : "Use pairing" })
|
|
18152
|
+
] })
|
|
18153
|
+
] })
|
|
18154
|
+
] })
|
|
18155
|
+
]
|
|
18156
|
+
}
|
|
18157
|
+
);
|
|
18158
|
+
}
|
|
18159
|
+
function TechnicalDetailsPanel({
|
|
18160
|
+
color: color2,
|
|
18161
|
+
copiedKey,
|
|
18162
|
+
onCopyValue,
|
|
18163
|
+
title,
|
|
18164
|
+
visibleFormats
|
|
18165
|
+
}) {
|
|
18166
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white", children: [
|
|
18167
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-grey-200 px-4 py-4 sm:px-5", children: [
|
|
18168
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: title }),
|
|
18169
|
+
color2 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18170
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: getPairingColorDisplayName3(color2) }),
|
|
18171
|
+
/* @__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 } }) })
|
|
18172
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "No AAA foreground available." })
|
|
18173
|
+
] }),
|
|
18174
|
+
color2 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-grey-200", children: formatValueRows(color2, visibleFormats).map((row) => {
|
|
18175
|
+
const copyKey = `${title}-${row.key}`;
|
|
18176
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18177
|
+
"div",
|
|
18178
|
+
{
|
|
18179
|
+
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",
|
|
18180
|
+
children: [
|
|
18181
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
18182
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: row.label }),
|
|
18183
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18184
|
+
"p",
|
|
18185
|
+
{
|
|
18186
|
+
className: cn(
|
|
18187
|
+
"mt-2 text-sm text-foreground",
|
|
18188
|
+
row.key !== "tone" && "font-mono break-all"
|
|
18189
|
+
),
|
|
18190
|
+
children: row.value
|
|
18191
|
+
}
|
|
18192
|
+
)
|
|
18193
|
+
] }),
|
|
18194
|
+
row.copyable ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
18195
|
+
Button2,
|
|
18196
|
+
{
|
|
18197
|
+
variant: "ghost",
|
|
18198
|
+
color: "grey",
|
|
18199
|
+
size: "sm",
|
|
18200
|
+
className: "self-start",
|
|
18201
|
+
onClick: () => onCopyValue(copyKey, row.value, `${row.label} copied`),
|
|
18202
|
+
"aria-label": `Copy ${title.toLowerCase()} ${row.label.toLowerCase()}`,
|
|
18203
|
+
children: copiedKey === copyKey ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18204
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-5" }),
|
|
18205
|
+
"Copied"
|
|
18206
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18207
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
|
|
18208
|
+
"Copy"
|
|
18209
|
+
] })
|
|
18210
|
+
}
|
|
18211
|
+
) : null
|
|
18212
|
+
]
|
|
18213
|
+
},
|
|
18214
|
+
row.key
|
|
18215
|
+
);
|
|
18216
|
+
}) }) : /* @__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." }) })
|
|
18217
|
+
] });
|
|
18218
|
+
}
|
|
18219
|
+
function resolveSelectionState(nextThemeCategory, nextPrimaryKey, nextAccentKey, preferredBackgroundToken, preferredPairId) {
|
|
18220
|
+
const context = getPairingContext(nextThemeCategory, nextPrimaryKey, nextAccentKey);
|
|
18221
|
+
const selectedBackgroundToken = resolveBackgroundToken3(
|
|
18222
|
+
context,
|
|
18223
|
+
preferredBackgroundToken,
|
|
18224
|
+
getToneFromToken3(preferredBackgroundToken)
|
|
18225
|
+
);
|
|
18226
|
+
const selectedPairId = getPreferredPairForBackground3(
|
|
18227
|
+
context.pairsByBackground[selectedBackgroundToken] ?? [],
|
|
18228
|
+
preferredPairId
|
|
18229
|
+
)?.id ?? "";
|
|
18230
|
+
return {
|
|
18231
|
+
accentKey: context.accent.key,
|
|
18232
|
+
context,
|
|
18233
|
+
primaryKey: context.primary.key,
|
|
18234
|
+
selectedBackgroundToken,
|
|
18235
|
+
selectedPairId,
|
|
18236
|
+
themeCategory: nextThemeCategory
|
|
18237
|
+
};
|
|
18238
|
+
}
|
|
18239
|
+
function ColorPairingToolV3Loading() {
|
|
18240
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 xl:grid-cols-[minmax(18rem,24rem)_minmax(0,1fr)]", children: [
|
|
18241
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
18242
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-52 rounded-sm border border-grey-200 bg-grey-50" }),
|
|
18243
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[32rem] rounded-sm border border-grey-200 bg-grey-50" })
|
|
18244
|
+
] }),
|
|
18245
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
18246
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-96 rounded-sm border border-grey-200 bg-grey-50" }),
|
|
18247
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-64 rounded-sm border border-grey-200 bg-grey-50" }),
|
|
18248
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-72 rounded-sm border border-grey-200 bg-grey-50" })
|
|
18249
|
+
] })
|
|
18250
|
+
] });
|
|
18251
|
+
}
|
|
18252
|
+
function ColorPairingToolV3Content({
|
|
18253
|
+
onAnalyticsEvent,
|
|
18254
|
+
visibleFormats
|
|
18255
|
+
}) {
|
|
18256
|
+
const searchParams = navigation.useSearchParams();
|
|
18257
|
+
const stickyOffset = useStickyOffset(24);
|
|
18258
|
+
const [initialState] = React5.useState(() => getInitialPairingState3(searchParams));
|
|
18259
|
+
const [themeCategory, setThemeCategory] = React5.useState(initialState.themeCategory);
|
|
18260
|
+
const [primaryFamilyKey, setPrimaryFamilyKey] = React5.useState(initialState.primaryKey);
|
|
18261
|
+
const [accentFamilyKey, setAccentFamilyKey] = React5.useState(initialState.accentKey);
|
|
18262
|
+
const [selectedBackgroundToken, setSelectedBackgroundToken] = React5.useState(
|
|
18263
|
+
initialState.selectedBackgroundToken
|
|
18264
|
+
);
|
|
18265
|
+
const [selectedPairId, setSelectedPairId] = React5.useState(initialState.selectedPairId);
|
|
18266
|
+
const [drawerStepIndex, setDrawerStepIndex] = React5.useState(0);
|
|
18267
|
+
const [isCompactControlsOpen, setIsCompactControlsOpen] = React5.useState(false);
|
|
18268
|
+
const [, copyToClipboardRaw] = usehooks.useCopyToClipboard();
|
|
18269
|
+
const [copiedKey, setCopiedKey] = React5.useState(null);
|
|
18270
|
+
const copiedKeyTimeoutRef = React5.useRef(null);
|
|
18271
|
+
const resultSectionRef = React5.useRef(null);
|
|
18272
|
+
const technicalDetailsSectionRef = React5.useRef(null);
|
|
18273
|
+
const noValidStateRef = React5.useRef(/* @__PURE__ */ new Set());
|
|
18274
|
+
const technicalDetailsViewedRef = React5.useRef(false);
|
|
18275
|
+
const emitAnalyticsEvent = React5.useCallback(
|
|
18276
|
+
(event) => {
|
|
18277
|
+
onAnalyticsEvent(event);
|
|
18278
|
+
if (typeof window !== "undefined") {
|
|
18279
|
+
window.dispatchEvent(
|
|
18280
|
+
new CustomEvent(COLOR_PAIRING_TOOL_V3_ANALYTICS_EVENT, {
|
|
18281
|
+
detail: event
|
|
18282
|
+
})
|
|
18283
|
+
);
|
|
18284
|
+
}
|
|
18285
|
+
},
|
|
18286
|
+
[onAnalyticsEvent]
|
|
18287
|
+
);
|
|
18288
|
+
React5.useEffect(() => {
|
|
18289
|
+
return () => {
|
|
18290
|
+
if (copiedKeyTimeoutRef.current) {
|
|
18291
|
+
clearTimeout(copiedKeyTimeoutRef.current);
|
|
18292
|
+
}
|
|
18293
|
+
};
|
|
18294
|
+
}, []);
|
|
18295
|
+
React5.useEffect(() => {
|
|
18296
|
+
if (typeof window === "undefined") {
|
|
18297
|
+
return;
|
|
18298
|
+
}
|
|
18299
|
+
const mediaQuery = window.matchMedia(PERSISTENT_DRAWER_MIN_WIDTH_QUERY);
|
|
18300
|
+
const handleChange = (event) => {
|
|
18301
|
+
if (event?.matches ?? mediaQuery.matches) {
|
|
18302
|
+
setIsCompactControlsOpen(false);
|
|
18303
|
+
}
|
|
18304
|
+
};
|
|
18305
|
+
handleChange();
|
|
18306
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
18307
|
+
return () => {
|
|
18308
|
+
mediaQuery.removeEventListener("change", handleChange);
|
|
18309
|
+
};
|
|
18310
|
+
}, []);
|
|
18311
|
+
const themeFamilies = React5.useMemo(() => getPairingFamilies(themeCategory), [themeCategory]);
|
|
18312
|
+
const context = React5.useMemo(
|
|
18313
|
+
() => getPairingContext(themeCategory, primaryFamilyKey, accentFamilyKey),
|
|
18314
|
+
[themeCategory, primaryFamilyKey, accentFamilyKey]
|
|
18315
|
+
);
|
|
18316
|
+
const selectableFamilies = React5.useMemo(
|
|
18317
|
+
() => themeFamilies.filter((family) => family.key !== context.grey.key),
|
|
18318
|
+
[themeFamilies, context.grey.key]
|
|
18319
|
+
);
|
|
18320
|
+
const selectableAccentFamilies = React5.useMemo(
|
|
18321
|
+
() => selectableFamilies.filter((family) => family.key !== context.primary.key),
|
|
18322
|
+
[selectableFamilies, context.primary.key]
|
|
18323
|
+
);
|
|
18324
|
+
const selectedBackground = React5.useMemo(
|
|
18325
|
+
() => context.backgrounds.find((background) => background.token === selectedBackgroundToken) ?? context.backgrounds[0] ?? null,
|
|
18326
|
+
[context.backgrounds, selectedBackgroundToken]
|
|
18327
|
+
);
|
|
18328
|
+
const selectedBackgroundPairs = React5.useMemo(
|
|
18329
|
+
() => selectedBackground ? context.pairsByBackground[selectedBackground.token] ?? [] : [],
|
|
18330
|
+
[context.pairsByBackground, selectedBackground]
|
|
18331
|
+
);
|
|
18332
|
+
const bestRecommendedPair = React5.useMemo(
|
|
18333
|
+
() => getPreferredPairForBackground3(selectedBackgroundPairs),
|
|
18334
|
+
[selectedBackgroundPairs]
|
|
18335
|
+
);
|
|
18336
|
+
const selectedPair = React5.useMemo(
|
|
18337
|
+
() => getPreferredPairForBackground3(selectedBackgroundPairs, selectedPairId),
|
|
18338
|
+
[selectedBackgroundPairs, selectedPairId]
|
|
18339
|
+
);
|
|
18340
|
+
const whiteForegroundExample = React5.useMemo(
|
|
18341
|
+
() => selectedBackground && supportsWhiteForegroundPreview(selectedBackground) ? getWhiteForegroundPair(selectedBackground) : null,
|
|
18342
|
+
[selectedBackground]
|
|
18343
|
+
);
|
|
18344
|
+
const previewPair = selectedPair ?? whiteForegroundExample ?? null;
|
|
18345
|
+
const detailForeground = selectedPair?.foreground ?? whiteForegroundExample?.foreground ?? null;
|
|
18346
|
+
const familySummary = React5.useMemo(
|
|
18347
|
+
() => [context.primary.label, context.accent.label, context.grey.label].join(" + "),
|
|
18348
|
+
[context.accent.label, context.grey.label, context.primary.label]
|
|
18349
|
+
);
|
|
18350
|
+
const recommendationItems = React5.useMemo(() => {
|
|
18351
|
+
return selectedBackgroundPairs.map((pair) => {
|
|
18352
|
+
const category = getRecommendationCategory(pair, bestRecommendedPair, context);
|
|
18353
|
+
return {
|
|
18354
|
+
category,
|
|
18355
|
+
categoryLabel: getRecommendationCategoryLabel(category),
|
|
18356
|
+
pair
|
|
18357
|
+
};
|
|
18358
|
+
}).sort(
|
|
18359
|
+
(left, right) => getRecommendationSortRank(left.category) - getRecommendationSortRank(right.category)
|
|
18360
|
+
);
|
|
18361
|
+
}, [bestRecommendedPair, context, selectedBackgroundPairs]);
|
|
18362
|
+
const liveAnnouncement = React5.useMemo(
|
|
18363
|
+
() => getLiveAnnouncement(previewPair, selectedBackground),
|
|
18364
|
+
[previewPair, selectedBackground]
|
|
18365
|
+
);
|
|
18366
|
+
const shareBackgroundToken = selectedBackground?.token ?? selectedBackgroundToken;
|
|
18367
|
+
const shareUrl = React5.useMemo(() => {
|
|
18368
|
+
const params = new URLSearchParams();
|
|
18369
|
+
params.set("palette", themeCategory);
|
|
18370
|
+
params.set("primary", context.primary.key);
|
|
18371
|
+
params.set("accent", context.accent.key);
|
|
18372
|
+
if (shareBackgroundToken) {
|
|
18373
|
+
params.set("background", shareBackgroundToken);
|
|
18374
|
+
}
|
|
18375
|
+
if (selectedPairId) {
|
|
18376
|
+
params.set("pair", selectedPairId);
|
|
18377
|
+
}
|
|
18378
|
+
const query = params.toString();
|
|
18379
|
+
return `${COLOR_PAIRING_TOOL_V3_PATH}${query ? `?${query}` : ""}`;
|
|
18380
|
+
}, [context.accent.key, context.primary.key, shareBackgroundToken, selectedPairId, themeCategory]);
|
|
18381
|
+
const activeDrawerStep = COLOR_PAIRING_TOOL_DRAWER_STEPS[drawerStepIndex];
|
|
18382
|
+
const isFirstDrawerStep = drawerStepIndex === 0;
|
|
18383
|
+
const isLastDrawerStep = drawerStepIndex === COLOR_PAIRING_TOOL_DRAWER_STEPS.length - 1;
|
|
18384
|
+
const desktopSidebarStyle = React5.useMemo(
|
|
18385
|
+
() => ({
|
|
18386
|
+
"--tool-sidebar-max-height": `calc(100vh - ${stickyOffset}px)`,
|
|
18387
|
+
"--tool-sidebar-top": `${stickyOffset}px`
|
|
18388
|
+
}),
|
|
18389
|
+
[stickyOffset]
|
|
18390
|
+
);
|
|
18391
|
+
const goToDrawerStep = React5.useCallback((stepIndex) => {
|
|
18392
|
+
setDrawerStepIndex(Math.max(0, Math.min(stepIndex, COLOR_PAIRING_TOOL_DRAWER_STEPS.length - 1)));
|
|
18393
|
+
}, []);
|
|
18394
|
+
const goToNextDrawerStep = React5.useCallback(() => {
|
|
18395
|
+
setDrawerStepIndex(
|
|
18396
|
+
(currentStep) => Math.min(currentStep + 1, COLOR_PAIRING_TOOL_DRAWER_STEPS.length - 1)
|
|
18397
|
+
);
|
|
18398
|
+
}, []);
|
|
18399
|
+
const goToPreviousDrawerStep = React5.useCallback(() => {
|
|
18400
|
+
setDrawerStepIndex((currentStep) => Math.max(currentStep - 1, 0));
|
|
18401
|
+
}, []);
|
|
18402
|
+
const updateUrlParams = React5.useCallback((nextState) => {
|
|
18403
|
+
const params = new URLSearchParams(window.location.search);
|
|
18404
|
+
params.delete("family");
|
|
18405
|
+
params.set("palette", nextState.themeCategory);
|
|
18406
|
+
params.set("primary", nextState.primaryKey);
|
|
18407
|
+
params.set("accent", nextState.accentKey);
|
|
18408
|
+
params.set("background", nextState.selectedBackgroundToken);
|
|
18409
|
+
if (nextState.selectedPairId) {
|
|
18410
|
+
params.set("pair", nextState.selectedPairId);
|
|
18411
|
+
} else {
|
|
18412
|
+
params.delete("pair");
|
|
18413
|
+
}
|
|
18414
|
+
window.history.replaceState(
|
|
18415
|
+
null,
|
|
18416
|
+
"",
|
|
18417
|
+
`${window.location.pathname}?${params.toString()}${window.location.hash}`
|
|
18418
|
+
);
|
|
18419
|
+
}, []);
|
|
18420
|
+
const applyResolvedSelection = React5.useCallback(
|
|
18421
|
+
(nextState) => {
|
|
18422
|
+
setThemeCategory(nextState.themeCategory);
|
|
18423
|
+
setPrimaryFamilyKey(nextState.primaryKey);
|
|
18424
|
+
setAccentFamilyKey(nextState.accentKey);
|
|
18425
|
+
setSelectedBackgroundToken(nextState.selectedBackgroundToken);
|
|
18426
|
+
setSelectedPairId(nextState.selectedPairId);
|
|
18427
|
+
updateUrlParams(nextState);
|
|
18428
|
+
},
|
|
18429
|
+
[updateUrlParams]
|
|
18430
|
+
);
|
|
18431
|
+
const buildAnalyticsContext = React5.useCallback(
|
|
18432
|
+
(overrides) => ({
|
|
18433
|
+
accentKey: context.accent.key,
|
|
18434
|
+
backgroundToken: selectedBackground?.token,
|
|
18435
|
+
foregroundToken: selectedPair?.foreground.token,
|
|
18436
|
+
pairId: selectedPair?.id,
|
|
18437
|
+
palette: themeCategory,
|
|
18438
|
+
primaryKey: context.primary.key,
|
|
18439
|
+
...overrides
|
|
18440
|
+
}),
|
|
18441
|
+
[context.accent.key, context.primary.key, selectedBackground, selectedPair, themeCategory]
|
|
18442
|
+
);
|
|
18443
|
+
const copyValue = React5.useCallback(
|
|
18444
|
+
(copyKey, value, toastLabel, analyticsEvent) => {
|
|
18445
|
+
copyToClipboardRaw(value);
|
|
18446
|
+
setCopiedKey(copyKey);
|
|
18447
|
+
sonner.toast(toastLabel, { duration: 2e3 });
|
|
18448
|
+
if (analyticsEvent) {
|
|
18449
|
+
emitAnalyticsEvent(analyticsEvent);
|
|
18450
|
+
}
|
|
18451
|
+
if (copiedKeyTimeoutRef.current) {
|
|
18452
|
+
clearTimeout(copiedKeyTimeoutRef.current);
|
|
18453
|
+
}
|
|
18454
|
+
copiedKeyTimeoutRef.current = setTimeout(() => {
|
|
18455
|
+
setCopiedKey(null);
|
|
18456
|
+
copiedKeyTimeoutRef.current = null;
|
|
18457
|
+
}, 2e3);
|
|
18458
|
+
},
|
|
18459
|
+
[copyToClipboardRaw, emitAnalyticsEvent]
|
|
18460
|
+
);
|
|
18461
|
+
const handleThemeCategoryChange = (nextThemeCategory) => {
|
|
18462
|
+
const nextState = resolveSelectionState(
|
|
18463
|
+
nextThemeCategory,
|
|
18464
|
+
primaryFamilyKey,
|
|
18465
|
+
accentFamilyKey,
|
|
18466
|
+
selectedBackgroundToken,
|
|
18467
|
+
selectedPairId
|
|
18468
|
+
);
|
|
18469
|
+
applyResolvedSelection(nextState);
|
|
18470
|
+
emitAnalyticsEvent({
|
|
18471
|
+
name: "palette_change",
|
|
18472
|
+
accentKey: nextState.accentKey,
|
|
18473
|
+
backgroundToken: nextState.selectedBackgroundToken,
|
|
18474
|
+
pairId: nextState.selectedPairId,
|
|
18475
|
+
palette: nextState.themeCategory,
|
|
18476
|
+
primaryKey: nextState.primaryKey
|
|
18477
|
+
});
|
|
18478
|
+
};
|
|
18479
|
+
const handlePrimaryColorChange = (nextPrimaryKey) => {
|
|
18480
|
+
const nextAccentKey = nextPrimaryKey === accentFamilyKey ? getDefaultAccentFamilyKey(themeCategory, nextPrimaryKey) : accentFamilyKey;
|
|
18481
|
+
const nextState = resolveSelectionState(
|
|
18482
|
+
themeCategory,
|
|
18483
|
+
nextPrimaryKey,
|
|
18484
|
+
nextAccentKey,
|
|
18485
|
+
selectedBackgroundToken,
|
|
18486
|
+
selectedPairId
|
|
18487
|
+
);
|
|
18488
|
+
applyResolvedSelection(nextState);
|
|
18489
|
+
emitAnalyticsEvent({
|
|
18490
|
+
name: "primary_change",
|
|
18491
|
+
accentKey: nextState.accentKey,
|
|
18492
|
+
backgroundToken: nextState.selectedBackgroundToken,
|
|
18493
|
+
pairId: nextState.selectedPairId,
|
|
18494
|
+
palette: nextState.themeCategory,
|
|
18495
|
+
primaryKey: nextState.primaryKey
|
|
18496
|
+
});
|
|
18497
|
+
};
|
|
18498
|
+
const handleAccentColorChange = (nextAccentKey) => {
|
|
18499
|
+
if (nextAccentKey === primaryFamilyKey) return;
|
|
18500
|
+
const nextState = resolveSelectionState(
|
|
18501
|
+
themeCategory,
|
|
18502
|
+
primaryFamilyKey,
|
|
18503
|
+
nextAccentKey,
|
|
18504
|
+
selectedBackgroundToken,
|
|
18505
|
+
selectedPairId
|
|
18506
|
+
);
|
|
18507
|
+
applyResolvedSelection(nextState);
|
|
18508
|
+
emitAnalyticsEvent({
|
|
18509
|
+
name: "accent_change",
|
|
18510
|
+
accentKey: nextState.accentKey,
|
|
18511
|
+
backgroundToken: nextState.selectedBackgroundToken,
|
|
18512
|
+
pairId: nextState.selectedPairId,
|
|
18513
|
+
palette: nextState.themeCategory,
|
|
18514
|
+
primaryKey: nextState.primaryKey
|
|
18515
|
+
});
|
|
18516
|
+
};
|
|
18517
|
+
const handleBackgroundChange = (nextSelectedBackgroundToken) => {
|
|
18518
|
+
const nextSelectedPairId = getPreferredPairForBackground3(
|
|
18519
|
+
context.pairsByBackground[nextSelectedBackgroundToken] ?? [],
|
|
18520
|
+
selectedPairId
|
|
18521
|
+
)?.id ?? "";
|
|
18522
|
+
const nextState = {
|
|
18523
|
+
accentKey: context.accent.key,
|
|
18524
|
+
context,
|
|
18525
|
+
primaryKey: context.primary.key,
|
|
18526
|
+
selectedBackgroundToken: nextSelectedBackgroundToken,
|
|
18527
|
+
selectedPairId: nextSelectedPairId,
|
|
18528
|
+
themeCategory
|
|
18529
|
+
};
|
|
18530
|
+
applyResolvedSelection(nextState);
|
|
18531
|
+
emitAnalyticsEvent({
|
|
18532
|
+
name: "background_selection",
|
|
18533
|
+
...buildAnalyticsContext({
|
|
18534
|
+
backgroundToken: nextSelectedBackgroundToken,
|
|
18535
|
+
foregroundToken: context.pairsByBackground[nextSelectedBackgroundToken]?.find(
|
|
18536
|
+
(pair) => pair.id === nextSelectedPairId
|
|
18537
|
+
)?.foreground.token,
|
|
18538
|
+
pairId: nextSelectedPairId
|
|
18539
|
+
})
|
|
18540
|
+
});
|
|
18541
|
+
if (typeof window !== "undefined" && window.matchMedia(MOBILE_RESULT_SCROLL_QUERY).matches) {
|
|
18542
|
+
requestAnimationFrame(() => {
|
|
18543
|
+
resultSectionRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
18544
|
+
});
|
|
18545
|
+
}
|
|
18546
|
+
};
|
|
18547
|
+
const handlePairChange = (nextSelectedPairId, source) => {
|
|
18548
|
+
if (!selectedBackground) return;
|
|
18549
|
+
const nextPair = selectedBackgroundPairs.find((pair) => pair.id === nextSelectedPairId) ?? null;
|
|
18550
|
+
setSelectedPairId(nextSelectedPairId);
|
|
18551
|
+
updateUrlParams({
|
|
18552
|
+
accentKey: context.accent.key,
|
|
18553
|
+
context,
|
|
18554
|
+
primaryKey: context.primary.key,
|
|
18555
|
+
selectedBackgroundToken: selectedBackground.token,
|
|
18556
|
+
selectedPairId: nextSelectedPairId,
|
|
18557
|
+
themeCategory
|
|
18558
|
+
});
|
|
18559
|
+
emitAnalyticsEvent({
|
|
18560
|
+
name: "foreground_selection",
|
|
18561
|
+
...buildAnalyticsContext({
|
|
18562
|
+
foregroundToken: nextPair?.foreground.token,
|
|
18563
|
+
pairId: nextSelectedPairId,
|
|
18564
|
+
source
|
|
18565
|
+
})
|
|
18566
|
+
});
|
|
18567
|
+
if (bestRecommendedPair && nextSelectedPairId !== bestRecommendedPair.id) {
|
|
18568
|
+
emitAnalyticsEvent({
|
|
18569
|
+
name: "alternative_combination_selected",
|
|
18570
|
+
...buildAnalyticsContext({
|
|
18571
|
+
foregroundToken: nextPair?.foreground.token,
|
|
18572
|
+
pairId: nextSelectedPairId,
|
|
18573
|
+
source
|
|
18574
|
+
})
|
|
18575
|
+
});
|
|
18576
|
+
}
|
|
18577
|
+
};
|
|
18578
|
+
React5.useEffect(() => {
|
|
18579
|
+
if (!selectedBackground || selectedBackgroundPairs.length > 0) {
|
|
18580
|
+
return;
|
|
18581
|
+
}
|
|
18582
|
+
const key = `${themeCategory}:${context.primary.key}:${context.accent.key}:${selectedBackground.token}`;
|
|
18583
|
+
if (noValidStateRef.current.has(key)) {
|
|
18584
|
+
return;
|
|
18585
|
+
}
|
|
18586
|
+
noValidStateRef.current.add(key);
|
|
18587
|
+
emitAnalyticsEvent({
|
|
18588
|
+
name: "no_valid_combination_state",
|
|
18589
|
+
...buildAnalyticsContext({
|
|
18590
|
+
backgroundToken: selectedBackground.token
|
|
18591
|
+
})
|
|
18592
|
+
});
|
|
18593
|
+
}, [
|
|
18594
|
+
buildAnalyticsContext,
|
|
18595
|
+
context.accent.key,
|
|
18596
|
+
context.primary.key,
|
|
18597
|
+
emitAnalyticsEvent,
|
|
18598
|
+
selectedBackground,
|
|
18599
|
+
selectedBackgroundPairs.length,
|
|
18600
|
+
themeCategory
|
|
18601
|
+
]);
|
|
18602
|
+
React5.useEffect(() => {
|
|
18603
|
+
if (technicalDetailsViewedRef.current) {
|
|
18604
|
+
return;
|
|
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
|
+
);
|
|
16972
20017
|
const handleThemeCategoryChange = (nextThemeCategory) => {
|
|
16973
|
-
|
|
20018
|
+
const nextState = resolveSelectionState2(
|
|
16974
20019
|
nextThemeCategory,
|
|
16975
20020
|
primaryFamilyKey,
|
|
16976
20021
|
accentFamilyKey,
|
|
16977
20022
|
selectedBackgroundToken,
|
|
16978
|
-
|
|
20023
|
+
null
|
|
16979
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
|
+
});
|
|
16980
20034
|
};
|
|
16981
20035
|
const handlePrimaryColorChange = (nextPrimaryKey) => {
|
|
16982
20036
|
const nextAccentKey = nextPrimaryKey === accentFamilyKey ? getDefaultAccentFamilyKey(themeCategory, nextPrimaryKey) : accentFamilyKey;
|
|
16983
|
-
|
|
20037
|
+
const nextState = resolveSelectionState2(
|
|
16984
20038
|
themeCategory,
|
|
16985
20039
|
nextPrimaryKey,
|
|
16986
20040
|
nextAccentKey,
|
|
16987
20041
|
selectedBackgroundToken,
|
|
16988
|
-
|
|
20042
|
+
null
|
|
16989
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
|
+
});
|
|
16990
20053
|
};
|
|
16991
20054
|
const handleAccentColorChange = (nextAccentKey) => {
|
|
16992
20055
|
if (nextAccentKey === primaryFamilyKey) return;
|
|
16993
|
-
|
|
20056
|
+
const nextState = resolveSelectionState2(
|
|
16994
20057
|
themeCategory,
|
|
16995
20058
|
primaryFamilyKey,
|
|
16996
20059
|
nextAccentKey,
|
|
16997
20060
|
selectedBackgroundToken,
|
|
16998
|
-
|
|
20061
|
+
null
|
|
16999
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
|
+
});
|
|
17000
20072
|
};
|
|
17001
20073
|
const handleBackgroundChange = (nextSelectedBackgroundToken) => {
|
|
17002
|
-
const nextSelectedPairId =
|
|
17003
|
-
|
|
17004
|
-
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17008
|
-
|
|
17009
|
-
themeCategory
|
|
17010
|
-
|
|
17011
|
-
|
|
17012
|
-
|
|
17013
|
-
|
|
17014
|
-
|
|
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
|
+
}
|
|
17015
20099
|
};
|
|
17016
|
-
const handlePairChange = (nextSelectedPairId) => {
|
|
20100
|
+
const handlePairChange = (nextSelectedPairId, source) => {
|
|
17017
20101
|
if (!selectedBackground) return;
|
|
20102
|
+
const nextPair = selectedBackgroundPairs.find((pair) => pair.id === nextSelectedPairId) ?? null;
|
|
17018
20103
|
setSelectedPairId(nextSelectedPairId);
|
|
17019
|
-
updateUrlParams(
|
|
17020
|
-
|
|
17021
|
-
context
|
|
17022
|
-
context.
|
|
17023
|
-
selectedBackground.token,
|
|
17024
|
-
nextSelectedPairId
|
|
17025
|
-
|
|
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
|
+
}
|
|
17026
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);
|
|
20140
|
+
emitAnalyticsEvent({
|
|
20141
|
+
name: "no_valid_combination_state",
|
|
20142
|
+
...buildAnalyticsContext({
|
|
20143
|
+
backgroundToken: selectedBackground.token
|
|
20144
|
+
})
|
|
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
|
+
};
|
|
20199
|
+
}, [buildAnalyticsContext, emitAnalyticsEvent]);
|
|
17027
20200
|
if (!selectedBackground) {
|
|
17028
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
17029
|
-
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level:
|
|
17030
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17031
|
-
] })
|
|
20201
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
|
|
20202
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "No approved background tones available" }),
|
|
20203
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No approved tones are available for the current palette and colour selection." })
|
|
20204
|
+
] });
|
|
17032
20205
|
}
|
|
17033
|
-
|
|
17034
|
-
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17039
|
-
/* @__PURE__ */ jsxRuntime.
|
|
17040
|
-
|
|
17041
|
-
|
|
17042
|
-
|
|
20206
|
+
const compactControlsSummary = `${themeCategory === "brand" ? "Brand" : "Aboriginal"} palette, ${context.primary.label} primary, ${context.accent.label} accent, ${getPairingColorDisplayName4(
|
|
20207
|
+
selectedBackground
|
|
20208
|
+
)} background.`;
|
|
20209
|
+
const renderControlsPanel = (isOverlay = false) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20210
|
+
/* @__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: [
|
|
20211
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
|
|
20212
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
20213
|
+
!isFirstDrawerStep ? /* @__PURE__ */ jsxRuntime.jsxs(Button2, { variant: "ghost", color: "grey", size: "sm", onClick: goToPreviousDrawerStep, children: [
|
|
20214
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.west, { "data-slot": "icon", className: "size-5" }),
|
|
20215
|
+
"Back"
|
|
20216
|
+
] }) : null,
|
|
20217
|
+
isOverlay ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
20218
|
+
Button2,
|
|
20219
|
+
{
|
|
20220
|
+
variant: "ghost",
|
|
20221
|
+
color: "grey",
|
|
20222
|
+
size: "icon",
|
|
20223
|
+
onClick: () => setIsCompactControlsOpen(false),
|
|
20224
|
+
"aria-label": "Close configuration",
|
|
20225
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.close, { "data-slot": "icon", className: "size-5" })
|
|
20226
|
+
}
|
|
20227
|
+
) : null
|
|
20228
|
+
] })
|
|
20229
|
+
] }) }),
|
|
20230
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-grey-200 px-5 py-4", children: [
|
|
20231
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
20232
|
+
COLOR_PAIRING_TOOL_DRAWER_STEPS2.map((step, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
17043
20233
|
"button",
|
|
17044
20234
|
{
|
|
17045
20235
|
type: "button",
|
|
17046
|
-
"aria-
|
|
17047
|
-
"aria-
|
|
17048
|
-
onClick: () =>
|
|
17049
|
-
className:
|
|
17050
|
-
|
|
17051
|
-
|
|
17052
|
-
|
|
17053
|
-
|
|
20236
|
+
"aria-current": index === drawerStepIndex ? "step" : void 0,
|
|
20237
|
+
"aria-label": `${step.eyebrow}: ${step.title}`,
|
|
20238
|
+
onClick: () => goToDrawerStep(index),
|
|
20239
|
+
className: "flex-1 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
|
|
20240
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20241
|
+
"span",
|
|
20242
|
+
{
|
|
20243
|
+
className: cn(
|
|
20244
|
+
"block h-1.5 rounded-full transition-colors",
|
|
20245
|
+
index <= drawerStepIndex ? "bg-primary-800" : "bg-grey-200"
|
|
20246
|
+
)
|
|
20247
|
+
}
|
|
20248
|
+
)
|
|
17054
20249
|
},
|
|
17055
|
-
|
|
17056
|
-
)
|
|
17057
|
-
|
|
17058
|
-
|
|
17059
|
-
|
|
17060
|
-
{
|
|
17061
|
-
|
|
17062
|
-
|
|
17063
|
-
|
|
17064
|
-
|
|
17065
|
-
|
|
17066
|
-
|
|
17067
|
-
|
|
17068
|
-
|
|
17069
|
-
|
|
17070
|
-
|
|
20250
|
+
step.id
|
|
20251
|
+
)),
|
|
20252
|
+
/* @__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 })
|
|
20253
|
+
] }),
|
|
20254
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 space-y-2", children: [
|
|
20255
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: activeDrawerStep.title }),
|
|
20256
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: activeDrawerStep.description })
|
|
20257
|
+
] })
|
|
20258
|
+
] }),
|
|
20259
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20260
|
+
"div",
|
|
20261
|
+
{
|
|
20262
|
+
className: "flex h-full transition-transform duration-300 ease-out",
|
|
20263
|
+
style: { transform: `translateX(-${drawerStepIndex * 100}%)` },
|
|
20264
|
+
children: [
|
|
20265
|
+
/* @__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: [
|
|
20266
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
20267
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Palette" }),
|
|
20268
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: ["brand", "aboriginal"].map((palette) => {
|
|
20269
|
+
const isSelected = themeCategory === palette;
|
|
20270
|
+
const label = palette === "brand" ? "Brand palette" : "Aboriginal palette";
|
|
17071
20271
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17072
|
-
|
|
20272
|
+
SelectorButton2,
|
|
17073
20273
|
{
|
|
17074
|
-
|
|
17075
|
-
|
|
17076
|
-
|
|
20274
|
+
label,
|
|
20275
|
+
isSelected,
|
|
20276
|
+
onClick: () => handleThemeCategoryChange(palette)
|
|
20277
|
+
},
|
|
20278
|
+
palette
|
|
20279
|
+
);
|
|
20280
|
+
}) })
|
|
20281
|
+
] }),
|
|
20282
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
20283
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Primary colour family" }),
|
|
20284
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableFamilies.map((family) => {
|
|
20285
|
+
const label = getFamilySelectorLabel4(family, themeCategory, "primary colour");
|
|
20286
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20287
|
+
SelectorButton2,
|
|
20288
|
+
{
|
|
20289
|
+
label,
|
|
20290
|
+
isSelected: family.key === context.primary.key,
|
|
17077
20291
|
onClick: () => handlePrimaryColorChange(family.key),
|
|
17078
|
-
|
|
17079
|
-
"min-h-11 rounded-sm border px-2 py-2 text-center text-[0.8rem] leading-5 font-semibold transition-transform",
|
|
17080
|
-
isSelected ? "ring-2 ring-primary-700 ring-offset-2 ring-offset-grey-50/60" : "hover:-translate-y-px"
|
|
17081
|
-
),
|
|
17082
|
-
style: {
|
|
17083
|
-
backgroundColor: getFamilySwatchColor2(family, swatchTone),
|
|
17084
|
-
color: getReadableTextColor(swatchTone),
|
|
17085
|
-
borderColor: "rgba(0, 0, 0, 0.12)"
|
|
17086
|
-
},
|
|
17087
|
-
title: label,
|
|
17088
|
-
children: label
|
|
20292
|
+
swatch: getFamilySwatchColor4(family, 800)
|
|
17089
20293
|
},
|
|
17090
20294
|
family.key
|
|
17091
20295
|
);
|
|
17092
20296
|
}) })
|
|
17093
20297
|
] }),
|
|
17094
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
17095
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17096
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-
|
|
17097
|
-
const
|
|
17098
|
-
const isSelected = family.key === context.accent.key;
|
|
17099
|
-
const label = getFamilySelectorLabel2(family, themeCategory, "accent colour");
|
|
20298
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
20299
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Accent colour family" }),
|
|
20300
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableAccentFamilies.map((family) => {
|
|
20301
|
+
const label = getFamilySelectorLabel4(family, themeCategory, "accent colour");
|
|
17100
20302
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17101
|
-
|
|
20303
|
+
SelectorButton2,
|
|
17102
20304
|
{
|
|
17103
|
-
|
|
17104
|
-
|
|
17105
|
-
"aria-pressed": isSelected,
|
|
20305
|
+
label,
|
|
20306
|
+
isSelected: family.key === context.accent.key,
|
|
17106
20307
|
onClick: () => handleAccentColorChange(family.key),
|
|
17107
|
-
|
|
17108
|
-
"min-h-11 rounded-sm border px-2 py-2 text-center text-[0.8rem] leading-5 font-semibold transition-transform",
|
|
17109
|
-
isSelected ? "ring-2 ring-primary-700 ring-offset-2 ring-offset-grey-50/60" : "hover:-translate-y-px"
|
|
17110
|
-
),
|
|
17111
|
-
style: {
|
|
17112
|
-
backgroundColor: getFamilySwatchColor2(family, swatchTone),
|
|
17113
|
-
color: getReadableTextColor(swatchTone),
|
|
17114
|
-
borderColor: "rgba(0, 0, 0, 0.12)"
|
|
17115
|
-
},
|
|
17116
|
-
title: label,
|
|
17117
|
-
children: label
|
|
20308
|
+
swatch: getFamilySwatchColor4(family, 600)
|
|
17118
20309
|
},
|
|
17119
20310
|
family.key
|
|
17120
20311
|
);
|
|
17121
20312
|
}) })
|
|
20313
|
+
] }),
|
|
20314
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-grey-200 pt-4", children: [
|
|
20315
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: "Grey is always included" }),
|
|
20316
|
+
/* @__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." })
|
|
17122
20317
|
] })
|
|
17123
|
-
] })
|
|
17124
|
-
|
|
17125
|
-
|
|
17126
|
-
/* @__PURE__ */ jsxRuntime.jsx(SidebarStep, { step: 3, title: "Pick a background", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
17127
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
17128
|
-
"Selected:",
|
|
17129
|
-
" ",
|
|
17130
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: selectedBackground.token })
|
|
17131
|
-
] }),
|
|
17132
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-4 gap-2", children: context.backgrounds.map((background) => {
|
|
17133
|
-
const hasPairs = (context.pairsByBackground[background.token]?.length ?? 0) > 0;
|
|
17134
|
-
const isSelected = selectedBackground.token === background.token;
|
|
17135
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17136
|
-
"button",
|
|
20318
|
+
] }) }),
|
|
20319
|
+
/* @__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(
|
|
20320
|
+
"section",
|
|
17137
20321
|
{
|
|
17138
|
-
|
|
17139
|
-
|
|
17140
|
-
|
|
17141
|
-
|
|
17142
|
-
|
|
17143
|
-
|
|
17144
|
-
|
|
17145
|
-
|
|
17146
|
-
|
|
17147
|
-
|
|
17148
|
-
|
|
17149
|
-
|
|
17150
|
-
|
|
17151
|
-
|
|
17152
|
-
|
|
20322
|
+
className: cn("space-y-3", index > 0 && "border-t border-grey-200 pt-6"),
|
|
20323
|
+
children: [
|
|
20324
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
20325
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: [
|
|
20326
|
+
group.family.label,
|
|
20327
|
+
" backgrounds"
|
|
20328
|
+
] }),
|
|
20329
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: group.label })
|
|
20330
|
+
] }),
|
|
20331
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3", children: group.backgrounds.map((background) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
20332
|
+
BackgroundSwatchButton2,
|
|
20333
|
+
{
|
|
20334
|
+
background,
|
|
20335
|
+
hasPairs: (context.pairsByBackground[background.token]?.length ?? 0) > 0,
|
|
20336
|
+
isSelected: selectedBackground.token === background.token,
|
|
20337
|
+
onClick: () => handleBackgroundChange(background.token)
|
|
20338
|
+
},
|
|
20339
|
+
background.token
|
|
20340
|
+
)) })
|
|
20341
|
+
]
|
|
17153
20342
|
},
|
|
17154
|
-
|
|
17155
|
-
)
|
|
17156
|
-
|
|
17157
|
-
|
|
17158
|
-
|
|
17159
|
-
|
|
17160
|
-
|
|
17161
|
-
|
|
17162
|
-
|
|
17163
|
-
|
|
17164
|
-
|
|
17165
|
-
|
|
17166
|
-
|
|
20343
|
+
group.key
|
|
20344
|
+
)) }) }),
|
|
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
|
+
] }) })
|
|
20375
|
+
]
|
|
20376
|
+
}
|
|
20377
|
+
) }),
|
|
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: [
|
|
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 }),
|
|
20380
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2 sm:w-auto sm:flex-none", children: [
|
|
20381
|
+
isOverlay && isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
20382
|
+
Button2,
|
|
17167
20383
|
{
|
|
17168
|
-
|
|
17169
|
-
|
|
17170
|
-
|
|
20384
|
+
color: "primary",
|
|
20385
|
+
className: "w-full sm:w-auto sm:min-w-40",
|
|
20386
|
+
onClick: () => setIsCompactControlsOpen(false),
|
|
20387
|
+
children: "Review result"
|
|
17171
20388
|
}
|
|
17172
|
-
) :
|
|
17173
|
-
/* @__PURE__ */ jsxRuntime.
|
|
17174
|
-
|
|
17175
|
-
|
|
17176
|
-
|
|
17177
|
-
|
|
17178
|
-
|
|
17179
|
-
|
|
17180
|
-
|
|
17181
|
-
|
|
17182
|
-
|
|
17183
|
-
|
|
17184
|
-
|
|
17185
|
-
|
|
17186
|
-
|
|
20389
|
+
) : null,
|
|
20390
|
+
!isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsxs(Button2, { color: "primary", className: "w-full sm:w-auto", onClick: goToNextDrawerStep, children: [
|
|
20391
|
+
"Continue",
|
|
20392
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.east, { "data-slot": "icon", className: "size-5" })
|
|
20393
|
+
] }) : null
|
|
20394
|
+
] })
|
|
20395
|
+
] }) })
|
|
20396
|
+
] });
|
|
20397
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 xl:grid-cols-[minmax(18rem,24rem)_minmax(0,1fr)]", children: [
|
|
20398
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20399
|
+
"div",
|
|
20400
|
+
{
|
|
20401
|
+
"data-slot": "tool-sidebar",
|
|
20402
|
+
className: "hidden xl:sticky xl:top-[var(--tool-sidebar-top)] xl:block xl:self-start",
|
|
20403
|
+
style: desktopSidebarStyle,
|
|
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() })
|
|
20405
|
+
}
|
|
20406
|
+
),
|
|
20407
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "tool-results", className: "space-y-6", children: [
|
|
20408
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4 xl:hidden", children: [
|
|
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: [
|
|
20410
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
20411
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
|
|
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." }),
|
|
20413
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: compactControlsSummary })
|
|
20414
|
+
] }),
|
|
20415
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20416
|
+
Button2,
|
|
20417
|
+
{
|
|
20418
|
+
color: "primary",
|
|
20419
|
+
className: "w-full sm:w-auto",
|
|
20420
|
+
onClick: () => setIsCompactControlsOpen(true),
|
|
20421
|
+
children: [
|
|
20422
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.edit_square, { "data-slot": "icon", className: "size-5" }),
|
|
20423
|
+
"Open configuration"
|
|
20424
|
+
]
|
|
20425
|
+
}
|
|
20426
|
+
)
|
|
20427
|
+
] }) }),
|
|
20428
|
+
/* @__PURE__ */ jsxRuntime.jsx(Sheet, { open: isCompactControlsOpen, onOpenChange: setIsCompactControlsOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20429
|
+
SheetContent,
|
|
17187
20430
|
{
|
|
17188
|
-
|
|
17189
|
-
|
|
17190
|
-
|
|
17191
|
-
|
|
17192
|
-
|
|
17193
|
-
|
|
17194
|
-
|
|
17195
|
-
|
|
17196
|
-
|
|
20431
|
+
side: "left",
|
|
20432
|
+
showClose: false,
|
|
20433
|
+
className: "w-[30rem] max-w-[90vw] overflow-hidden p-0",
|
|
20434
|
+
children: [
|
|
20435
|
+
/* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Colour pairing configuration" }),
|
|
20436
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full flex-col bg-background", children: renderControlsPanel(true) })
|
|
20437
|
+
]
|
|
20438
|
+
}
|
|
20439
|
+
) })
|
|
17197
20440
|
] }),
|
|
17198
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
20441
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { ref: resultSectionRef, className: "space-y-6", "aria-label": "Current result", children: [
|
|
20442
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sr-only", "aria-live": "polite", children: liveAnnouncement }),
|
|
17199
20443
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17200
|
-
|
|
20444
|
+
CurrentResultCard2,
|
|
17201
20445
|
{
|
|
17202
|
-
|
|
17203
|
-
|
|
17204
|
-
|
|
20446
|
+
bestPair: bestRecommendedPair,
|
|
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,
|
|
20461
|
+
pair: previewPair,
|
|
20462
|
+
supportText: currentPairSupportText,
|
|
20463
|
+
selectedBackground
|
|
17205
20464
|
}
|
|
17206
|
-
)
|
|
17207
|
-
|
|
17208
|
-
|
|
20465
|
+
)
|
|
20466
|
+
] }),
|
|
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: [
|
|
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,
|
|
17209
20475
|
{
|
|
17210
|
-
|
|
17211
|
-
|
|
17212
|
-
|
|
17213
|
-
|
|
17214
|
-
|
|
17215
|
-
|
|
17216
|
-
|
|
17217
|
-
|
|
17218
|
-
|
|
17219
|
-
|
|
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: [
|
|
20510
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Technical colour values" }),
|
|
20511
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Token, tone, HEX, RGB, HSL, and OKLCH values for the current selection." })
|
|
20512
|
+
] }),
|
|
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: [
|
|
20514
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20515
|
+
TechnicalDetailsPanel2,
|
|
20516
|
+
{
|
|
20517
|
+
title: "Background values",
|
|
20518
|
+
color: selectedBackground,
|
|
20519
|
+
visibleFormats,
|
|
20520
|
+
copiedKey,
|
|
20521
|
+
onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
|
|
20522
|
+
}
|
|
20523
|
+
),
|
|
20524
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20525
|
+
TechnicalDetailsPanel2,
|
|
20526
|
+
{
|
|
20527
|
+
title: "Foreground values",
|
|
20528
|
+
color: detailForeground,
|
|
20529
|
+
visibleFormats,
|
|
20530
|
+
copiedKey,
|
|
20531
|
+
onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
|
|
20532
|
+
}
|
|
20533
|
+
)
|
|
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 })
|
|
17220
20566
|
] })
|
|
17221
20567
|
] })
|
|
17222
20568
|
] })
|
|
17223
20569
|
] });
|
|
17224
20570
|
}
|
|
17225
|
-
function
|
|
17226
|
-
|
|
20571
|
+
function ColorPairingToolV4({
|
|
20572
|
+
onAnalyticsEvent = () => {
|
|
20573
|
+
},
|
|
20574
|
+
visibleFormats = DEFAULT_VISIBLE_FORMATS4
|
|
17227
20575
|
} = {}) {
|
|
17228
20576
|
const normalizedVisibleFormats = [...new Set(visibleFormats)];
|
|
17229
|
-
return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20577
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolV4Loading, {}), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20578
|
+
ColorPairingToolV4Content,
|
|
20579
|
+
{
|
|
20580
|
+
onAnalyticsEvent,
|
|
20581
|
+
visibleFormats: normalizedVisibleFormats
|
|
20582
|
+
}
|
|
20583
|
+
) });
|
|
17230
20584
|
}
|
|
17231
20585
|
function ColorSwatches({ theme: theme2, format, viewMode }) {
|
|
17232
20586
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -18141,23 +21495,23 @@ var ComboChart = React5__namespace.default.forwardRef((props, forwardedRef) => {
|
|
|
18141
21495
|
});
|
|
18142
21496
|
ComboChart.displayName = "ComboChart";
|
|
18143
21497
|
function Dialog({ ...props }) {
|
|
18144
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21498
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Root, { "data-slot": "dialog", ...props });
|
|
18145
21499
|
}
|
|
18146
21500
|
function DialogTrigger({ ...props }) {
|
|
18147
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21501
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Trigger, { "data-slot": "dialog-trigger", ...props });
|
|
18148
21502
|
}
|
|
18149
21503
|
function DialogPortal({ ...props }) {
|
|
18150
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21504
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Portal, { "data-slot": "dialog-portal", ...props });
|
|
18151
21505
|
}
|
|
18152
21506
|
function DialogClose({ ...props }) {
|
|
18153
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21507
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Close, { "data-slot": "dialog-close", ...props });
|
|
18154
21508
|
}
|
|
18155
21509
|
function DialogOverlay({
|
|
18156
21510
|
className,
|
|
18157
21511
|
...props
|
|
18158
21512
|
}) {
|
|
18159
21513
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18160
|
-
|
|
21514
|
+
SheetPrimitive__namespace.Overlay,
|
|
18161
21515
|
{
|
|
18162
21516
|
"data-slot": "dialog-overlay",
|
|
18163
21517
|
className: cn(
|
|
@@ -18177,7 +21531,7 @@ function DialogContent({
|
|
|
18177
21531
|
return /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [
|
|
18178
21532
|
/* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
|
|
18179
21533
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
18180
|
-
|
|
21534
|
+
SheetPrimitive__namespace.Content,
|
|
18181
21535
|
{
|
|
18182
21536
|
"data-slot": "dialog-content",
|
|
18183
21537
|
className: cn(
|
|
@@ -18187,7 +21541,7 @@ function DialogContent({
|
|
|
18187
21541
|
...props,
|
|
18188
21542
|
children: [
|
|
18189
21543
|
children,
|
|
18190
|
-
showClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21544
|
+
showClose && /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Close, { className: "absolute top-1 right-1", asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button2, { variant: "ghost", size: "icon", children: [
|
|
18191
21545
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.close, { className: "size-6", "aria-hidden": "true" }),
|
|
18192
21546
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
|
|
18193
21547
|
] }) })
|
|
@@ -18218,7 +21572,7 @@ function DialogFooter({ className, ...props }) {
|
|
|
18218
21572
|
}
|
|
18219
21573
|
function DialogTitle({ className, ...props }) {
|
|
18220
21574
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18221
|
-
|
|
21575
|
+
SheetPrimitive__namespace.Title,
|
|
18222
21576
|
{
|
|
18223
21577
|
"data-slot": "dialog-title",
|
|
18224
21578
|
className: cn("text-lg leading-none font-semibold", className),
|
|
@@ -18231,7 +21585,7 @@ function DialogDescription({
|
|
|
18231
21585
|
...props
|
|
18232
21586
|
}) {
|
|
18233
21587
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18234
|
-
|
|
21588
|
+
SheetPrimitive__namespace.Description,
|
|
18235
21589
|
{
|
|
18236
21590
|
"data-slot": "dialog-description",
|
|
18237
21591
|
className: cn("text-sm text-muted-foreground", className),
|
|
@@ -19500,7 +22854,7 @@ function FieldLabel({
|
|
|
19500
22854
|
}
|
|
19501
22855
|
);
|
|
19502
22856
|
}
|
|
19503
|
-
function
|
|
22857
|
+
function Description5({
|
|
19504
22858
|
className,
|
|
19505
22859
|
...props
|
|
19506
22860
|
}) {
|
|
@@ -19852,7 +23206,7 @@ function FormatToggle({ format, setFormat }) {
|
|
|
19852
23206
|
|
|
19853
23207
|
// package.json
|
|
19854
23208
|
var package_default = {
|
|
19855
|
-
version: "1.
|
|
23209
|
+
version: "1.104.0"};
|
|
19856
23210
|
function Logo(props) {
|
|
19857
23211
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19858
23212
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "NSW Government" }),
|
|
@@ -21124,28 +24478,6 @@ function Loading() {
|
|
|
21124
24478
|
/* @__PURE__ */ jsxRuntime.jsx(Text, { children: "Loading..." })
|
|
21125
24479
|
] });
|
|
21126
24480
|
}
|
|
21127
|
-
function useSelectorHeight(selector = "header") {
|
|
21128
|
-
const [height, setHeight] = React5.useState(0);
|
|
21129
|
-
const elementRef = React5.useRef(null);
|
|
21130
|
-
const resizeObserverRef = React5.useRef(null);
|
|
21131
|
-
React5.useEffect(() => {
|
|
21132
|
-
const element = document.querySelector(selector);
|
|
21133
|
-
if (!element) return;
|
|
21134
|
-
elementRef.current = element;
|
|
21135
|
-
const resizeObserver = new ResizeObserver((entries) => {
|
|
21136
|
-
const entry = entries[0];
|
|
21137
|
-
const target = entry?.target ?? elementRef.current;
|
|
21138
|
-
if (!target) return;
|
|
21139
|
-
setHeight(target.offsetHeight);
|
|
21140
|
-
});
|
|
21141
|
-
resizeObserverRef.current = resizeObserver;
|
|
21142
|
-
resizeObserver.observe(element);
|
|
21143
|
-
return () => {
|
|
21144
|
-
resizeObserverRef.current?.disconnect();
|
|
21145
|
-
};
|
|
21146
|
-
}, [selector]);
|
|
21147
|
-
return height;
|
|
21148
|
-
}
|
|
21149
24481
|
function MainNavigation({ navigation }) {
|
|
21150
24482
|
const headerHeight = useSelectorHeight();
|
|
21151
24483
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -30910,110 +34242,6 @@ function ResizableHandle({
|
|
|
30910
34242
|
}
|
|
30911
34243
|
);
|
|
30912
34244
|
}
|
|
30913
|
-
function Sheet({ ...props }) {
|
|
30914
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Root, { "data-slot": "sheet", ...props });
|
|
30915
|
-
}
|
|
30916
|
-
function SheetTrigger({ ...props }) {
|
|
30917
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Trigger, { "data-slot": "sheet-trigger", ...props });
|
|
30918
|
-
}
|
|
30919
|
-
function SheetClose({ ...props }) {
|
|
30920
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Close, { "data-slot": "sheet-close", ...props });
|
|
30921
|
-
}
|
|
30922
|
-
function SheetPortal({ ...props }) {
|
|
30923
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Portal, { "data-slot": "sheet-portal", ...props });
|
|
30924
|
-
}
|
|
30925
|
-
function SheetOverlay({
|
|
30926
|
-
className,
|
|
30927
|
-
...props
|
|
30928
|
-
}) {
|
|
30929
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
30930
|
-
DialogPrimitive__namespace.Overlay,
|
|
30931
|
-
{
|
|
30932
|
-
"data-slot": "sheet-overlay",
|
|
30933
|
-
className: cn(
|
|
30934
|
-
"fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
|
|
30935
|
-
className
|
|
30936
|
-
),
|
|
30937
|
-
...props
|
|
30938
|
-
}
|
|
30939
|
-
);
|
|
30940
|
-
}
|
|
30941
|
-
function SheetContent({
|
|
30942
|
-
className,
|
|
30943
|
-
children,
|
|
30944
|
-
side = "right",
|
|
30945
|
-
showClose = true,
|
|
30946
|
-
...props
|
|
30947
|
-
}) {
|
|
30948
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(SheetPortal, { children: [
|
|
30949
|
-
/* @__PURE__ */ jsxRuntime.jsx(SheetOverlay, {}),
|
|
30950
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
30951
|
-
DialogPrimitive__namespace.Content,
|
|
30952
|
-
{
|
|
30953
|
-
"data-slot": "sheet-content",
|
|
30954
|
-
className: cn(
|
|
30955
|
-
"fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=closed]:animate-out data-[state=open]:duration-500 data-[state=open]:animate-in",
|
|
30956
|
-
side === "right" && "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
|
30957
|
-
side === "left" && "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
|
30958
|
-
side === "top" && "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
|
30959
|
-
side === "bottom" && "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
|
30960
|
-
className
|
|
30961
|
-
),
|
|
30962
|
-
...props,
|
|
30963
|
-
children: [
|
|
30964
|
-
children,
|
|
30965
|
-
showClose && /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Close, { "data-slot": "sheet-close", className: "absolute top-4 right-4", asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button2, { variant: "ghost", size: "icon", children: [
|
|
30966
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icons.close, { className: "size-6", "aria-hidden": "true" }),
|
|
30967
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
|
|
30968
|
-
] }) })
|
|
30969
|
-
]
|
|
30970
|
-
}
|
|
30971
|
-
)
|
|
30972
|
-
] });
|
|
30973
|
-
}
|
|
30974
|
-
function SheetHeader({ className, ...props }) {
|
|
30975
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
30976
|
-
"div",
|
|
30977
|
-
{
|
|
30978
|
-
"data-slot": "sheet-header",
|
|
30979
|
-
className: cn("flex flex-col gap-1.5 p-4", className),
|
|
30980
|
-
...props
|
|
30981
|
-
}
|
|
30982
|
-
);
|
|
30983
|
-
}
|
|
30984
|
-
function SheetFooter({ className, ...props }) {
|
|
30985
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
30986
|
-
"div",
|
|
30987
|
-
{
|
|
30988
|
-
"data-slot": "sheet-footer",
|
|
30989
|
-
className: cn("mt-auto flex flex-col gap-2 p-4", className),
|
|
30990
|
-
...props
|
|
30991
|
-
}
|
|
30992
|
-
);
|
|
30993
|
-
}
|
|
30994
|
-
function SheetTitle({ className, ...props }) {
|
|
30995
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
30996
|
-
DialogPrimitive__namespace.Title,
|
|
30997
|
-
{
|
|
30998
|
-
"data-slot": "sheet-title",
|
|
30999
|
-
className: cn("font-semibold text-foreground", className),
|
|
31000
|
-
...props
|
|
31001
|
-
}
|
|
31002
|
-
);
|
|
31003
|
-
}
|
|
31004
|
-
function SheetDescription({
|
|
31005
|
-
className,
|
|
31006
|
-
...props
|
|
31007
|
-
}) {
|
|
31008
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
31009
|
-
DialogPrimitive__namespace.Description,
|
|
31010
|
-
{
|
|
31011
|
-
"data-slot": "sheet-description",
|
|
31012
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
31013
|
-
...props
|
|
31014
|
-
}
|
|
31015
|
-
);
|
|
31016
|
-
}
|
|
31017
34245
|
function Skeleton({ className, ...props }) {
|
|
31018
34246
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
31019
34247
|
"div",
|
|
@@ -35741,13 +38969,36 @@ function getHeadings(slugify$1 = slugify.slugifyWithCounter()) {
|
|
|
35741
38969
|
});
|
|
35742
38970
|
return result;
|
|
35743
38971
|
}
|
|
35744
|
-
function
|
|
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
|
+
}
|
|
38981
|
+
function areHeadingTreesEqual(left, right) {
|
|
38982
|
+
if (left.length !== right.length) {
|
|
38983
|
+
return false;
|
|
38984
|
+
}
|
|
38985
|
+
return left.every((heading, index) => areHeadingNodesEqual(heading, right[index]));
|
|
38986
|
+
}
|
|
38987
|
+
function usePageHeadings(enabled = true) {
|
|
35745
38988
|
const [headings, setHeadings] = React5.useState([]);
|
|
35746
38989
|
const pathname = navigation.usePathname();
|
|
35747
38990
|
const observerRef = React5.useRef(null);
|
|
35748
38991
|
const observedElRef = React5.useRef(null);
|
|
35749
38992
|
React5.useEffect(() => {
|
|
35750
|
-
|
|
38993
|
+
if (!enabled) {
|
|
38994
|
+
return;
|
|
38995
|
+
}
|
|
38996
|
+
const update = () => {
|
|
38997
|
+
const nextHeadings = getHeadings();
|
|
38998
|
+
setHeadings(
|
|
38999
|
+
(currentHeadings) => areHeadingTreesEqual(currentHeadings, nextHeadings) ? currentHeadings : nextHeadings
|
|
39000
|
+
);
|
|
39001
|
+
};
|
|
35751
39002
|
const attachToCurrentArticle = () => {
|
|
35752
39003
|
const article = document.querySelector("article");
|
|
35753
39004
|
if (!article || observedElRef.current === article) return;
|
|
@@ -35794,16 +39045,8 @@ function usePageHeadings() {
|
|
|
35794
39045
|
observerRef.current = null;
|
|
35795
39046
|
observedElRef.current = null;
|
|
35796
39047
|
};
|
|
35797
|
-
}, [pathname]);
|
|
35798
|
-
return headings;
|
|
35799
|
-
}
|
|
35800
|
-
function useStickyOffset(extraPadding = 0) {
|
|
35801
|
-
const headerHeight = useSelectorHeight("#nsw-header");
|
|
35802
|
-
const navigationHeight = useSelectorHeight("#nsw-main-navigation");
|
|
35803
|
-
return React5.useMemo(() => {
|
|
35804
|
-
const total = headerHeight + navigationHeight + extraPadding;
|
|
35805
|
-
return total > 0 ? total : 0;
|
|
35806
|
-
}, [extraPadding, headerHeight, navigationHeight]);
|
|
39048
|
+
}, [enabled, pathname]);
|
|
39049
|
+
return enabled ? headings : [];
|
|
35807
39050
|
}
|
|
35808
39051
|
function createFormStore(opts) {
|
|
35809
39052
|
const { storageKey, initialFormData, initialFormStatus } = opts;
|
|
@@ -35945,6 +39188,8 @@ exports.CollapsibleTrigger = CollapsibleTrigger2;
|
|
|
35945
39188
|
exports.ColorCard = ColorCard;
|
|
35946
39189
|
exports.ColorPairingTool = ColorPairingTool;
|
|
35947
39190
|
exports.ColorPairingToolV2 = ColorPairingToolV2;
|
|
39191
|
+
exports.ColorPairingToolV3 = ColorPairingToolV3;
|
|
39192
|
+
exports.ColorPairingToolV4 = ColorPairingToolV4;
|
|
35948
39193
|
exports.ColorSwatches = ColorSwatches;
|
|
35949
39194
|
exports.ColourScale = ColourScale;
|
|
35950
39195
|
exports.ComboChart = ComboChart;
|
|
@@ -35992,7 +39237,7 @@ exports.DataTableFacetedFilter = DataTableFacetedFilter;
|
|
|
35992
39237
|
exports.DataTablePagination = DataTablePagination;
|
|
35993
39238
|
exports.DataTableToolbar = DataTableToolbar;
|
|
35994
39239
|
exports.DataTableViewOptions = DataTableViewOptions;
|
|
35995
|
-
exports.Description =
|
|
39240
|
+
exports.Description = Description5;
|
|
35996
39241
|
exports.DescriptionDetails = DescriptionDetails;
|
|
35997
39242
|
exports.DescriptionList = DescriptionList;
|
|
35998
39243
|
exports.DescriptionTerm = DescriptionTerm;
|