@alfadocs/ui-kit-debug 0.23.0 → 0.24.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/_chunks/{autocomplete-BxfabhZ8.js → autocomplete-C7xq06bP.js} +40 -40
- package/dist/_chunks/{autocomplete-BxfabhZ8.js.map → autocomplete-C7xq06bP.js.map} +1 -1
- package/dist/_chunks/editable-currency-cell-renderer-DJB5MxAI.js +2349 -0
- package/dist/_chunks/editable-currency-cell-renderer-DJB5MxAI.js.map +1 -0
- package/dist/_chunks/locale-picker-CYBhgSHR.js +575 -0
- package/dist/_chunks/locale-picker-CYBhgSHR.js.map +1 -0
- package/dist/_chunks/{patient-shell-DavGODt9.js → patient-shell-B164drIa.js} +40 -55
- package/dist/_chunks/patient-shell-B164drIa.js.map +1 -0
- package/dist/_chunks/settings-ca2Yi9R8.js +21 -0
- package/dist/_chunks/settings-ca2Yi9R8.js.map +1 -0
- package/dist/_chunks/sun-Eweh5fvi.js +50 -0
- package/dist/_chunks/sun-Eweh5fvi.js.map +1 -0
- package/dist/_chunks/{theme-toggle-BswYl0Yp.js → theme-toggle-FrotC2VI.js} +85 -127
- package/dist/_chunks/{theme-toggle-BswYl0Yp.js.map → theme-toggle-FrotC2VI.js.map} +1 -1
- package/dist/_chunks/use-locale-BkCIHujH.js +20 -0
- package/dist/_chunks/use-locale-BkCIHujH.js.map +1 -0
- package/dist/_chunks/use-scroll-to-first-error-BrK7dKB_.js +55 -0
- package/dist/_chunks/use-scroll-to-first-error-BrK7dKB_.js.map +1 -0
- package/dist/_chunks/{whatsapp-button-CtlLwM3M.js → whatsapp-button-DUjlWGKf.js} +26 -25
- package/dist/_chunks/{whatsapp-button-CtlLwM3M.js.map → whatsapp-button-DUjlWGKf.js.map} +1 -1
- package/dist/agent-catalog.json +59 -1
- package/dist/components/autocomplete/autocomplete.d.ts.map +1 -1
- package/dist/components/autocomplete/index.js +1 -1
- package/dist/components/data-table/data-table.d.ts.map +1 -1
- package/dist/components/data-table/filters/number-filter.d.ts +56 -0
- package/dist/components/data-table/filters/number-filter.d.ts.map +1 -0
- package/dist/components/data-table/filters/text-filter.d.ts +49 -0
- package/dist/components/data-table/filters/text-filter.d.ts.map +1 -0
- package/dist/components/data-table/index.d.ts +4 -0
- package/dist/components/data-table/index.d.ts.map +1 -1
- package/dist/components/data-table/index.js +25 -21
- package/dist/components/header-settings/index.js +205 -0
- package/dist/components/header-settings/index.js.map +1 -0
- package/dist/components/locale-picker/index.js +7 -0
- package/dist/components/locale-picker/index.js.map +1 -0
- package/dist/components/theme-toggle/index.js +1 -1
- package/dist/components/whatsapp-button/index.js +1 -1
- package/dist/components/whatsapp-button/whatsapp-button.d.ts +14 -1
- package/dist/components/whatsapp-button/whatsapp-button.d.ts.map +1 -1
- package/dist/fonts/Lexend-VF-latin-ext.woff2 +0 -0
- package/dist/fonts/Lexend-VF-latin.woff2 +0 -0
- package/dist/fonts/Lexend-VF-vietnamese.woff2 +0 -0
- package/dist/fonts/NotoSansArabic-VF-arabic.woff2 +0 -0
- package/dist/fonts/NotoSansDevanagari-VF-devanagari.woff2 +0 -0
- package/dist/hooks/index.js +29 -28
- package/dist/hooks/index.js.map +1 -1
- package/dist/i18n/config.js +2726 -134
- package/dist/i18n/config.js.map +1 -1
- package/dist/i18n/locales/ar.d.ts +147 -3
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/de.d.ts +147 -3
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/el.d.ts +147 -3
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/es.d.ts +147 -3
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/fr.d.ts +147 -3
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/hi.d.ts +147 -3
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/ja.d.ts +147 -3
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/nl.d.ts +147 -3
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.d.ts +149 -5
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pt.d.ts +147 -3
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/ro.d.ts +147 -3
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ru.d.ts +148 -4
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/sq.d.ts +147 -3
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sv.d.ts +147 -3
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/tr.d.ts +147 -3
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/zh.d.ts +147 -3
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/resources.d.ts +294 -6
- package/dist/i18n/resources.d.ts.map +1 -1
- package/dist/index.js +512 -507
- package/dist/index.js.map +1 -1
- package/dist/locales/ar.json +149 -5
- package/dist/locales/de.json +149 -5
- package/dist/locales/el.json +149 -5
- package/dist/locales/en.json +147 -3
- package/dist/locales/es.json +149 -5
- package/dist/locales/fr.json +149 -5
- package/dist/locales/hi.json +149 -5
- package/dist/locales/it.json +147 -3
- package/dist/locales/ja.json +149 -5
- package/dist/locales/nl.json +149 -5
- package/dist/locales/pl.json +151 -7
- package/dist/locales/pt.json +149 -5
- package/dist/locales/ro.json +149 -5
- package/dist/locales/ru.json +150 -6
- package/dist/locales/sq.json +149 -5
- package/dist/locales/sv.json +149 -5
- package/dist/locales/tr.json +149 -5
- package/dist/locales/zh.json +149 -5
- package/dist/patterns/patient-shell/index.js +1 -1
- package/dist/tokens.css +2 -2
- package/package.json +10 -1
- package/dist/_chunks/editable-currency-cell-renderer-1t42gENX.js +0 -1972
- package/dist/_chunks/editable-currency-cell-renderer-1t42gENX.js.map +0 -1
- package/dist/_chunks/patient-shell-DavGODt9.js.map +0 -1
- package/dist/_chunks/use-locale-C5rS3Xon.js +0 -71
- package/dist/_chunks/use-locale-C5rS3Xon.js.map +0 -1
|
@@ -1,57 +1,15 @@
|
|
|
1
|
-
import { jsx as t, jsxs as m, Fragment as
|
|
2
|
-
import { forwardRef as N, useRef as
|
|
1
|
+
import { jsx as t, jsxs as m, Fragment as V } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as N, useRef as k, useImperativeHandle as M, useMemo as _, useCallback as S } from "react";
|
|
3
3
|
import { c as P } from "./index-D2ZczOXr.js";
|
|
4
4
|
import { useTranslation as g } from "react-i18next";
|
|
5
|
-
import { I as
|
|
6
|
-
import { I as
|
|
7
|
-
import { S as
|
|
5
|
+
import { I as y } from "./icon-button-C4CGcYuz.js";
|
|
6
|
+
import { I as K } from "./icon-button-group-DeV3FpNY.js";
|
|
7
|
+
import { S as x } from "./switch-D916VW86.js";
|
|
8
8
|
import { D as o } from "./dropdown-menu-DZxwF23X.js";
|
|
9
|
-
import { u as
|
|
10
|
-
import { u as
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
* @license lucide-react v1.8.0 - ISC
|
|
14
|
-
*
|
|
15
|
-
* This source code is licensed under the ISC license.
|
|
16
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
17
|
-
*/
|
|
18
|
-
const D = [
|
|
19
|
-
["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
|
|
20
|
-
["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
|
|
21
|
-
["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
|
|
22
|
-
], _ = C("monitor", D);
|
|
23
|
-
/**
|
|
24
|
-
* @license lucide-react v1.8.0 - ISC
|
|
25
|
-
*
|
|
26
|
-
* This source code is licensed under the ISC license.
|
|
27
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
28
|
-
*/
|
|
29
|
-
const H = [
|
|
30
|
-
[
|
|
31
|
-
"path",
|
|
32
|
-
{
|
|
33
|
-
d: "M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",
|
|
34
|
-
key: "kfwtm"
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
], f = C("moon", H);
|
|
38
|
-
/**
|
|
39
|
-
* @license lucide-react v1.8.0 - ISC
|
|
40
|
-
*
|
|
41
|
-
* This source code is licensed under the ISC license.
|
|
42
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
43
|
-
*/
|
|
44
|
-
const q = [
|
|
45
|
-
["circle", { cx: "12", cy: "12", r: "4", key: "4exip2" }],
|
|
46
|
-
["path", { d: "M12 2v2", key: "tus03m" }],
|
|
47
|
-
["path", { d: "M12 20v2", key: "1lh1kg" }],
|
|
48
|
-
["path", { d: "m4.93 4.93 1.41 1.41", key: "149t6j" }],
|
|
49
|
-
["path", { d: "m17.66 17.66 1.41 1.41", key: "ptbguv" }],
|
|
50
|
-
["path", { d: "M2 12h2", key: "1t8f8n" }],
|
|
51
|
-
["path", { d: "M20 12h2", key: "1q8mjw" }],
|
|
52
|
-
["path", { d: "m6.34 17.66-1.41 1.41", key: "1m8zz5" }],
|
|
53
|
-
["path", { d: "m19.07 4.93-1.41 1.41", key: "1shlcs" }]
|
|
54
|
-
], k = C("sun", q), B = {
|
|
9
|
+
import { u as z } from "./use-theme-B1cwAXJR.js";
|
|
10
|
+
import { u as D } from "./registry-C9nwlNyL.js";
|
|
11
|
+
import { M as v, S as C, a as w } from "./sun-Eweh5fvi.js";
|
|
12
|
+
const H = {
|
|
55
13
|
id: "theme-toggle",
|
|
56
14
|
capabilities: ["view_change"],
|
|
57
15
|
state: {
|
|
@@ -110,30 +68,30 @@ const q = [
|
|
|
110
68
|
},
|
|
111
69
|
defaultVariants: { variant: "menu" }
|
|
112
70
|
});
|
|
113
|
-
function
|
|
71
|
+
function L(e) {
|
|
114
72
|
const {
|
|
115
73
|
theme: n,
|
|
116
|
-
accessibility:
|
|
117
|
-
onThemeChange:
|
|
74
|
+
accessibility: s,
|
|
75
|
+
onThemeChange: c,
|
|
118
76
|
onAccessibilityChange: a
|
|
119
|
-
} = e, i =
|
|
77
|
+
} = e, i = z(), u = n ?? i.theme, p = s ?? i.accessibility, l = i.setTheme, T = i.setAccessibility, d = S(
|
|
120
78
|
(r) => {
|
|
121
|
-
if (
|
|
122
|
-
|
|
79
|
+
if (c) {
|
|
80
|
+
c(r);
|
|
123
81
|
return;
|
|
124
82
|
}
|
|
125
83
|
l(r);
|
|
126
84
|
},
|
|
127
|
-
[
|
|
85
|
+
[c, l]
|
|
128
86
|
), h = S(
|
|
129
87
|
(r) => {
|
|
130
88
|
if (a) {
|
|
131
89
|
a(r);
|
|
132
90
|
return;
|
|
133
91
|
}
|
|
134
|
-
|
|
92
|
+
T(r);
|
|
135
93
|
},
|
|
136
|
-
[a,
|
|
94
|
+
[a, T]
|
|
137
95
|
);
|
|
138
96
|
return {
|
|
139
97
|
theme: u,
|
|
@@ -146,40 +104,40 @@ function G(e) {
|
|
|
146
104
|
function I({
|
|
147
105
|
value: e,
|
|
148
106
|
onValueChange: n,
|
|
149
|
-
ariaLabel:
|
|
150
|
-
size:
|
|
107
|
+
ariaLabel: s,
|
|
108
|
+
size: c = "md"
|
|
151
109
|
}) {
|
|
152
110
|
const { t: a } = g();
|
|
153
111
|
return /* @__PURE__ */ m(
|
|
154
|
-
|
|
112
|
+
K,
|
|
155
113
|
{
|
|
156
|
-
"aria-label":
|
|
114
|
+
"aria-label": s,
|
|
157
115
|
role: "radiogroup",
|
|
158
116
|
mode: "toggle-single",
|
|
159
|
-
size:
|
|
117
|
+
size: c,
|
|
160
118
|
value: e,
|
|
161
119
|
onValueChange: (i) => n(i),
|
|
162
120
|
children: [
|
|
163
121
|
/* @__PURE__ */ t(
|
|
164
|
-
|
|
122
|
+
y,
|
|
165
123
|
{
|
|
166
|
-
icon: /* @__PURE__ */ t(
|
|
124
|
+
icon: /* @__PURE__ */ t(C, { "aria-hidden": !0 }),
|
|
167
125
|
"aria-label": a("navigation.themeToggle.appearance.light"),
|
|
168
126
|
value: "light"
|
|
169
127
|
}
|
|
170
128
|
),
|
|
171
129
|
/* @__PURE__ */ t(
|
|
172
|
-
|
|
130
|
+
y,
|
|
173
131
|
{
|
|
174
|
-
icon: /* @__PURE__ */ t(
|
|
132
|
+
icon: /* @__PURE__ */ t(v, { "aria-hidden": !0 }),
|
|
175
133
|
"aria-label": a("navigation.themeToggle.appearance.dark"),
|
|
176
134
|
value: "dark"
|
|
177
135
|
}
|
|
178
136
|
),
|
|
179
137
|
/* @__PURE__ */ t(
|
|
180
|
-
|
|
138
|
+
y,
|
|
181
139
|
{
|
|
182
|
-
icon: /* @__PURE__ */ t(
|
|
140
|
+
icon: /* @__PURE__ */ t(w, { "aria-hidden": !0 }),
|
|
183
141
|
"aria-label": a("navigation.themeToggle.appearance.system"),
|
|
184
142
|
value: "system"
|
|
185
143
|
}
|
|
@@ -188,42 +146,42 @@ function I({
|
|
|
188
146
|
}
|
|
189
147
|
);
|
|
190
148
|
}
|
|
191
|
-
function
|
|
149
|
+
function j({
|
|
192
150
|
value: e,
|
|
193
151
|
onValueChange: n,
|
|
194
|
-
size:
|
|
152
|
+
size: s = "md"
|
|
195
153
|
}) {
|
|
196
|
-
const { t:
|
|
154
|
+
const { t: c } = g(), a = e === "accessible";
|
|
197
155
|
return /* @__PURE__ */ t(
|
|
198
|
-
|
|
156
|
+
x,
|
|
199
157
|
{
|
|
200
|
-
label:
|
|
158
|
+
label: c("navigation.themeToggle.accessibility.label"),
|
|
201
159
|
labelSide: "start",
|
|
202
|
-
size:
|
|
160
|
+
size: s,
|
|
203
161
|
checked: a,
|
|
204
162
|
onCheckedChange: (i) => n(i ? "accessible" : "default")
|
|
205
163
|
}
|
|
206
164
|
);
|
|
207
165
|
}
|
|
208
|
-
function
|
|
166
|
+
function B({
|
|
209
167
|
state: e,
|
|
210
168
|
className: n,
|
|
211
|
-
rest:
|
|
212
|
-
forwardedRef:
|
|
169
|
+
rest: s,
|
|
170
|
+
forwardedRef: c,
|
|
213
171
|
showAccessibility: a
|
|
214
172
|
}) {
|
|
215
|
-
const { t: i } = g(), u = e.resolvedTheme === "dark" || e.resolvedTheme === "dark-accessible" ? /* @__PURE__ */ t(
|
|
173
|
+
const { t: i } = g(), u = e.resolvedTheme === "dark" || e.resolvedTheme === "dark-accessible" ? /* @__PURE__ */ t(v, { "aria-hidden": !0 }) : /* @__PURE__ */ t(C, { "aria-hidden": !0 }), p = e.accessibility === "accessible";
|
|
216
174
|
return /* @__PURE__ */ t(
|
|
217
175
|
"div",
|
|
218
176
|
{
|
|
219
|
-
ref:
|
|
177
|
+
ref: c,
|
|
220
178
|
"data-component": "theme-toggle",
|
|
221
|
-
"data-component-id":
|
|
179
|
+
"data-component-id": s.id,
|
|
222
180
|
className: A({ variant: "menu", className: n }),
|
|
223
|
-
...
|
|
181
|
+
...s,
|
|
224
182
|
children: /* @__PURE__ */ m(o.Root, { children: [
|
|
225
183
|
/* @__PURE__ */ t(o.Trigger, { asChild: !0, children: /* @__PURE__ */ t(
|
|
226
|
-
|
|
184
|
+
y,
|
|
227
185
|
{
|
|
228
186
|
icon: u,
|
|
229
187
|
"aria-label": i("navigation.themeToggle.trigger")
|
|
@@ -238,21 +196,21 @@ function F({
|
|
|
238
196
|
onValueChange: (l) => e.setTheme(l),
|
|
239
197
|
children: [
|
|
240
198
|
/* @__PURE__ */ m(o.RadioItem, { value: "light", children: [
|
|
241
|
-
/* @__PURE__ */ t(
|
|
199
|
+
/* @__PURE__ */ t(C, { "aria-hidden": !0, className: "ds:size-4" }),
|
|
242
200
|
i("navigation.themeToggle.appearance.light")
|
|
243
201
|
] }),
|
|
244
202
|
/* @__PURE__ */ m(o.RadioItem, { value: "dark", children: [
|
|
245
|
-
/* @__PURE__ */ t(
|
|
203
|
+
/* @__PURE__ */ t(v, { "aria-hidden": !0, className: "ds:size-4" }),
|
|
246
204
|
i("navigation.themeToggle.appearance.dark")
|
|
247
205
|
] }),
|
|
248
206
|
/* @__PURE__ */ m(o.RadioItem, { value: "system", children: [
|
|
249
|
-
/* @__PURE__ */ t(
|
|
207
|
+
/* @__PURE__ */ t(w, { "aria-hidden": !0, className: "ds:size-4" }),
|
|
250
208
|
i("navigation.themeToggle.appearance.system")
|
|
251
209
|
] })
|
|
252
210
|
]
|
|
253
211
|
}
|
|
254
212
|
),
|
|
255
|
-
a ? /* @__PURE__ */ m(
|
|
213
|
+
a ? /* @__PURE__ */ m(V, { children: [
|
|
256
214
|
/* @__PURE__ */ t(o.Separator, {}),
|
|
257
215
|
/* @__PURE__ */ t(
|
|
258
216
|
o.CheckboxItem,
|
|
@@ -269,21 +227,21 @@ function F({
|
|
|
269
227
|
}
|
|
270
228
|
);
|
|
271
229
|
}
|
|
272
|
-
function
|
|
230
|
+
function G({
|
|
273
231
|
state: e,
|
|
274
232
|
className: n,
|
|
275
|
-
rest:
|
|
276
|
-
forwardedRef:
|
|
233
|
+
rest: s,
|
|
234
|
+
forwardedRef: c
|
|
277
235
|
}) {
|
|
278
236
|
const { t: a } = g();
|
|
279
237
|
return /* @__PURE__ */ t(
|
|
280
238
|
"div",
|
|
281
239
|
{
|
|
282
|
-
ref:
|
|
240
|
+
ref: c,
|
|
283
241
|
"data-component": "theme-toggle",
|
|
284
|
-
"data-component-id":
|
|
242
|
+
"data-component-id": s.id,
|
|
285
243
|
className: A({ variant: "compact", className: n }),
|
|
286
|
-
...
|
|
244
|
+
...s,
|
|
287
245
|
children: /* @__PURE__ */ t(
|
|
288
246
|
I,
|
|
289
247
|
{
|
|
@@ -295,22 +253,22 @@ function O({
|
|
|
295
253
|
}
|
|
296
254
|
);
|
|
297
255
|
}
|
|
298
|
-
function
|
|
256
|
+
function F({
|
|
299
257
|
state: e,
|
|
300
258
|
className: n,
|
|
301
|
-
rest:
|
|
302
|
-
forwardedRef:
|
|
259
|
+
rest: s,
|
|
260
|
+
forwardedRef: c,
|
|
303
261
|
showAccessibility: a
|
|
304
262
|
}) {
|
|
305
263
|
const { t: i } = g();
|
|
306
264
|
return /* @__PURE__ */ m(
|
|
307
265
|
"div",
|
|
308
266
|
{
|
|
309
|
-
ref:
|
|
267
|
+
ref: c,
|
|
310
268
|
"data-component": "theme-toggle",
|
|
311
|
-
"data-component-id":
|
|
269
|
+
"data-component-id": s.id,
|
|
312
270
|
className: A({ variant: "split", className: n }),
|
|
313
|
-
...
|
|
271
|
+
...s,
|
|
314
272
|
children: [
|
|
315
273
|
/* @__PURE__ */ t(
|
|
316
274
|
I,
|
|
@@ -321,7 +279,7 @@ function E({
|
|
|
321
279
|
}
|
|
322
280
|
),
|
|
323
281
|
a ? /* @__PURE__ */ t(
|
|
324
|
-
|
|
282
|
+
j,
|
|
325
283
|
{
|
|
326
284
|
value: e.accessibility,
|
|
327
285
|
onValueChange: e.setAccessibility
|
|
@@ -331,11 +289,11 @@ function E({
|
|
|
331
289
|
}
|
|
332
290
|
);
|
|
333
291
|
}
|
|
334
|
-
const
|
|
292
|
+
const O = N(
|
|
335
293
|
(e, n) => {
|
|
336
294
|
const {
|
|
337
|
-
variant:
|
|
338
|
-
showAccessibility:
|
|
295
|
+
variant: s = "menu",
|
|
296
|
+
showAccessibility: c = !0,
|
|
339
297
|
className: a,
|
|
340
298
|
id: i,
|
|
341
299
|
// Strip controlled props from the spread — they are read by the
|
|
@@ -343,54 +301,54 @@ const J = N(
|
|
|
343
301
|
theme: u,
|
|
344
302
|
accessibility: p,
|
|
345
303
|
onThemeChange: l,
|
|
346
|
-
onAccessibilityChange:
|
|
304
|
+
onAccessibilityChange: T,
|
|
347
305
|
...d
|
|
348
|
-
} = e, h =
|
|
306
|
+
} = e, h = L(e), r = k(h);
|
|
349
307
|
r.current = h;
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
const
|
|
308
|
+
const b = k(null);
|
|
309
|
+
M(n, () => b.current, []);
|
|
310
|
+
const R = _(
|
|
353
311
|
() => ({
|
|
354
312
|
getCurrentTheme: () => r.current.theme,
|
|
355
313
|
getCurrentAccessibility: () => r.current.accessibility,
|
|
356
|
-
setTheme: (
|
|
357
|
-
setAccessibility: (
|
|
314
|
+
setTheme: (f) => r.current.setTheme(f),
|
|
315
|
+
setAccessibility: (f) => r.current.setAccessibility(f)
|
|
358
316
|
}),
|
|
359
317
|
[]
|
|
360
318
|
);
|
|
361
|
-
return
|
|
362
|
-
|
|
319
|
+
return D(H, R, i), s === "compact" ? /* @__PURE__ */ t(
|
|
320
|
+
G,
|
|
363
321
|
{
|
|
364
322
|
state: h,
|
|
365
323
|
className: a,
|
|
366
324
|
rest: d,
|
|
367
|
-
forwardedRef:
|
|
368
|
-
showAccessibility:
|
|
325
|
+
forwardedRef: b,
|
|
326
|
+
showAccessibility: c
|
|
369
327
|
}
|
|
370
|
-
) :
|
|
371
|
-
|
|
328
|
+
) : s === "split" ? /* @__PURE__ */ t(
|
|
329
|
+
F,
|
|
372
330
|
{
|
|
373
331
|
state: h,
|
|
374
332
|
className: a,
|
|
375
333
|
rest: d,
|
|
376
|
-
forwardedRef:
|
|
377
|
-
showAccessibility:
|
|
334
|
+
forwardedRef: b,
|
|
335
|
+
showAccessibility: c
|
|
378
336
|
}
|
|
379
337
|
) : /* @__PURE__ */ t(
|
|
380
|
-
|
|
338
|
+
B,
|
|
381
339
|
{
|
|
382
340
|
state: h,
|
|
383
341
|
className: a,
|
|
384
342
|
rest: d,
|
|
385
|
-
forwardedRef:
|
|
386
|
-
showAccessibility:
|
|
343
|
+
forwardedRef: b,
|
|
344
|
+
showAccessibility: c
|
|
387
345
|
}
|
|
388
346
|
);
|
|
389
347
|
}
|
|
390
348
|
);
|
|
391
|
-
|
|
349
|
+
O.displayName = "ThemeToggle";
|
|
392
350
|
export {
|
|
393
|
-
|
|
394
|
-
|
|
351
|
+
O as T,
|
|
352
|
+
H as t
|
|
395
353
|
};
|
|
396
|
-
//# sourceMappingURL=theme-toggle-
|
|
354
|
+
//# sourceMappingURL=theme-toggle-FrotC2VI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-toggle-BswYl0Yp.js","sources":["../../node_modules/lucide-react/dist/esm/icons/monitor.js","../../node_modules/lucide-react/dist/esm/icons/moon.js","../../node_modules/lucide-react/dist/esm/icons/sun.js","../../src/components/theme-toggle/theme-toggle.agent.ts","../../src/components/theme-toggle/theme-toggle.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"20\", height: \"14\", x: \"2\", y: \"3\", rx: \"2\", key: \"48i651\" }],\n [\"line\", { x1: \"8\", x2: \"16\", y1: \"21\", y2: \"21\", key: \"1svkeh\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"17\", y2: \"21\", key: \"vw1qmm\" }]\n];\nconst Monitor = createLucideIcon(\"monitor\", __iconNode);\n\nexport { __iconNode, Monitor as default };\n//# sourceMappingURL=monitor.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\",\n key: \"kfwtm\"\n }\n ]\n];\nconst Moon = createLucideIcon(\"moon\", __iconNode);\n\nexport { __iconNode, Moon as default };\n//# sourceMappingURL=moon.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"4\", key: \"4exip2\" }],\n [\"path\", { d: \"M12 2v2\", key: \"tus03m\" }],\n [\"path\", { d: \"M12 20v2\", key: \"1lh1kg\" }],\n [\"path\", { d: \"m4.93 4.93 1.41 1.41\", key: \"149t6j\" }],\n [\"path\", { d: \"m17.66 17.66 1.41 1.41\", key: \"ptbguv\" }],\n [\"path\", { d: \"M2 12h2\", key: \"1t8f8n\" }],\n [\"path\", { d: \"M20 12h2\", key: \"1q8mjw\" }],\n [\"path\", { d: \"m6.34 17.66-1.41 1.41\", key: \"1m8zz5\" }],\n [\"path\", { d: \"m19.07 4.93-1.41 1.41\", key: \"1shlcs\" }]\n];\nconst Sun = createLucideIcon(\"sun\", __iconNode);\n\nexport { __iconNode, Sun as default };\n//# sourceMappingURL=sun.js.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — ThemeToggle. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { ThemeToggleHandle } from './theme-toggle';\n\nexport const themeToggleAgent: AgentAdapter<ThemeToggleHandle> = {\n id: 'theme-toggle',\n capabilities: ['view_change'],\n state: {\n currentTheme: {\n type: 'ThemePreference',\n descriptionKey: 'ui.agent.themeToggle.state.currentTheme',\n description: 'Active theme preference: light, dark, or system.',\n read: (handle) => handle.getCurrentTheme(),\n },\n currentAccessibility: {\n type: 'AccessibilityPreference',\n descriptionKey: 'ui.agent.themeToggle.state.currentAccessibility',\n description: 'Active accessibility preference: default or accessible.',\n read: (handle) => handle.getCurrentAccessibility(),\n },\n },\n actions: {\n set_theme: {\n safety: 'write',\n argsType: '{ theme: \"light\" | \"dark\" | \"system\" }',\n descriptionKey: 'ui.agent.themeToggle.actions.setTheme',\n description: 'Switch the theme preference.',\n invoke: (handle, args: { theme: 'light' | 'dark' | 'system' }) => {\n handle.setTheme(args.theme);\n },\n },\n set_accessibility: {\n safety: 'write',\n argsType: '{ accessibility: \"default\" | \"accessible\" }',\n descriptionKey: 'ui.agent.themeToggle.actions.setAccessibility',\n description: 'Switch the accessibility preference.',\n invoke: (handle, args: { accessibility: 'default' | 'accessible' }) => {\n handle.setAccessibility(args.accessibility);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'theme-toggle',\n description: 'Marks the ThemeToggle wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n type HTMLAttributes,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Monitor, Moon, Sun } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { IconButtonGroup } from '../icon-button-group/icon-button-group';\nimport { Switch } from '../switch/switch';\nimport { DropdownMenu } from '../dropdown-menu/dropdown-menu';\nimport {\n useTheme,\n type AccessibilityPreference,\n type ThemePreference,\n type UseThemeReturn,\n} from '../../hooks';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { themeToggleAgent } from './theme-toggle.agent';\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst wrapperVariants = cva('ds:inline-flex ds:items-center', {\n variants: {\n variant: {\n menu: '',\n compact: '',\n split: 'ds:gap-[var(--spacing-md)]',\n },\n },\n defaultVariants: { variant: 'menu' },\n});\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport type ThemeToggleVariant = 'menu' | 'compact' | 'split';\n\ninterface ThemeToggleBaseProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onChange'>,\n VariantProps<typeof wrapperVariants> {\n /**\n * Visual form factor.\n * - `menu` (default) — single trigger that opens a dropdown with both\n * Appearance and Accessibility controls. Best for headers / nav rails.\n * - `compact` — segmented Appearance control only. Use when accessibility\n * lives on a separate settings surface.\n * - `split` — segmented Appearance control plus an inline Accessibility\n * switch. Best for full-width settings panels.\n */\n variant?: ThemeToggleVariant;\n /** Hide the accessibility control. Ignored on `compact`, which never renders it. */\n showAccessibility?: boolean;\n /**\n * Controlled escape hatch — when omitted the component reads/writes\n * `useTheme()` directly so it can drop into any header with no wiring.\n * Pass all four to opt into controlled mode.\n */\n theme?: ThemePreference;\n accessibility?: AccessibilityPreference;\n onThemeChange?: (next: ThemePreference) => void;\n onAccessibilityChange?: (next: AccessibilityPreference) => void;\n}\n\nexport type ThemeToggleProps = ThemeToggleBaseProps;\n\n/** Curated imperative handle for agent / external automation. */\nexport interface ThemeToggleHandle {\n getCurrentTheme: () => ThemePreference;\n getCurrentAccessibility: () => AccessibilityPreference;\n setTheme: (next: ThemePreference) => void;\n setAccessibility: (next: AccessibilityPreference) => void;\n}\n\n/* ------------------------------------------------------------------ */\n/* Hook adapter */\n/* ------------------------------------------------------------------ */\n\n/**\n * Resolves controlled props against the store. When the consumer passes\n * `theme` / `onThemeChange` (etc.) we honour those; otherwise we fall\n * through to the singleton `useTheme()` hook so a bare `<ThemeToggle />`\n * works with zero wiring.\n */\nfunction useResolvedTheme(props: ThemeToggleBaseProps): UseThemeReturn {\n const {\n theme: themeProp,\n accessibility: accessibilityProp,\n onThemeChange,\n onAccessibilityChange,\n } = props;\n const store = useTheme();\n const theme = themeProp ?? store.theme;\n const accessibility = accessibilityProp ?? store.accessibility;\n\n const storeSetTheme = store.setTheme;\n const storeSetAccessibility = store.setAccessibility;\n\n const setTheme = useCallback(\n (next: ThemePreference) => {\n if (onThemeChange) {\n onThemeChange(next);\n return;\n }\n storeSetTheme(next);\n },\n [onThemeChange, storeSetTheme],\n );\n\n const setAccessibility = useCallback(\n (next: AccessibilityPreference) => {\n if (onAccessibilityChange) {\n onAccessibilityChange(next);\n return;\n }\n storeSetAccessibility(next);\n },\n [onAccessibilityChange, storeSetAccessibility],\n );\n\n return {\n theme,\n accessibility,\n resolvedTheme: store.resolvedTheme,\n setTheme,\n setAccessibility,\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Sub-pieces */\n/* ------------------------------------------------------------------ */\n\ninterface AppearanceSegmentProps {\n value: ThemePreference;\n onValueChange: (next: ThemePreference) => void;\n ariaLabel: string;\n size?: 'sm' | 'md' | 'lg';\n}\n\nfunction AppearanceSegment({\n value,\n onValueChange,\n ariaLabel,\n size = 'md',\n}: AppearanceSegmentProps) {\n const { t } = useTranslation();\n return (\n <IconButtonGroup\n aria-label={ariaLabel}\n role=\"radiogroup\"\n mode=\"toggle-single\"\n size={size}\n value={value}\n onValueChange={(next) => onValueChange(next as ThemePreference)}\n >\n <IconButton\n icon={<Sun aria-hidden />}\n aria-label={t('navigation.themeToggle.appearance.light')}\n value=\"light\"\n />\n <IconButton\n icon={<Moon aria-hidden />}\n aria-label={t('navigation.themeToggle.appearance.dark')}\n value=\"dark\"\n />\n <IconButton\n icon={<Monitor aria-hidden />}\n aria-label={t('navigation.themeToggle.appearance.system')}\n value=\"system\"\n />\n </IconButtonGroup>\n );\n}\n\ninterface AccessibilitySwitchProps {\n value: AccessibilityPreference;\n onValueChange: (next: AccessibilityPreference) => void;\n size?: 'sm' | 'md' | 'lg';\n}\n\nfunction AccessibilitySwitch({\n value,\n onValueChange,\n size = 'md',\n}: AccessibilitySwitchProps) {\n const { t } = useTranslation();\n // 'system' is treated as \"off\" visually — the OS preference flows through\n // automatically. Flipping the switch on creates an explicit override.\n const checked = value === 'accessible';\n return (\n <Switch\n label={t('navigation.themeToggle.accessibility.label')}\n labelSide=\"start\"\n size={size}\n checked={checked}\n onCheckedChange={(next) => onValueChange(next ? 'accessible' : 'default')}\n />\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Variants */\n/* ------------------------------------------------------------------ */\n\ninterface VariantRenderProps {\n state: UseThemeReturn;\n className?: string;\n rest: HTMLAttributes<HTMLDivElement>;\n forwardedRef: React.Ref<HTMLDivElement>;\n showAccessibility: boolean;\n}\n\nfunction MenuVariant({\n state,\n className,\n rest,\n forwardedRef,\n showAccessibility,\n}: VariantRenderProps) {\n const { t } = useTranslation();\n const triggerIcon =\n state.resolvedTheme === 'dark' ||\n state.resolvedTheme === 'dark-accessible' ? (\n <Moon aria-hidden />\n ) : (\n <Sun aria-hidden />\n );\n\n const accessibleChecked = state.accessibility === 'accessible';\n\n return (\n <div\n ref={forwardedRef}\n data-component=\"theme-toggle\"\n data-component-id={rest.id}\n className={wrapperVariants({ variant: 'menu', className })}\n {...rest}\n >\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <IconButton\n icon={triggerIcon}\n aria-label={t('navigation.themeToggle.trigger')}\n />\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content align=\"end\" sideOffset={8}>\n <DropdownMenu.Label>\n {t('navigation.themeToggle.appearance.label')}\n </DropdownMenu.Label>\n <DropdownMenu.RadioGroup\n value={state.theme}\n onValueChange={(next) => state.setTheme(next as ThemePreference)}\n >\n <DropdownMenu.RadioItem value=\"light\">\n <Sun aria-hidden className=\"ds:size-4\" />\n {t('navigation.themeToggle.appearance.light')}\n </DropdownMenu.RadioItem>\n <DropdownMenu.RadioItem value=\"dark\">\n <Moon aria-hidden className=\"ds:size-4\" />\n {t('navigation.themeToggle.appearance.dark')}\n </DropdownMenu.RadioItem>\n <DropdownMenu.RadioItem value=\"system\">\n <Monitor aria-hidden className=\"ds:size-4\" />\n {t('navigation.themeToggle.appearance.system')}\n </DropdownMenu.RadioItem>\n </DropdownMenu.RadioGroup>\n {showAccessibility ? (\n <>\n <DropdownMenu.Separator />\n {/* CheckboxItem keeps the accessibility toggle inside the\n Radix menu collection so ArrowDown reaches it and Space\n activates it; `onSelect={preventDefault}` prevents the\n menu from closing on toggle. */}\n <DropdownMenu.CheckboxItem\n checked={accessibleChecked}\n onCheckedChange={(next) =>\n state.setAccessibility(next ? 'accessible' : 'default')\n }\n onSelect={(event) => event.preventDefault()}\n >\n {t('navigation.themeToggle.accessibility.label')}\n </DropdownMenu.CheckboxItem>\n </>\n ) : null}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n </div>\n );\n}\n\nfunction CompactVariant({\n state,\n className,\n rest,\n forwardedRef,\n}: VariantRenderProps) {\n const { t } = useTranslation();\n return (\n <div\n ref={forwardedRef}\n data-component=\"theme-toggle\"\n data-component-id={rest.id}\n className={wrapperVariants({ variant: 'compact', className })}\n {...rest}\n >\n <AppearanceSegment\n value={state.theme}\n onValueChange={state.setTheme}\n ariaLabel={t('navigation.themeToggle.appearance.label')}\n />\n </div>\n );\n}\n\nfunction SplitVariant({\n state,\n className,\n rest,\n forwardedRef,\n showAccessibility,\n}: VariantRenderProps) {\n const { t } = useTranslation();\n return (\n <div\n ref={forwardedRef}\n data-component=\"theme-toggle\"\n data-component-id={rest.id}\n className={wrapperVariants({ variant: 'split', className })}\n {...rest}\n >\n <AppearanceSegment\n value={state.theme}\n onValueChange={state.setTheme}\n ariaLabel={t('navigation.themeToggle.appearance.label')}\n />\n {showAccessibility ? (\n <AccessibilitySwitch\n value={state.accessibility}\n onValueChange={state.setAccessibility}\n />\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* ThemeToggle */\n/* ------------------------------------------------------------------ */\n\nexport const ThemeToggle = forwardRef<HTMLDivElement, ThemeToggleProps>(\n (props, ref) => {\n const {\n variant = 'menu',\n showAccessibility = true,\n className,\n id,\n // Strip controlled props from the spread — they are read by the\n // adapter, not by the DOM element.\n theme: _theme,\n accessibility: _accessibility,\n onThemeChange: _onThemeChange,\n onAccessibilityChange: _onAccessibilityChange,\n ...rest\n } = props as ThemeToggleProps & { id?: string };\n\n const state = useResolvedTheme(props);\n const stateRef = useRef(state);\n stateRef.current = state;\n\n // Internal variant wrappers attach refs to <div> elements; we forward that\n // DOM node as the public ref (Pattern B). The agent handle is registered\n // separately via useAgentRegistration.\n const forwardedRef = useRef<HTMLDivElement | null>(null);\n useImperativeHandle(ref, () => forwardedRef.current as HTMLDivElement, []);\n\n const agentHandle = useMemo<ThemeToggleHandle>(\n () => ({\n getCurrentTheme: () => stateRef.current.theme,\n getCurrentAccessibility: () => stateRef.current.accessibility,\n setTheme: (next) => stateRef.current.setTheme(next),\n setAccessibility: (next) => stateRef.current.setAccessibility(next),\n }),\n [],\n );\n useAgentRegistration(themeToggleAgent, agentHandle, id);\n\n if (variant === 'compact') {\n return (\n <CompactVariant\n state={state}\n className={className}\n rest={rest}\n forwardedRef={forwardedRef}\n showAccessibility={showAccessibility}\n />\n );\n }\n if (variant === 'split') {\n return (\n <SplitVariant\n state={state}\n className={className}\n rest={rest}\n forwardedRef={forwardedRef}\n showAccessibility={showAccessibility}\n />\n );\n }\n return (\n <MenuVariant\n state={state}\n className={className}\n rest={rest}\n forwardedRef={forwardedRef}\n showAccessibility={showAccessibility}\n />\n );\n },\n);\n\nThemeToggle.displayName = 'ThemeToggle';\n"],"names":["__iconNode","Monitor","createLucideIcon","Moon","Sun","themeToggleAgent","handle","args","wrapperVariants","cva","useResolvedTheme","props","themeProp","accessibilityProp","onThemeChange","onAccessibilityChange","store","useTheme","theme","accessibility","storeSetTheme","storeSetAccessibility","setTheme","useCallback","next","setAccessibility","AppearanceSegment","value","onValueChange","ariaLabel","size","t","useTranslation","jsxs","IconButtonGroup","jsx","IconButton","AccessibilitySwitch","checked","Switch","MenuVariant","state","className","rest","forwardedRef","showAccessibility","triggerIcon","accessibleChecked","DropdownMenu","Fragment","event","CompactVariant","SplitVariant","ThemeToggle","forwardRef","ref","variant","id","_theme","_accessibility","_onThemeChange","_onAccessibilityChange","stateRef","useRef","useImperativeHandle","agentHandle","useMemo","useAgentRegistration"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
1
|
+
{"version":3,"file":"theme-toggle-FrotC2VI.js","sources":["../../src/components/theme-toggle/theme-toggle.agent.ts","../../src/components/theme-toggle/theme-toggle.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — ThemeToggle. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { ThemeToggleHandle } from './theme-toggle';\n\nexport const themeToggleAgent: AgentAdapter<ThemeToggleHandle> = {\n id: 'theme-toggle',\n capabilities: ['view_change'],\n state: {\n currentTheme: {\n type: 'ThemePreference',\n descriptionKey: 'ui.agent.themeToggle.state.currentTheme',\n description: 'Active theme preference: light, dark, or system.',\n read: (handle) => handle.getCurrentTheme(),\n },\n currentAccessibility: {\n type: 'AccessibilityPreference',\n descriptionKey: 'ui.agent.themeToggle.state.currentAccessibility',\n description: 'Active accessibility preference: default or accessible.',\n read: (handle) => handle.getCurrentAccessibility(),\n },\n },\n actions: {\n set_theme: {\n safety: 'write',\n argsType: '{ theme: \"light\" | \"dark\" | \"system\" }',\n descriptionKey: 'ui.agent.themeToggle.actions.setTheme',\n description: 'Switch the theme preference.',\n invoke: (handle, args: { theme: 'light' | 'dark' | 'system' }) => {\n handle.setTheme(args.theme);\n },\n },\n set_accessibility: {\n safety: 'write',\n argsType: '{ accessibility: \"default\" | \"accessible\" }',\n descriptionKey: 'ui.agent.themeToggle.actions.setAccessibility',\n description: 'Switch the accessibility preference.',\n invoke: (handle, args: { accessibility: 'default' | 'accessible' }) => {\n handle.setAccessibility(args.accessibility);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'theme-toggle',\n description: 'Marks the ThemeToggle wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n type HTMLAttributes,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Monitor, Moon, Sun } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { IconButtonGroup } from '../icon-button-group/icon-button-group';\nimport { Switch } from '../switch/switch';\nimport { DropdownMenu } from '../dropdown-menu/dropdown-menu';\nimport {\n useTheme,\n type AccessibilityPreference,\n type ThemePreference,\n type UseThemeReturn,\n} from '../../hooks';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { themeToggleAgent } from './theme-toggle.agent';\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst wrapperVariants = cva('ds:inline-flex ds:items-center', {\n variants: {\n variant: {\n menu: '',\n compact: '',\n split: 'ds:gap-[var(--spacing-md)]',\n },\n },\n defaultVariants: { variant: 'menu' },\n});\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport type ThemeToggleVariant = 'menu' | 'compact' | 'split';\n\ninterface ThemeToggleBaseProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onChange'>,\n VariantProps<typeof wrapperVariants> {\n /**\n * Visual form factor.\n * - `menu` (default) — single trigger that opens a dropdown with both\n * Appearance and Accessibility controls. Best for headers / nav rails.\n * - `compact` — segmented Appearance control only. Use when accessibility\n * lives on a separate settings surface.\n * - `split` — segmented Appearance control plus an inline Accessibility\n * switch. Best for full-width settings panels.\n */\n variant?: ThemeToggleVariant;\n /** Hide the accessibility control. Ignored on `compact`, which never renders it. */\n showAccessibility?: boolean;\n /**\n * Controlled escape hatch — when omitted the component reads/writes\n * `useTheme()` directly so it can drop into any header with no wiring.\n * Pass all four to opt into controlled mode.\n */\n theme?: ThemePreference;\n accessibility?: AccessibilityPreference;\n onThemeChange?: (next: ThemePreference) => void;\n onAccessibilityChange?: (next: AccessibilityPreference) => void;\n}\n\nexport type ThemeToggleProps = ThemeToggleBaseProps;\n\n/** Curated imperative handle for agent / external automation. */\nexport interface ThemeToggleHandle {\n getCurrentTheme: () => ThemePreference;\n getCurrentAccessibility: () => AccessibilityPreference;\n setTheme: (next: ThemePreference) => void;\n setAccessibility: (next: AccessibilityPreference) => void;\n}\n\n/* ------------------------------------------------------------------ */\n/* Hook adapter */\n/* ------------------------------------------------------------------ */\n\n/**\n * Resolves controlled props against the store. When the consumer passes\n * `theme` / `onThemeChange` (etc.) we honour those; otherwise we fall\n * through to the singleton `useTheme()` hook so a bare `<ThemeToggle />`\n * works with zero wiring.\n */\nfunction useResolvedTheme(props: ThemeToggleBaseProps): UseThemeReturn {\n const {\n theme: themeProp,\n accessibility: accessibilityProp,\n onThemeChange,\n onAccessibilityChange,\n } = props;\n const store = useTheme();\n const theme = themeProp ?? store.theme;\n const accessibility = accessibilityProp ?? store.accessibility;\n\n const storeSetTheme = store.setTheme;\n const storeSetAccessibility = store.setAccessibility;\n\n const setTheme = useCallback(\n (next: ThemePreference) => {\n if (onThemeChange) {\n onThemeChange(next);\n return;\n }\n storeSetTheme(next);\n },\n [onThemeChange, storeSetTheme],\n );\n\n const setAccessibility = useCallback(\n (next: AccessibilityPreference) => {\n if (onAccessibilityChange) {\n onAccessibilityChange(next);\n return;\n }\n storeSetAccessibility(next);\n },\n [onAccessibilityChange, storeSetAccessibility],\n );\n\n return {\n theme,\n accessibility,\n resolvedTheme: store.resolvedTheme,\n setTheme,\n setAccessibility,\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Sub-pieces */\n/* ------------------------------------------------------------------ */\n\ninterface AppearanceSegmentProps {\n value: ThemePreference;\n onValueChange: (next: ThemePreference) => void;\n ariaLabel: string;\n size?: 'sm' | 'md' | 'lg';\n}\n\nfunction AppearanceSegment({\n value,\n onValueChange,\n ariaLabel,\n size = 'md',\n}: AppearanceSegmentProps) {\n const { t } = useTranslation();\n return (\n <IconButtonGroup\n aria-label={ariaLabel}\n role=\"radiogroup\"\n mode=\"toggle-single\"\n size={size}\n value={value}\n onValueChange={(next) => onValueChange(next as ThemePreference)}\n >\n <IconButton\n icon={<Sun aria-hidden />}\n aria-label={t('navigation.themeToggle.appearance.light')}\n value=\"light\"\n />\n <IconButton\n icon={<Moon aria-hidden />}\n aria-label={t('navigation.themeToggle.appearance.dark')}\n value=\"dark\"\n />\n <IconButton\n icon={<Monitor aria-hidden />}\n aria-label={t('navigation.themeToggle.appearance.system')}\n value=\"system\"\n />\n </IconButtonGroup>\n );\n}\n\ninterface AccessibilitySwitchProps {\n value: AccessibilityPreference;\n onValueChange: (next: AccessibilityPreference) => void;\n size?: 'sm' | 'md' | 'lg';\n}\n\nfunction AccessibilitySwitch({\n value,\n onValueChange,\n size = 'md',\n}: AccessibilitySwitchProps) {\n const { t } = useTranslation();\n // 'system' is treated as \"off\" visually — the OS preference flows through\n // automatically. Flipping the switch on creates an explicit override.\n const checked = value === 'accessible';\n return (\n <Switch\n label={t('navigation.themeToggle.accessibility.label')}\n labelSide=\"start\"\n size={size}\n checked={checked}\n onCheckedChange={(next) => onValueChange(next ? 'accessible' : 'default')}\n />\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Variants */\n/* ------------------------------------------------------------------ */\n\ninterface VariantRenderProps {\n state: UseThemeReturn;\n className?: string;\n rest: HTMLAttributes<HTMLDivElement>;\n forwardedRef: React.Ref<HTMLDivElement>;\n showAccessibility: boolean;\n}\n\nfunction MenuVariant({\n state,\n className,\n rest,\n forwardedRef,\n showAccessibility,\n}: VariantRenderProps) {\n const { t } = useTranslation();\n const triggerIcon =\n state.resolvedTheme === 'dark' ||\n state.resolvedTheme === 'dark-accessible' ? (\n <Moon aria-hidden />\n ) : (\n <Sun aria-hidden />\n );\n\n const accessibleChecked = state.accessibility === 'accessible';\n\n return (\n <div\n ref={forwardedRef}\n data-component=\"theme-toggle\"\n data-component-id={rest.id}\n className={wrapperVariants({ variant: 'menu', className })}\n {...rest}\n >\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <IconButton\n icon={triggerIcon}\n aria-label={t('navigation.themeToggle.trigger')}\n />\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content align=\"end\" sideOffset={8}>\n <DropdownMenu.Label>\n {t('navigation.themeToggle.appearance.label')}\n </DropdownMenu.Label>\n <DropdownMenu.RadioGroup\n value={state.theme}\n onValueChange={(next) => state.setTheme(next as ThemePreference)}\n >\n <DropdownMenu.RadioItem value=\"light\">\n <Sun aria-hidden className=\"ds:size-4\" />\n {t('navigation.themeToggle.appearance.light')}\n </DropdownMenu.RadioItem>\n <DropdownMenu.RadioItem value=\"dark\">\n <Moon aria-hidden className=\"ds:size-4\" />\n {t('navigation.themeToggle.appearance.dark')}\n </DropdownMenu.RadioItem>\n <DropdownMenu.RadioItem value=\"system\">\n <Monitor aria-hidden className=\"ds:size-4\" />\n {t('navigation.themeToggle.appearance.system')}\n </DropdownMenu.RadioItem>\n </DropdownMenu.RadioGroup>\n {showAccessibility ? (\n <>\n <DropdownMenu.Separator />\n {/* CheckboxItem keeps the accessibility toggle inside the\n Radix menu collection so ArrowDown reaches it and Space\n activates it; `onSelect={preventDefault}` prevents the\n menu from closing on toggle. */}\n <DropdownMenu.CheckboxItem\n checked={accessibleChecked}\n onCheckedChange={(next) =>\n state.setAccessibility(next ? 'accessible' : 'default')\n }\n onSelect={(event) => event.preventDefault()}\n >\n {t('navigation.themeToggle.accessibility.label')}\n </DropdownMenu.CheckboxItem>\n </>\n ) : null}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n </div>\n );\n}\n\nfunction CompactVariant({\n state,\n className,\n rest,\n forwardedRef,\n}: VariantRenderProps) {\n const { t } = useTranslation();\n return (\n <div\n ref={forwardedRef}\n data-component=\"theme-toggle\"\n data-component-id={rest.id}\n className={wrapperVariants({ variant: 'compact', className })}\n {...rest}\n >\n <AppearanceSegment\n value={state.theme}\n onValueChange={state.setTheme}\n ariaLabel={t('navigation.themeToggle.appearance.label')}\n />\n </div>\n );\n}\n\nfunction SplitVariant({\n state,\n className,\n rest,\n forwardedRef,\n showAccessibility,\n}: VariantRenderProps) {\n const { t } = useTranslation();\n return (\n <div\n ref={forwardedRef}\n data-component=\"theme-toggle\"\n data-component-id={rest.id}\n className={wrapperVariants({ variant: 'split', className })}\n {...rest}\n >\n <AppearanceSegment\n value={state.theme}\n onValueChange={state.setTheme}\n ariaLabel={t('navigation.themeToggle.appearance.label')}\n />\n {showAccessibility ? (\n <AccessibilitySwitch\n value={state.accessibility}\n onValueChange={state.setAccessibility}\n />\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* ThemeToggle */\n/* ------------------------------------------------------------------ */\n\nexport const ThemeToggle = forwardRef<HTMLDivElement, ThemeToggleProps>(\n (props, ref) => {\n const {\n variant = 'menu',\n showAccessibility = true,\n className,\n id,\n // Strip controlled props from the spread — they are read by the\n // adapter, not by the DOM element.\n theme: _theme,\n accessibility: _accessibility,\n onThemeChange: _onThemeChange,\n onAccessibilityChange: _onAccessibilityChange,\n ...rest\n } = props as ThemeToggleProps & { id?: string };\n\n const state = useResolvedTheme(props);\n const stateRef = useRef(state);\n stateRef.current = state;\n\n // Internal variant wrappers attach refs to <div> elements; we forward that\n // DOM node as the public ref (Pattern B). The agent handle is registered\n // separately via useAgentRegistration.\n const forwardedRef = useRef<HTMLDivElement | null>(null);\n useImperativeHandle(ref, () => forwardedRef.current as HTMLDivElement, []);\n\n const agentHandle = useMemo<ThemeToggleHandle>(\n () => ({\n getCurrentTheme: () => stateRef.current.theme,\n getCurrentAccessibility: () => stateRef.current.accessibility,\n setTheme: (next) => stateRef.current.setTheme(next),\n setAccessibility: (next) => stateRef.current.setAccessibility(next),\n }),\n [],\n );\n useAgentRegistration(themeToggleAgent, agentHandle, id);\n\n if (variant === 'compact') {\n return (\n <CompactVariant\n state={state}\n className={className}\n rest={rest}\n forwardedRef={forwardedRef}\n showAccessibility={showAccessibility}\n />\n );\n }\n if (variant === 'split') {\n return (\n <SplitVariant\n state={state}\n className={className}\n rest={rest}\n forwardedRef={forwardedRef}\n showAccessibility={showAccessibility}\n />\n );\n }\n return (\n <MenuVariant\n state={state}\n className={className}\n rest={rest}\n forwardedRef={forwardedRef}\n showAccessibility={showAccessibility}\n />\n );\n },\n);\n\nThemeToggle.displayName = 'ThemeToggle';\n"],"names":["themeToggleAgent","handle","args","wrapperVariants","cva","useResolvedTheme","props","themeProp","accessibilityProp","onThemeChange","onAccessibilityChange","store","useTheme","theme","accessibility","storeSetTheme","storeSetAccessibility","setTheme","useCallback","next","setAccessibility","AppearanceSegment","value","onValueChange","ariaLabel","size","t","useTranslation","jsxs","IconButtonGroup","jsx","IconButton","Sun","Moon","Monitor","AccessibilitySwitch","checked","Switch","MenuVariant","state","className","rest","forwardedRef","showAccessibility","triggerIcon","accessibleChecked","DropdownMenu","Fragment","event","CompactVariant","SplitVariant","ThemeToggle","forwardRef","ref","variant","id","_theme","_accessibility","_onThemeChange","_onAccessibilityChange","stateRef","useRef","useImperativeHandle","agentHandle","useMemo","useAgentRegistration"],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useState as r, useEffect as u, useCallback as c } from "react";
|
|
2
|
+
import "../i18n/config.js";
|
|
3
|
+
import a from "i18next";
|
|
4
|
+
function m() {
|
|
5
|
+
const [e, n] = r(() => a.language);
|
|
6
|
+
u(() => {
|
|
7
|
+
const t = (l) => n(l);
|
|
8
|
+
return a.on("languageChanged", t), a.language !== e && n(a.language), () => {
|
|
9
|
+
a.off("languageChanged", t);
|
|
10
|
+
};
|
|
11
|
+
}, [e]);
|
|
12
|
+
const o = c(async (t) => {
|
|
13
|
+
await a.changeLanguage(t);
|
|
14
|
+
}, []), g = a.dir(e) === "rtl" ? "rtl" : "ltr";
|
|
15
|
+
return { locale: e, dir: g, setLocale: o };
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
m as u
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=use-locale-BkCIHujH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-locale-BkCIHujH.js","sources":["../../src/hooks/use-locale.ts"],"sourcesContent":["import { useCallback, useEffect, useState } from 'react';\nimport i18n from '../i18n/config';\n\nexport type LocaleDir = 'ltr' | 'rtl';\n\nexport interface UseLocaleReturn {\n /** Current i18next language tag (e.g. `'en'`, `'ar'`, `'ja'`). */\n locale: string;\n /** Reading direction for the current locale, derived from `i18n.dir(locale)`. */\n dir: LocaleDir;\n /** Change the active i18next language. */\n setLocale: (next: string) => Promise<void>;\n}\n\n/**\n * Read the active i18n locale and its reading direction. Subscribes to\n * `i18next.on('languageChanged')` so consumers re-render when the locale\n * changes (e.g. via `<select>` in a settings page).\n *\n * SSR-safe: the initial state is read synchronously from the i18next\n * instance, which itself ships an SSR-friendly default. The\n * `languageChanged` listener attaches in `useEffect`, so it only runs\n * client-side.\n *\n * Thin wrapper — the underlying source of truth is the i18next instance\n * exported from `src/i18n/config.ts`. Use this hook over reading\n * `i18n.language` directly so components can:\n * 1. Re-render on language change without ad-hoc state.\n * 2. Get `dir` derived correctly (RTL for `ar`).\n */\nexport function useLocale(): UseLocaleReturn {\n const [locale, setLocaleState] = useState<string>(() => i18n.language);\n\n useEffect(() => {\n const onChange = (next: string) => setLocaleState(next);\n i18n.on('languageChanged', onChange);\n // Re-sync — the `i18n.language` may have settled between the\n // initial useState read and effect attach (async language load).\n if (i18n.language !== locale) setLocaleState(i18n.language);\n return () => {\n i18n.off('languageChanged', onChange);\n };\n }, [locale]);\n\n const setLocale = useCallback(async (next: string) => {\n await i18n.changeLanguage(next);\n }, []);\n\n // `i18n.dir(locale)` returns `'ltr' | 'rtl'` — the i18next types declare\n // it as `string`, so we narrow.\n const dir = (i18n.dir(locale) === 'rtl' ? 'rtl' : 'ltr') as LocaleDir;\n\n return { locale, dir, setLocale };\n}\n"],"names":["useLocale","locale","setLocaleState","useState","i18n","useEffect","onChange","next","setLocale","useCallback","dir"],"mappings":";;;AA8BO,SAASA,IAA6B;AAC3C,QAAM,CAACC,GAAQC,CAAc,IAAIC,EAAiB,MAAMC,EAAK,QAAQ;AAErE,EAAAC,EAAU,MAAM;AACd,UAAMC,IAAW,CAACC,MAAiBL,EAAeK,CAAI;AACtDH,WAAAA,EAAK,GAAG,mBAAmBE,CAAQ,GAG/BF,EAAK,aAAaH,KAAQC,EAAeE,EAAK,QAAQ,GACnD,MAAM;AACXA,MAAAA,EAAK,IAAI,mBAAmBE,CAAQ;AAAA,IACtC;AAAA,EACF,GAAG,CAACL,CAAM,CAAC;AAEX,QAAMO,IAAYC,EAAY,OAAOF,MAAiB;AACpD,UAAMH,EAAK,eAAeG,CAAI;AAAA,EAChC,GAAG,CAAA,CAAE,GAICG,IAAON,EAAK,IAAIH,CAAM,MAAM,QAAQ,QAAQ;AAElD,SAAO,EAAE,QAAAA,GAAQ,KAAAS,GAAK,WAAAF,EAAA;AACxB;"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useState as h, useEffect as w, useRef as m } from "react";
|
|
2
|
+
function v(e) {
|
|
3
|
+
const [i, r] = h(() => typeof window > "u" || typeof window.matchMedia != "function" ? !1 : window.matchMedia(e).matches);
|
|
4
|
+
return w(() => {
|
|
5
|
+
if (typeof window > "u" || typeof window.matchMedia != "function")
|
|
6
|
+
return;
|
|
7
|
+
const n = window.matchMedia(e);
|
|
8
|
+
r(n.matches);
|
|
9
|
+
const t = (u) => r(u.matches);
|
|
10
|
+
return typeof n.addEventListener == "function" ? (n.addEventListener("change", t), () => n.removeEventListener("change", t)) : (n.addListener(t), () => n.removeListener(t));
|
|
11
|
+
}, [e]), i;
|
|
12
|
+
}
|
|
13
|
+
function p(e) {
|
|
14
|
+
return e != null && e.current ? e.current : typeof document > "u" ? null : document;
|
|
15
|
+
}
|
|
16
|
+
function S(e, i) {
|
|
17
|
+
const r = typeof CSS < "u" && typeof CSS.escape == "function" ? CSS.escape(e) : (
|
|
18
|
+
// SSR / jsdom fallback — drop every character that's
|
|
19
|
+
// significant in a CSS attribute selector. Conservative but
|
|
20
|
+
// robust enough for the test environment.
|
|
21
|
+
e.replace(/["'\\[\]]/g, "")
|
|
22
|
+
), n = `[data-error-anchor="${r}"], [name="${r}"], [name$="[${r}]"]`, t = Array.from(i.querySelectorAll(n));
|
|
23
|
+
return t.length === 0 ? null : t.find((f) => f.offsetParent !== null) ?? t[0];
|
|
24
|
+
}
|
|
25
|
+
function E(e, i, r = {}) {
|
|
26
|
+
const {
|
|
27
|
+
scope: n,
|
|
28
|
+
scrollOptions: t = { behavior: "smooth", block: "center" },
|
|
29
|
+
focus: u = !0,
|
|
30
|
+
skipInitialMount: f = !0
|
|
31
|
+
} = r, l = m(!0), c = m(null), o = i.find((s) => !!e[s]) ?? null;
|
|
32
|
+
w(() => {
|
|
33
|
+
if (l.current && (l.current = !1, f)) {
|
|
34
|
+
c.current = o;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (!o) {
|
|
38
|
+
c.current = null;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (o === c.current || typeof window > "u") return;
|
|
42
|
+
const s = window.requestAnimationFrame(() => {
|
|
43
|
+
const d = p(n);
|
|
44
|
+
if (!d) return;
|
|
45
|
+
const a = S(o, d);
|
|
46
|
+
a && (a.scrollIntoView(t), u && a.focus({ preventScroll: !0 }), c.current = o);
|
|
47
|
+
});
|
|
48
|
+
return () => window.cancelAnimationFrame(s);
|
|
49
|
+
}, [o]);
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
E as a,
|
|
53
|
+
v as u
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=use-scroll-to-first-error-BrK7dKB_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-scroll-to-first-error-BrK7dKB_.js","sources":["../../src/hooks/use-media-query.ts","../../src/hooks/use-scroll-to-first-error.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n/**\n * Subscribe to an arbitrary media query and return whether it currently\n * matches. Useful for responsive components that need to branch on\n * viewport size without hand-rolling `matchMedia` plumbing.\n *\n * SSR-safe: returns `false` when `window` is undefined. The effect is\n * client-only, so hydration mismatches are avoided without a null\n * sentinel at the type level.\n *\n * Mirrors the shape of `usePrefersReducedMotion` — Safari < 14 fallback\n * via `addListener` / `removeListener` is included.\n *\n * @example\n * const isMobile = useMediaQuery('(max-width: 640px)');\n */\nexport function useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState<boolean>(() => {\n if (\n typeof window === 'undefined' ||\n typeof window.matchMedia !== 'function'\n ) {\n return false;\n }\n return window.matchMedia(query).matches;\n });\n\n useEffect(() => {\n if (\n typeof window === 'undefined' ||\n typeof window.matchMedia !== 'function'\n ) {\n return;\n }\n const mql = window.matchMedia(query);\n // Re-sync in case the query (or the OS state) changed between the\n // initial useState read and the first effect.\n setMatches(mql.matches);\n const onChange = (ev: MediaQueryListEvent) => setMatches(ev.matches);\n if (typeof mql.addEventListener === 'function') {\n mql.addEventListener('change', onChange);\n return () => mql.removeEventListener('change', onChange);\n }\n mql.addListener(onChange);\n return () => mql.removeListener(onChange);\n }, [query]);\n\n return matches;\n}\n","import { useEffect, useRef, type RefObject } from 'react';\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\nexport interface UseScrollToFirstErrorOptions {\n /**\n * Limits the DOM query to this element. Useful when the page renders\n * more than one form, or when an unrelated component happens to share\n * a field name. Defaults to `document`.\n */\n scope?: RefObject<HTMLElement | null>;\n /**\n * Forwarded to `scrollIntoView`. Defaults to\n * `{ behavior: 'smooth', block: 'center' }`. Pass\n * `{ behavior: 'auto' }` (or omit `behavior`) on consumers that\n * respect `prefers-reduced-motion` upstream — the kit doesn't shadow\n * the user's motion preference inside the hook, since some consumers\n * deliberately keep a near-instant snap for power-user form flows.\n */\n scrollOptions?: ScrollIntoViewOptions;\n /**\n * Move keyboard focus to the errored field after scrolling. Default\n * `true`. The focus call uses `preventScroll: true` so the smooth\n * scroll the hook just did isn't replaced by a snap.\n *\n * Setting this `false` defeats the keyboard-user side of WCAG 3.3.1\n * — the viewport will scroll but the active element stays on the\n * submit button, forcing a Shift+Tab back into the form. Only flip\n * this off when an upstream concern (e.g. a custom error summary\n * panel that owns its own focus) is taking responsibility.\n */\n focus?: boolean;\n /**\n * On the very first render, do nothing even if `errors` already has\n * entries. Default `true`. Without this the hook would yank the\n * viewport whenever a form is hydrated with server-rendered errors\n * from a no-JS fallback path — bad UX, since the user landed on the\n * page and hasn't asked for any movement yet. Set `false` only when\n * the consumer explicitly wants the initial-mount scroll (rare).\n */\n skipInitialMount?: boolean;\n}\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\nfunction getScopeRoot(\n scope: RefObject<HTMLElement | null> | undefined,\n): ParentNode | null {\n if (scope?.current) return scope.current;\n if (typeof document === 'undefined') return null;\n return document;\n}\n\n/**\n * Resolve the DOM element to scroll/focus for a given errored field\n * name. The match order is:\n *\n * 1. `[data-error-anchor=\"<name>\"]` — the consumer's explicit hook,\n * used for Radix-based fields (Checkbox / Select / Switch) where\n * the named `<input>` is hidden behind a visible `<button>`.\n * Consumers set this on the trigger.\n * 2. `[name=\"<name>\"]` — the literal field name.\n * 3. `[name$=\"[<name>]\"]` — Symfony form-prefixed names like\n * `privacy_generator[fiscal_code]`. Suffix match keeps the hook\n * consumer-agnostic; no need to thread the form prefix through.\n *\n * Returns the first visible element among the matches. \"Visible\" here\n * means `offsetParent !== null` — that's the cheap heuristic Radix's\n * hidden inputs (display:none-equivalent positioning) fail and the\n * visible triggers pass. Falls back to the first match if every match\n * is hidden, so a field can still be scrolled into view even when the\n * trigger uses a non-standard layout.\n */\nfunction findErrorElement(name: string, root: ParentNode): HTMLElement | null {\n // `CSS.escape` is load-bearing here, not cosmetic. The Symfony\n // suffix-match arm embeds `name` inside `[name$=\"[${safe}]\"]`, so a\n // field name containing `]` would otherwise close the attribute\n // selector early and turn the rest of the string into stray\n // selector tokens. We don't expect adversarial input in practice\n // (server-controlled field names), but a server returning a `]`\n // in a 422 payload shouldn't be able to break the query.\n const safe =\n typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(name)\n : // SSR / jsdom fallback — drop every character that's\n // significant in a CSS attribute selector. Conservative but\n // robust enough for the test environment.\n name.replace(/[\"'\\\\[\\]]/g, '');\n const selector =\n `[data-error-anchor=\"${safe}\"], ` +\n `[name=\"${safe}\"], ` +\n `[name$=\"[${safe}]\"]`;\n\n const matches = Array.from(root.querySelectorAll<HTMLElement>(selector));\n if (matches.length === 0) return null;\n\n const visible = matches.find((el) => el.offsetParent !== null);\n return visible ?? matches[0];\n}\n\n/* -------------------------------------------------------------------- */\n/* Hook */\n/* -------------------------------------------------------------------- */\n\n/**\n * Scrolls the first errored field into view and (by default) focuses\n * it, after `errors` changes. Backs the standard AlfaDocs rebrand\n * validation-error UX: after a 422 with `{ errors: { field: message } }`\n * is rendered inline, the user shouldn't be left staring at red labels\n * they can't see. Implements WCAG 3.3.1 / 3.3.3.\n *\n * The hook is stateless and never mutates the DOM beyond the\n * `scrollIntoView` + `focus` calls.\n *\n * @example\n * const fieldOrder = ['firstName', 'email', 'fiscalCode'] as const;\n * const [errors, setErrors] = useState<Record<string, string>>({});\n * useScrollToFirstError(errors, fieldOrder);\n *\n * @example Radix-based field\n * <Checkbox data-error-anchor=\"consent\" name=\"consent\" />\n * // hook scrolls to the visible <button>, not Radix's hidden input.\n *\n * @example Scoped to one form\n * const formRef = useRef<HTMLFormElement>(null);\n * useScrollToFirstError(errors, fieldOrder, { scope: formRef });\n */\nexport function useScrollToFirstError(\n errors: Readonly<Record<string, string | undefined>>,\n fieldOrder: ReadonlyArray<string>,\n options: UseScrollToFirstErrorOptions = {},\n): void {\n const {\n scope,\n scrollOptions = { behavior: 'smooth', block: 'center' },\n focus = true,\n skipInitialMount = true,\n } = options;\n\n const isInitialMount = useRef(true);\n\n // Track the previous \"first errored field name\" so a re-render that\n // leaves the same field errored doesn't re-scroll. We intentionally\n // depend on the resolved name (not the whole errors object) — that\n // way callers can mutate `errors` shape freely as long as the head\n // of the validation list is stable, which is the typical pattern\n // after a server returns the same 422 twice in a row.\n const lastScrolledFieldRef = useRef<string | null>(null);\n\n // Resolve the first errored field by visual order. A field is\n // \"errored\" iff its key has a truthy string value — the kit's form\n // contract is `Record<string, string | undefined>` where `undefined`\n // / missing keys mean \"no error\".\n const firstErroredField =\n fieldOrder.find((name) => Boolean(errors[name])) ?? null;\n\n useEffect(() => {\n if (isInitialMount.current) {\n isInitialMount.current = false;\n if (skipInitialMount) {\n // Record what we skipped so the next render doesn't try to\n // scroll to a field that was already errored at mount.\n lastScrolledFieldRef.current = firstErroredField;\n return;\n }\n }\n\n if (!firstErroredField) {\n lastScrolledFieldRef.current = null;\n return;\n }\n\n if (firstErroredField === lastScrolledFieldRef.current) return;\n\n if (typeof window === 'undefined') return;\n\n // rAF defers the scroll until after the browser has laid out the\n // freshly-rendered error labels. Calling scrollIntoView synchronously\n // inside useEffect would fire before the new DOM is painted on\n // some browsers, leaving the viewport pointing at the old layout.\n const handle = window.requestAnimationFrame(() => {\n const root = getScopeRoot(scope);\n if (!root) return;\n const el = findErrorElement(firstErroredField, root);\n if (!el) return;\n\n el.scrollIntoView(scrollOptions);\n if (focus) {\n // preventScroll: true so the browser doesn't override the\n // smooth scroll above with a snap to put the element at the\n // top of the viewport.\n el.focus({ preventScroll: true });\n }\n lastScrolledFieldRef.current = firstErroredField;\n });\n\n return () => window.cancelAnimationFrame(handle);\n // `scrollOptions` / `focus` / `scope` / `skipInitialMount` are\n // option bag values — re-running on their identity change would\n // be surprising. The hook re-fires only when the field at the\n // head of the errored list changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [firstErroredField]);\n}\n"],"names":["useMediaQuery","query","matches","setMatches","useState","useEffect","mql","onChange","ev","getScopeRoot","scope","findErrorElement","name","root","safe","selector","el","useScrollToFirstError","errors","fieldOrder","options","scrollOptions","focus","skipInitialMount","isInitialMount","useRef","lastScrolledFieldRef","firstErroredField","handle"],"mappings":";AAiBO,SAASA,EAAcC,GAAwB;AACpD,QAAM,CAACC,GAASC,CAAU,IAAIC,EAAkB,MAE5C,OAAO,SAAW,OAClB,OAAO,OAAO,cAAe,aAEtB,KAEF,OAAO,WAAWH,CAAK,EAAE,OACjC;AAED,SAAAI,EAAU,MAAM;AACd,QACE,OAAO,SAAW,OAClB,OAAO,OAAO,cAAe;AAE7B;AAEF,UAAMC,IAAM,OAAO,WAAWL,CAAK;AAGnC,IAAAE,EAAWG,EAAI,OAAO;AACtB,UAAMC,IAAW,CAACC,MAA4BL,EAAWK,EAAG,OAAO;AACnE,WAAI,OAAOF,EAAI,oBAAqB,cAClCA,EAAI,iBAAiB,UAAUC,CAAQ,GAChC,MAAMD,EAAI,oBAAoB,UAAUC,CAAQ,MAEzDD,EAAI,YAAYC,CAAQ,GACjB,MAAMD,EAAI,eAAeC,CAAQ;AAAA,EAC1C,GAAG,CAACN,CAAK,CAAC,GAEHC;AACT;ACAA,SAASO,EACPC,GACmB;AACnB,SAAIA,KAAA,QAAAA,EAAO,UAAgBA,EAAM,UAC7B,OAAO,WAAa,MAAoB,OACrC;AACT;AAsBA,SAASC,EAAiBC,GAAcC,GAAsC;AAQ5E,QAAMC,IACJ,OAAO,MAAQ,OAAe,OAAO,IAAI,UAAW,aAChD,IAAI,OAAOF,CAAI;AAAA;AAAA;AAAA;AAAA,IAIfA,EAAK,QAAQ,cAAc,EAAE;AAAA,KAC7BG,IACJ,uBAAuBD,CAAI,cACjBA,CAAI,gBACFA,CAAI,OAEZZ,IAAU,MAAM,KAAKW,EAAK,iBAA8BE,CAAQ,CAAC;AACvE,SAAIb,EAAQ,WAAW,IAAU,OAEjBA,EAAQ,KAAK,CAACc,MAAOA,EAAG,iBAAiB,IAAI,KAC3Cd,EAAQ,CAAC;AAC7B;AA6BO,SAASe,EACdC,GACAC,GACAC,IAAwC,CAAA,GAClC;AACN,QAAM;AAAA,IACJ,OAAAV;AAAA,IACA,eAAAW,IAAgB,EAAE,UAAU,UAAU,OAAO,SAAA;AAAA,IAC7C,OAAAC,IAAQ;AAAA,IACR,kBAAAC,IAAmB;AAAA,EAAA,IACjBH,GAEEI,IAAiBC,EAAO,EAAI,GAQ5BC,IAAuBD,EAAsB,IAAI,GAMjDE,IACJR,EAAW,KAAK,CAACP,MAAS,EAAQM,EAAON,CAAI,CAAE,KAAK;AAEtD,EAAAP,EAAU,MAAM;AACd,QAAImB,EAAe,YACjBA,EAAe,UAAU,IACrBD,IAAkB;AAGpB,MAAAG,EAAqB,UAAUC;AAC/B;AAAA,IACF;AAGF,QAAI,CAACA,GAAmB;AACtB,MAAAD,EAAqB,UAAU;AAC/B;AAAA,IACF;AAIA,QAFIC,MAAsBD,EAAqB,WAE3C,OAAO,SAAW,IAAa;AAMnC,UAAME,IAAS,OAAO,sBAAsB,MAAM;AAChD,YAAMf,IAAOJ,EAAaC,CAAK;AAC/B,UAAI,CAACG,EAAM;AACX,YAAMG,IAAKL,EAAiBgB,GAAmBd,CAAI;AACnD,MAAKG,MAELA,EAAG,eAAeK,CAAa,GAC3BC,KAIFN,EAAG,MAAM,EAAE,eAAe,GAAA,CAAM,GAElCU,EAAqB,UAAUC;AAAA,IACjC,CAAC;AAED,WAAO,MAAM,OAAO,qBAAqBC,CAAM;AAAA,EAMjD,GAAG,CAACD,CAAiB,CAAC;AACxB;"}
|