twico-ui 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var React25 = require('react');
4
+ var React37 = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var reactDom = require('react-dom');
7
7
 
@@ -23,21 +23,338 @@ function _interopNamespace(e) {
23
23
  return Object.freeze(n);
24
24
  }
25
25
 
26
- var React25__namespace = /*#__PURE__*/_interopNamespace(React25);
26
+ var React37__namespace = /*#__PURE__*/_interopNamespace(React37);
27
27
 
28
- // components/navigation/Accordion.jsx
29
- var SUPPORTS_STYLE_HOIST = parseInt(String(React25__namespace.version), 10) >= 19;
28
+ // components/TwicoProvider.jsx
29
+ var SUPPORTS_STYLE_HOIST = parseInt(String(React37__namespace.version), 10) >= 19;
30
+ var NonceContext = React37__namespace.createContext(void 0);
30
31
  function useScopedStyles(id, css) {
31
- React25__namespace.useInsertionEffect(() => {
32
+ const nonce = React37__namespace.useContext(NonceContext);
33
+ React37__namespace.useInsertionEffect(() => {
32
34
  if (SUPPORTS_STYLE_HOIST) return;
33
- if (typeof document === "undefined" || document.getElementById(id)) return;
34
- const el = document.createElement("style");
35
- el.id = id;
36
- el.textContent = css;
37
- document.head.appendChild(el);
38
- }, [id, css]);
39
- return SUPPORTS_STYLE_HOIST ? React25__namespace.createElement("style", { href: id, precedence: "twc-ui" }, css) : null;
35
+ if (typeof document === "undefined") return;
36
+ if (!css) return;
37
+ let el = document.getElementById(id);
38
+ if (!el) {
39
+ el = document.createElement("style");
40
+ el.id = id;
41
+ if (nonce) {
42
+ el.setAttribute("nonce", nonce);
43
+ el.nonce = nonce;
44
+ }
45
+ document.head.appendChild(el);
46
+ }
47
+ if (el.textContent !== css) el.textContent = css;
48
+ }, [id, css, nonce]);
49
+ return SUPPORTS_STYLE_HOIST && css ? React37__namespace.createElement("style", { href: id, precedence: "twc-ui", nonce }, css) : null;
50
+ }
51
+
52
+ // components/TwicoProvider.jsx
53
+ function TwicoProvider({ nonce, children }) {
54
+ return React37__namespace.default.createElement(NonceContext.Provider, { value: nonce }, children);
55
+ }
56
+ var GROUPS = { colors: "color", space: "space", radius: "radius", font: "font", shadow: "shadow", motion: "" };
57
+ function createTheme(partial = {}) {
58
+ const vars = {};
59
+ for (const [group, prefix] of Object.entries(GROUPS)) {
60
+ const obj = partial[group];
61
+ if (!obj || typeof obj !== "object") continue;
62
+ for (const [key, value] of Object.entries(obj)) {
63
+ if (value == null) continue;
64
+ vars[`--${prefix ? `${prefix}-` : ""}${key}`] = String(value);
65
+ }
66
+ }
67
+ return vars;
68
+ }
69
+ function toVars(theme) {
70
+ if (!theme) return {};
71
+ return Object.keys(theme).some((k) => k.startsWith("--")) ? theme : createTheme(theme);
72
+ }
73
+ function ThemeProvider({ theme, mode = "inline", className = "", style, children, ...rest }) {
74
+ const vars = React37__namespace.default.useMemo(() => toVars(theme), [theme]);
75
+ const uid = React37__namespace.default.useId();
76
+ const scopeId = `twc-theme-${uid.replace(/[^a-zA-Z0-9]/g, "")}`;
77
+ const css = mode === "stylesheet" ? `[data-twc-theme="${scopeId}"] { ${Object.entries(vars).map(([k, v]) => `${k}: ${v};`).join(" ")} }` : "";
78
+ const __twcStyles = useScopedStyles(mode === "stylesheet" ? scopeId : "twc-theme-noop", css);
79
+ return /* @__PURE__ */ jsxRuntime.jsxs(
80
+ "div",
81
+ {
82
+ className: `twc-theme ${className}`.trim(),
83
+ "data-twc-theme": mode === "stylesheet" ? scopeId : void 0,
84
+ style: mode === "stylesheet" ? style : { ...vars, ...style },
85
+ ...rest,
86
+ children: [
87
+ mode === "stylesheet" ? __twcStyles : null,
88
+ children
89
+ ]
90
+ }
91
+ );
40
92
  }
93
+ var FORM_CSS = `
94
+ .twc-form { display: flex; flex-direction: column; gap: var(--space-4); font-family: var(--font-sans); }
95
+ .twc-form__fieldset { border: 0; margin: 0; padding: 0; min-width: 0; display: flex; flex-direction: column; gap: inherit; }
96
+ `;
97
+ var Form = React37__namespace.default.forwardRef(function Form2({
98
+ onSubmit,
99
+ preventDefault = true,
100
+ loading = false,
101
+ disabled = false,
102
+ gap,
103
+ className = "",
104
+ style,
105
+ children,
106
+ ...rest
107
+ }, ref) {
108
+ const __twcStyles = useScopedStyles("twc-form-styles", FORM_CSS);
109
+ const handleSubmit = (e) => {
110
+ if (preventDefault) e.preventDefault();
111
+ onSubmit?.(e);
112
+ };
113
+ return /* @__PURE__ */ jsxRuntime.jsxs(
114
+ "form",
115
+ {
116
+ ref,
117
+ className: `twc-form ${className}`.trim(),
118
+ onSubmit: handleSubmit,
119
+ style: gap != null ? { gap: `var(--space-${gap})`, ...style } : style,
120
+ ...rest,
121
+ children: [
122
+ __twcStyles,
123
+ /* @__PURE__ */ jsxRuntime.jsx("fieldset", { className: "twc-form__fieldset", disabled: loading || disabled || void 0, "aria-busy": loading || void 0, children })
124
+ ]
125
+ }
126
+ );
127
+ });
128
+ Form.displayName = "Form";
129
+ var VH_CSS = `
130
+ .twc-visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
131
+ `;
132
+ var VisuallyHidden = React37__namespace.default.forwardRef(function VisuallyHidden2({ as: Tag2 = "span", className = "", children, ...rest }, ref) {
133
+ const __twcStyles = useScopedStyles("twc-visually-hidden-styles", VH_CSS);
134
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tag2, { ref, className: `twc-visually-hidden ${className}`.trim(), ...rest, children: [
135
+ __twcStyles,
136
+ children
137
+ ] });
138
+ });
139
+ VisuallyHidden.displayName = "VisuallyHidden";
140
+ var canUseDOM = typeof window !== "undefined" && typeof document !== "undefined";
141
+ var useIsoLayoutEffect = canUseDOM ? React37__namespace.default.useLayoutEffect : React37__namespace.default.useEffect;
142
+ var FOCUSABLE = 'a[href]:not([tabindex="-1"]), button:not([disabled]):not([tabindex="-1"]), textarea:not([disabled]):not([tabindex="-1"]), input:not([disabled]):not([tabindex="-1"]), select:not([disabled]):not([tabindex="-1"]), [tabindex]:not([tabindex="-1"])';
143
+ function useFocusTrap(ref, active = true, { restoreFocus = true, initialFocus } = {}) {
144
+ React37__namespace.default.useEffect(() => {
145
+ if (!active || !canUseDOM) return void 0;
146
+ const node = ref.current;
147
+ if (!node) return void 0;
148
+ const prevFocused = document.activeElement;
149
+ const target = (typeof initialFocus === "function" ? initialFocus() : initialFocus && initialFocus.current) || node.querySelector(FOCUSABLE);
150
+ (target || node).focus();
151
+ return () => {
152
+ if (restoreFocus && prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
153
+ };
154
+ }, [active]);
155
+ React37__namespace.default.useEffect(() => {
156
+ if (!active || !canUseDOM) return void 0;
157
+ const node = ref.current;
158
+ const onKey = (e) => {
159
+ if (e.key !== "Tab" || !node) return;
160
+ const f = Array.from(node.querySelectorAll(FOCUSABLE)).filter((el) => el.offsetParent !== null);
161
+ if (!f.length) {
162
+ e.preventDefault();
163
+ node.focus();
164
+ return;
165
+ }
166
+ const first = f[0], last = f[f.length - 1], ae = document.activeElement;
167
+ if (e.shiftKey) {
168
+ if (ae === first || ae === node || !node.contains(ae)) {
169
+ e.preventDefault();
170
+ last.focus();
171
+ }
172
+ } else if (ae === last || !node.contains(ae)) {
173
+ e.preventDefault();
174
+ first.focus();
175
+ }
176
+ };
177
+ document.addEventListener("keydown", onKey);
178
+ return () => document.removeEventListener("keydown", onKey);
179
+ }, [active]);
180
+ }
181
+ function usePortal() {
182
+ return React37__namespace.default.useCallback((node) => {
183
+ if (typeof document === "undefined") return null;
184
+ return typeof reactDom.createPortal === "function" ? reactDom.createPortal(node, document.body) : node;
185
+ }, []);
186
+ }
187
+ var __scrollLockCount = 0;
188
+ var __scrollLockSaved = { overflow: "", paddingRight: "" };
189
+ function useScrollLock(locked = true) {
190
+ useIsoLayoutEffect(() => {
191
+ if (!canUseDOM || !locked) return void 0;
192
+ if (__scrollLockCount === 0) {
193
+ const b = document.body;
194
+ __scrollLockSaved = { overflow: b.style.overflow, paddingRight: b.style.paddingRight };
195
+ const gutter = window.innerWidth - document.documentElement.clientWidth;
196
+ b.style.overflow = "hidden";
197
+ if (gutter > 0) b.style.paddingRight = `${(parseFloat(getComputedStyle(b).paddingRight) || 0) + gutter}px`;
198
+ }
199
+ __scrollLockCount += 1;
200
+ return () => {
201
+ __scrollLockCount -= 1;
202
+ if (__scrollLockCount === 0) {
203
+ document.body.style.overflow = __scrollLockSaved.overflow;
204
+ document.body.style.paddingRight = __scrollLockSaved.paddingRight;
205
+ }
206
+ };
207
+ }, [locked]);
208
+ }
209
+ function useInertBackground(ref, active) {
210
+ React37__namespace.default.useEffect(() => {
211
+ if (!active || !canUseDOM) return void 0;
212
+ const node = ref.current;
213
+ if (!node) return void 0;
214
+ const changed = [];
215
+ Array.from(document.body.children).forEach((el) => {
216
+ if (el.contains(node) || el.hasAttribute("aria-hidden") || el.inert) return;
217
+ el.inert = true;
218
+ el.setAttribute("aria-hidden", "true");
219
+ changed.push(el);
220
+ });
221
+ return () => {
222
+ changed.forEach((el) => {
223
+ el.inert = false;
224
+ el.removeAttribute("aria-hidden");
225
+ });
226
+ };
227
+ }, [active]);
228
+ }
229
+
230
+ // components/layout/Portal.jsx
231
+ function Portal({ children }) {
232
+ const render = usePortal();
233
+ return render(children);
234
+ }
235
+ function getColorSchemeScript({ storageKey = "twico-theme", attribute = "class", defaultScheme } = {}) {
236
+ const k = JSON.stringify(storageKey);
237
+ const a = JSON.stringify(attribute);
238
+ const d = defaultScheme === "dark" || defaultScheme === "light" ? JSON.stringify(defaultScheme) : "null";
239
+ return `(function(){try{var k=${k},a=${a},d=${d},t=localStorage.getItem(k);if(t!=='light'){if(t!=='dark'){t=d?d:(window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light');}}if(a==='class'){document.documentElement.classList.toggle('dark',t==='dark');}else{document.documentElement.setAttribute(a,t);}}catch(e){}})();`;
240
+ }
241
+ function ColorSchemeScript({ storageKey = "twico-theme", attribute = "class", nonce, defaultScheme }) {
242
+ return React37__namespace.default.createElement("script", { nonce }, getColorSchemeScript({ storageKey, attribute, defaultScheme }));
243
+ }
244
+ var KBD_CSS = `
245
+ .twc-kbd { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; padding: 2px 6px;
246
+ font-family: var(--font-mono); font-size: 11px; font-weight: var(--font-semibold); line-height: 1; color: var(--color-text-muted);
247
+ background: var(--color-surface-sunken); border: var(--border-thin) solid var(--color-border);
248
+ border-bottom-width: 2px; border-radius: var(--radius-sm); }
249
+ `;
250
+ var Kbd = React37__namespace.default.forwardRef(function Kbd2({ className = "", children, ...rest }, ref) {
251
+ const __twcStyles = useScopedStyles("twc-kbd-styles", KBD_CSS);
252
+ return /* @__PURE__ */ jsxRuntime.jsxs("kbd", { ref, className: `twc-kbd ${className}`.trim(), ...rest, children: [
253
+ __twcStyles,
254
+ children
255
+ ] });
256
+ });
257
+ Kbd.displayName = "Kbd";
258
+ var PRE_CSS = `
259
+ .twc-pre { margin: 0; padding: var(--space-4); overflow-x: auto; max-width: 100%;
260
+ font-family: var(--font-mono); font-size: var(--text-sm); line-height: var(--leading-normal);
261
+ color: var(--color-text); background: var(--color-surface-sunken);
262
+ border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-lg);
263
+ white-space: pre; -webkit-overflow-scrolling: touch; }
264
+ `;
265
+ var Pre = React37__namespace.default.forwardRef(function Pre2({ className = "", children, ...rest }, ref) {
266
+ const __twcStyles = useScopedStyles("twc-pre-styles", PRE_CSS);
267
+ return /* @__PURE__ */ jsxRuntime.jsxs("pre", { ref, className: `twc-pre ${className}`.trim(), ...rest, children: [
268
+ __twcStyles,
269
+ children
270
+ ] });
271
+ });
272
+ Pre.displayName = "Pre";
273
+ var ANCHOR_CSS = `
274
+ .twc-anchor { color: var(--color-primary); text-decoration: none; border-radius: var(--radius-sm);
275
+ transition: color var(--duration-fast) var(--ease-standard); }
276
+ .twc-anchor:hover { text-decoration: underline; color: var(--color-primary-hover, var(--color-primary)); }
277
+ .twc-anchor:focus-visible { outline: none; box-shadow: var(--ring); }
278
+ .twc-anchor__ext { display: inline-block; margin-inline-start: 3px; font-size: 0.85em; vertical-align: baseline; }
279
+ `;
280
+ function safeHref(url) {
281
+ if (url == null) return void 0;
282
+ const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
283
+ return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
284
+ }
285
+ var Anchor = React37__namespace.default.forwardRef(function Anchor2({ as: Tag2 = "a", href, external = false, className = "", children, ...rest }, ref) {
286
+ const __twcStyles = useScopedStyles("twc-anchor-styles", ANCHOR_CSS);
287
+ const extra = external ? { target: "_blank", rel: "noopener noreferrer" } : {};
288
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tag2, { ref, className: `twc-anchor ${className}`.trim(), href: Tag2 === "a" ? safeHref(href) : href, ...extra, ...rest, children: [
289
+ __twcStyles,
290
+ children,
291
+ external ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-anchor__ext", "aria-hidden": "true", children: "\u2197" }) : null
292
+ ] });
293
+ });
294
+ Anchor.displayName = "Anchor";
295
+ var LABEL_CSS = `
296
+ .twc-label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); display: inline-flex; gap: 4px; align-items: center; }
297
+ .twc-label[data-size="sm"] { font-size: var(--text-xs); }
298
+ .twc-label[data-size="lg"] { font-size: var(--text-base); }
299
+ .twc-label__req { color: var(--color-danger); }
300
+ `;
301
+ var Label = React37__namespace.default.forwardRef(function Label2({ htmlFor, required = false, size = "md", className = "", children, ...rest }, ref) {
302
+ const __twcStyles = useScopedStyles("twc-label-styles", LABEL_CSS);
303
+ return /* @__PURE__ */ jsxRuntime.jsxs("label", { ref, htmlFor, className: `twc-label ${className}`.trim(), "data-size": size, ...rest, children: [
304
+ __twcStyles,
305
+ children,
306
+ required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-label__req", "aria-hidden": "true", children: "*" }) : null
307
+ ] });
308
+ });
309
+ Label.displayName = "Label";
310
+ var IMAGE_CSS = `
311
+ .twc-image { display: block; max-width: 100%; }
312
+ .twc-image[data-fit] { width: 100%; height: 100%; }
313
+ `;
314
+ var Image = React37__namespace.default.forwardRef(function Image2({
315
+ src,
316
+ alt,
317
+ fit,
318
+ radius,
319
+ aspectRatio,
320
+ fallback,
321
+ loading = "lazy",
322
+ className = "",
323
+ style,
324
+ onError,
325
+ ...rest
326
+ }, ref) {
327
+ const __twcStyles = useScopedStyles("twc-image-styles", IMAGE_CSS);
328
+ const [failed, setFailed] = React37__namespace.default.useState(false);
329
+ const shownSrc = failed && fallback ? fallback : src;
330
+ const s = {
331
+ objectFit: fit,
332
+ borderRadius: radius ? `var(--radius-${radius})` : void 0,
333
+ aspectRatio,
334
+ ...style
335
+ };
336
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
337
+ __twcStyles,
338
+ /* @__PURE__ */ jsxRuntime.jsx(
339
+ "img",
340
+ {
341
+ ref,
342
+ src: shownSrc,
343
+ alt,
344
+ loading,
345
+ className: `twc-image ${className}`.trim(),
346
+ "data-fit": fit || void 0,
347
+ style: s,
348
+ onError: (e) => {
349
+ onError?.(e);
350
+ if (fallback && !failed) setFailed(true);
351
+ },
352
+ ...rest
353
+ }
354
+ )
355
+ ] });
356
+ });
357
+ Image.displayName = "Image";
41
358
  var ACCORDION_CSS = `
42
359
  .twc-accordion { display: flex; flex-direction: column; font-family: var(--font-sans);
43
360
  border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-lg); overflow: hidden; background: var(--color-surface); }
@@ -77,10 +394,10 @@ function Accordion({
77
394
  ...rest
78
395
  }) {
79
396
  const __twcStyles = useScopedStyles("twc-accordion-styles", ACCORDION_CSS);
80
- const rootRef = React25__namespace.default.useRef(null);
81
- const [internal, setInternal] = React25__namespace.default.useState(() => new Set(defaultOpen));
397
+ const rootRef = React37__namespace.default.useRef(null);
398
+ const [internal, setInternal] = React37__namespace.default.useState(() => new Set(defaultOpen));
82
399
  const open = openProp !== void 0 ? new Set(openProp) : internal;
83
- const baseId = React25__namespace.default.useId();
400
+ const baseId = React37__namespace.default.useId();
84
401
  function toggle(val) {
85
402
  const item = items.find((x) => x.value === val);
86
403
  if (item?.disabled) return;
@@ -127,9 +444,9 @@ function Accordion({
127
444
  const triggerId = `${baseId}-trigger-${i}`;
128
445
  const panelId = `${baseId}-panel-${i}`;
129
446
  const lvl = Math.min(6, Math.max(1, it.headingLevel ?? headingLevel));
130
- const Heading2 = `h${lvl}`;
447
+ const Heading3 = `h${lvl}`;
131
448
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-accordion__item", children: [
132
- /* @__PURE__ */ jsxRuntime.jsx(Heading2, { className: "twc-accordion__heading", children: /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", id: triggerId, className: "twc-accordion__trigger", "data-open": isOpen || void 0, disabled: it.disabled || void 0, "aria-disabled": it.disabled || void 0, "data-disabled": it.disabled || void 0, "aria-expanded": isOpen, "aria-controls": panelId, onClick: () => toggle(it.value), children: [
449
+ /* @__PURE__ */ jsxRuntime.jsx(Heading3, { className: "twc-accordion__heading", children: /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", id: triggerId, className: "twc-accordion__trigger", "data-open": isOpen || void 0, disabled: it.disabled || void 0, "aria-disabled": it.disabled || void 0, "data-disabled": it.disabled || void 0, "aria-expanded": isOpen, "aria-controls": panelId, onClick: () => toggle(it.value), children: [
133
450
  it.icon,
134
451
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-accordion__label", children: it.label }),
135
452
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-accordion__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" }) }) })
@@ -266,7 +583,7 @@ function Avatar({
266
583
  ...rest
267
584
  }) {
268
585
  const __twcStyles = useScopedStyles("twc-avatar-styles", AVATAR_CSS);
269
- const [errored, setErrored] = React25__namespace.default.useState(false);
586
+ const [errored, setErrored] = React37__namespace.default.useState(false);
270
587
  const cleanSrc = safeSrc(src);
271
588
  const showImg = cleanSrc && !errored;
272
589
  const _statusLabel = status ? statusLabel ?? statusLabels?.[status] ?? STATUS_LABELS[status] : void 0;
@@ -324,7 +641,7 @@ var MENU_CSS = `
324
641
  .twc-menu__item-label { flex: 1 1 auto; min-width: 0; }
325
642
  .twc-menu__shortcut { margin-inline-start: auto; padding-inline-start: var(--space-3); font-size: var(--text-xs); color: var(--color-text-subtle); font-family: var(--font-mono); }
326
643
  `;
327
- var safeHref = (url) => {
644
+ var safeHref2 = (url) => {
328
645
  if (url == null) return void 0;
329
646
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
330
647
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -344,25 +661,25 @@ function Menu({
344
661
  ...rest
345
662
  }) {
346
663
  const __twcStyles = useScopedStyles("twc-menu-styles", MENU_CSS);
347
- const [openState, setOpenState] = React25__namespace.default.useState(defaultOpen);
348
- const [render, setRender] = React25__namespace.default.useState(false);
349
- const [pos, setPos] = React25__namespace.default.useState(null);
350
- const [active, setActive] = React25__namespace.default.useState(-1);
351
- const wrapRef = React25__namespace.default.useRef(null);
352
- const menuRef = React25__namespace.default.useRef(null);
353
- const typeBufRef = React25__namespace.default.useRef("");
354
- const typeTimerRef = React25__namespace.default.useRef(null);
355
- const menuId = React25__namespace.default.useId();
664
+ const [openState, setOpenState] = React37__namespace.default.useState(defaultOpen);
665
+ const [render, setRender] = React37__namespace.default.useState(false);
666
+ const [pos, setPos] = React37__namespace.default.useState(null);
667
+ const [active, setActive] = React37__namespace.default.useState(-1);
668
+ const wrapRef = React37__namespace.default.useRef(null);
669
+ const menuRef = React37__namespace.default.useRef(null);
670
+ const typeBufRef = React37__namespace.default.useRef("");
671
+ const typeTimerRef = React37__namespace.default.useRef(null);
672
+ const menuId = React37__namespace.default.useId();
356
673
  const headerId = `${menuId}-header`;
357
674
  const controlled = openProp !== void 0;
358
675
  const open = controlled ? !!openProp : openState;
359
- const openRef = React25__namespace.default.useRef(open);
676
+ const openRef = React37__namespace.default.useRef(open);
360
677
  openRef.current = open;
361
- const controlledRef = React25__namespace.default.useRef(controlled);
678
+ const controlledRef = React37__namespace.default.useRef(controlled);
362
679
  controlledRef.current = controlled;
363
- const onOpenChangeRef = React25__namespace.default.useRef(onOpenChange);
680
+ const onOpenChangeRef = React37__namespace.default.useRef(onOpenChange);
364
681
  onOpenChangeRef.current = onOpenChange;
365
- const setOpen = React25__namespace.default.useCallback((next) => {
682
+ const setOpen = React37__namespace.default.useCallback((next) => {
366
683
  const value = typeof next === "function" ? next(openRef.current) : next;
367
684
  if (value === openRef.current) return;
368
685
  if (!controlledRef.current) setOpenState(value);
@@ -370,7 +687,7 @@ function Menu({
370
687
  }, []);
371
688
  const RD = { createPortal: typeof reactDom.createPortal === "function" ? reactDom.createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
372
689
  const interactiveIdx = items.map((it, i) => !it.separator && !it.heading ? i : -1).filter((i) => i >= 0);
373
- const place = React25__namespace.default.useCallback(() => {
690
+ const place = React37__namespace.default.useCallback(() => {
374
691
  const t = wrapRef.current;
375
692
  if (!t) return;
376
693
  const r = t.getBoundingClientRect();
@@ -385,7 +702,7 @@ function Menu({
385
702
  const avail = (flip ? r.top : vh - r.bottom) - gap - M;
386
703
  setPos({ top, bottom, left, width: w, flip, maxHeight: Math.max(120, avail) });
387
704
  }, [align, width]);
388
- React25__namespace.default.useEffect(() => {
705
+ React37__namespace.default.useEffect(() => {
389
706
  if (!open) return;
390
707
  place();
391
708
  const onMove = () => place();
@@ -403,7 +720,7 @@ function Menu({
403
720
  document.removeEventListener("mousedown", onDown);
404
721
  };
405
722
  }, [open, place]);
406
- React25__namespace.default.useEffect(() => {
723
+ React37__namespace.default.useEffect(() => {
407
724
  if (open) {
408
725
  setRender(true);
409
726
  return;
@@ -496,7 +813,7 @@ function Menu({
496
813
  items.map((it, i) => {
497
814
  if (it.separator) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-menu__sep", role: "separator" }, `s${i}`);
498
815
  if (it.label && it.heading) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-menu__label", children: it.label }, `h${i}`);
499
- const href = !it.disabled ? safeHref(it.href) : void 0;
816
+ const href = !it.disabled ? safeHref2(it.href) : void 0;
500
817
  const Tag2 = href ? "a" : "button";
501
818
  return /* @__PURE__ */ jsxRuntime.jsxs(
502
819
  Tag2,
@@ -526,7 +843,7 @@ function Menu({
526
843
  }
527
844
  ) : null;
528
845
  const activeDescId = open && active >= 0 ? `${menuId}-item-${active}` : void 0;
529
- const triggerEl = React25__namespace.default.isValidElement(trigger) ? React25__namespace.default.cloneElement(trigger, {
846
+ const triggerEl = React37__namespace.default.isValidElement(trigger) ? React37__namespace.default.cloneElement(trigger, {
530
847
  onClick: (e) => {
531
848
  trigger.props.onClick?.(e);
532
849
  toggle();
@@ -677,7 +994,7 @@ a.twc-breadcrumb__item:hover, button.twc-breadcrumb__item:hover { color: var(--c
677
994
  .twc-breadcrumb__ellipsis { border: none; background: transparent; cursor: pointer; color: var(--color-text-subtle); padding: 3px 7px; border-radius: var(--radius-sm); font: inherit; }
678
995
  .twc-breadcrumb__ellipsis:hover { background: var(--color-surface-sunken); color: var(--color-text); }
679
996
  `;
680
- function safeHref2(url) {
997
+ function safeHref3(url) {
681
998
  if (url == null) return void 0;
682
999
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
683
1000
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -691,7 +1008,7 @@ function Breadcrumb({
691
1008
  ...rest
692
1009
  }) {
693
1010
  const __twcStyles = useScopedStyles("twc-breadcrumb-styles", BREADCRUMB_CSS);
694
- const [expanded, setExpanded] = React25__namespace.default.useState(false);
1011
+ const [expanded, setExpanded] = React37__namespace.default.useState(false);
695
1012
  const sep = separator || /* @__PURE__ */ jsxRuntime.jsx(ChevronSep, {});
696
1013
  let display = items;
697
1014
  if (maxItems > 0 && items.length > maxItems && !expanded) {
@@ -704,7 +1021,7 @@ function Breadcrumb({
704
1021
  __twcStyles,
705
1022
  display.map((it, i) => {
706
1023
  const last = i === display.length - 1;
707
- return /* @__PURE__ */ jsxRuntime.jsxs(React25__namespace.default.Fragment, { children: [
1024
+ return /* @__PURE__ */ jsxRuntime.jsxs(React37__namespace.default.Fragment, { children: [
708
1025
  it.ellipsis ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-breadcrumb__ellipsis", "aria-label": "Show more", onClick: () => setExpanded(true), children: "\u2026" }) : last ? /* @__PURE__ */ jsxRuntime.jsxs(
709
1026
  "span",
710
1027
  {
@@ -716,7 +1033,7 @@ function Breadcrumb({
716
1033
  it.label
717
1034
  ]
718
1035
  }
719
- ) : safeHref2(it.href) ? /* @__PURE__ */ jsxRuntime.jsxs("a", { className: "twc-breadcrumb__item", href: safeHref2(it.href), onClick: it.onClick, children: [
1036
+ ) : safeHref3(it.href) ? /* @__PURE__ */ jsxRuntime.jsxs("a", { className: "twc-breadcrumb__item", href: safeHref3(it.href), onClick: it.onClick, children: [
720
1037
  it.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { display: "inline-flex" }, children: it.icon }) : null,
721
1038
  it.label
722
1039
  ] }) : it.onClick ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "twc-breadcrumb__item", onClick: it.onClick, children: [
@@ -824,7 +1141,7 @@ var CSS2 = `
824
1141
  animation: twico-ripple var(--duration-slow) var(--ease-out) forwards;
825
1142
  }
826
1143
  `;
827
- function safeHref3(url) {
1144
+ function safeHref4(url) {
828
1145
  if (url == null) return void 0;
829
1146
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
830
1147
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -846,7 +1163,7 @@ function Button({
846
1163
  ...rest
847
1164
  }) {
848
1165
  const __twcStyles = useScopedStyles("twc-btn-styles", CSS2);
849
- const [ripples, setRipples] = React25__namespace.default.useState([]);
1166
+ const [ripples, setRipples] = React37__namespace.default.useState([]);
850
1167
  const Tag2 = as;
851
1168
  const inert = Tag2 === "a" && (disabled || loading);
852
1169
  function handleClick(e) {
@@ -875,7 +1192,7 @@ function Button({
875
1192
  "data-block": fullWidth || void 0,
876
1193
  disabled: Tag2 === "button" ? disabled || loading : void 0,
877
1194
  type: Tag2 === "button" ? "button" : void 0,
878
- href: inert ? void 0 : safeHref3(href),
1195
+ href: inert ? void 0 : safeHref4(href),
879
1196
  "aria-disabled": inert || void 0,
880
1197
  tabIndex: inert ? -1 : void 0,
881
1198
  "aria-busy": loading || void 0,
@@ -901,6 +1218,122 @@ function Button({
901
1218
  }
902
1219
  );
903
1220
  }
1221
+ var UNITLESS = /* @__PURE__ */ new Set([
1222
+ "animationIterationCount",
1223
+ "aspectRatio",
1224
+ "borderImageOutset",
1225
+ "borderImageSlice",
1226
+ "borderImageWidth",
1227
+ "boxFlex",
1228
+ "boxFlexGroup",
1229
+ "boxOrdinalGroup",
1230
+ "columnCount",
1231
+ "columns",
1232
+ "flex",
1233
+ "flexGrow",
1234
+ "flexShrink",
1235
+ "flexPositive",
1236
+ "flexNegative",
1237
+ "flexOrder",
1238
+ "gridArea",
1239
+ "gridRow",
1240
+ "gridRowEnd",
1241
+ "gridRowSpan",
1242
+ "gridRowStart",
1243
+ "gridColumn",
1244
+ "gridColumnEnd",
1245
+ "gridColumnSpan",
1246
+ "gridColumnStart",
1247
+ "fontWeight",
1248
+ "lineClamp",
1249
+ "lineHeight",
1250
+ "opacity",
1251
+ "order",
1252
+ "orphans",
1253
+ "tabSize",
1254
+ "widows",
1255
+ "zIndex",
1256
+ "zoom",
1257
+ "fillOpacity",
1258
+ "floodOpacity",
1259
+ "stopOpacity",
1260
+ "strokeDasharray",
1261
+ "strokeDashoffset",
1262
+ "strokeMiterlimit",
1263
+ "strokeOpacity",
1264
+ "strokeWidth",
1265
+ "scale"
1266
+ ]);
1267
+ var isObject = (v) => v != null && typeof v === "object" && !Array.isArray(v);
1268
+ var isNestedKey = (k, v) => isObject(v) || k.charCodeAt(0) === 38 || k.charCodeAt(0) === 64 || k.charCodeAt(0) === 58;
1269
+ function kebab(prop) {
1270
+ if (prop.startsWith("--")) return prop;
1271
+ return prop.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
1272
+ }
1273
+ function cssValue(key, value) {
1274
+ if (typeof value !== "number") return String(value);
1275
+ if (value === 0 || key.startsWith("--") || UNITLESS.has(key)) return String(value);
1276
+ return `${value}px`;
1277
+ }
1278
+ function resolveSelector(key, scope) {
1279
+ if (key.includes("&")) return key.replace(/&/g, scope);
1280
+ if (key.charCodeAt(0) === 58) return `${scope}${key}`;
1281
+ return `${scope} ${key}`;
1282
+ }
1283
+ function compileSx(obj, selector) {
1284
+ if (!isObject(obj)) return "";
1285
+ let decls = "";
1286
+ let rules = "";
1287
+ for (const key of Object.keys(obj)) {
1288
+ const value = obj[key];
1289
+ if (isNestedKey(key, value)) {
1290
+ if (!isObject(value)) continue;
1291
+ if (key.charCodeAt(0) === 64) {
1292
+ const inner = compileSx(value, selector);
1293
+ if (inner) rules += `${key} { ${inner.trim()} }
1294
+ `;
1295
+ } else {
1296
+ rules += compileSx(value, resolveSelector(key, selector));
1297
+ }
1298
+ } else {
1299
+ decls += `${kebab(key)}: ${cssValue(key, value)}; `;
1300
+ }
1301
+ }
1302
+ let out = "";
1303
+ if (decls) out += `${selector} { ${decls.trimEnd()} }
1304
+ `;
1305
+ out += rules;
1306
+ return out;
1307
+ }
1308
+ function buildSx(sx, uid) {
1309
+ if (!isObject(sx)) return { flatStyle: void 0, css: "" };
1310
+ const scope = `[data-twc-sx="${uid}"]`;
1311
+ let flatStyle;
1312
+ let css = "";
1313
+ for (const key of Object.keys(sx)) {
1314
+ const value = sx[key];
1315
+ if (isNestedKey(key, value)) {
1316
+ if (!isObject(value)) continue;
1317
+ if (key.charCodeAt(0) === 64) {
1318
+ const inner = compileSx(value, scope);
1319
+ if (inner) css += `${key} { ${inner.trim()} }
1320
+ `;
1321
+ } else {
1322
+ css += compileSx(value, resolveSelector(key, scope));
1323
+ }
1324
+ } else {
1325
+ (flatStyle || (flatStyle = {}))[key] = value;
1326
+ }
1327
+ }
1328
+ return { flatStyle, css };
1329
+ }
1330
+ function useSx(sx) {
1331
+ const rawId = React37__namespace.default.useId();
1332
+ const uid = `sx${rawId.replace(/[^a-zA-Z0-9]/g, "")}`;
1333
+ const { flatStyle, css } = React37__namespace.default.useMemo(() => buildSx(sx, uid), [sx, uid]);
1334
+ const styleNode = useScopedStyles(`twc-sx-${uid}`, css);
1335
+ return { flatStyle, styleNode, sxAttr: css ? uid : void 0 };
1336
+ }
904
1337
  var CARD_CSS = `
905
1338
  .twc-card {
906
1339
  display: flex; flex-direction: column;
@@ -940,10 +1373,13 @@ function Card({
940
1373
  padding = "md",
941
1374
  interactive = false,
942
1375
  fullHeight = false,
1376
+ sx,
943
1377
  className = "",
1378
+ style,
944
1379
  ...rest
945
1380
  }) {
946
1381
  const __twcStyles = useScopedStyles("twc-card-styles", CARD_CSS);
1382
+ const { flatStyle, styleNode, sxAttr } = useSx(sx);
947
1383
  return /* @__PURE__ */ jsxRuntime.jsxs(
948
1384
  "div",
949
1385
  {
@@ -952,9 +1388,12 @@ function Card({
952
1388
  "data-pad": padding,
953
1389
  "data-interactive": interactive || void 0,
954
1390
  "data-full": fullHeight || void 0,
1391
+ "data-twc-sx": sxAttr,
1392
+ style: style || flatStyle ? { ...style, ...flatStyle } : void 0,
955
1393
  ...rest,
956
1394
  children: [
957
1395
  __twcStyles,
1396
+ styleNode,
958
1397
  title || subtitle || actions ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-card__header", children: [
959
1398
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-card__heading", children: [
960
1399
  title ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-card__title", children: title }) : null,
@@ -1020,14 +1459,14 @@ function Carousel({
1020
1459
  ...rest
1021
1460
  }) {
1022
1461
  const __twcStyles = useScopedStyles("twc-carousel-styles", CAROUSEL_CSS);
1023
- const slides = React25__namespace.default.Children.toArray(children);
1462
+ const slides = React37__namespace.default.Children.toArray(children);
1024
1463
  const count = slides.length;
1025
- const [internal, setInternal] = React25__namespace.default.useState(defaultIndex);
1464
+ const [internal, setInternal] = React37__namespace.default.useState(defaultIndex);
1026
1465
  const index = indexProp !== void 0 ? indexProp : internal;
1027
- const [paused, setPaused] = React25__namespace.default.useState(false);
1028
- const [userPaused, setUserPaused] = React25__namespace.default.useState(false);
1029
- const [prefersReduced, setPrefersReduced] = React25__namespace.default.useState(false);
1030
- React25__namespace.default.useEffect(() => {
1466
+ const [paused, setPaused] = React37__namespace.default.useState(false);
1467
+ const [userPaused, setUserPaused] = React37__namespace.default.useState(false);
1468
+ const [prefersReduced, setPrefersReduced] = React37__namespace.default.useState(false);
1469
+ React37__namespace.default.useEffect(() => {
1031
1470
  if (typeof window === "undefined" || !window.matchMedia) return void 0;
1032
1471
  const mql = window.matchMedia("(prefers-reduced-motion: reduce)");
1033
1472
  const on = () => setPrefersReduced(mql.matches);
@@ -1035,15 +1474,15 @@ function Carousel({
1035
1474
  mql.addEventListener("change", on);
1036
1475
  return () => mql.removeEventListener("change", on);
1037
1476
  }, []);
1038
- const setIndex = React25__namespace.default.useCallback((i) => {
1477
+ const setIndex = React37__namespace.default.useCallback((i) => {
1039
1478
  if (indexProp === void 0) setInternal(i);
1040
1479
  onIndexChange?.(i);
1041
1480
  }, [indexProp, onIndexChange]);
1042
- const go = React25__namespace.default.useCallback((i) => {
1481
+ const go = React37__namespace.default.useCallback((i) => {
1043
1482
  setIndex(loop ? (i + count) % count : Math.min(Math.max(i, 0), count - 1));
1044
1483
  }, [count, loop, setIndex]);
1045
1484
  const autoRotating = autoPlay && !paused && !userPaused && !prefersReduced && count > 1;
1046
- React25__namespace.default.useEffect(() => {
1485
+ React37__namespace.default.useEffect(() => {
1047
1486
  if (!autoRotating) return void 0;
1048
1487
  const t = setInterval(() => {
1049
1488
  const next = loop ? (index + 1) % count : index + 1 >= count ? index : index + 1;
@@ -1138,7 +1577,7 @@ function Chart({
1138
1577
  ...rest
1139
1578
  }) {
1140
1579
  const __twcStyles = useScopedStyles("twc-chart-styles", CHART_CSS);
1141
- const uid = React25__namespace.default.useId();
1580
+ const uid = React37__namespace.default.useId();
1142
1581
  const tableId = tableFallback ? `${uid}-table` : void 0;
1143
1582
  const keys = series || ["value"];
1144
1583
  const palette = colors && colors.length ? colors : SERIES_COLORS;
@@ -1294,13 +1733,13 @@ function Checkbox({
1294
1733
  .twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
1295
1734
  .twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
1296
1735
  `);
1297
- const autoId = React25__namespace.default.useId();
1736
+ const autoId = React37__namespace.default.useId();
1298
1737
  const fieldId = id || autoId;
1299
1738
  const errId = `${fieldId}-error`;
1300
1739
  const invalid = Boolean(error);
1301
- const ref = React25__namespace.default.useRef(null);
1740
+ const ref = React37__namespace.default.useRef(null);
1302
1741
  const mixed = indeterminate && !checked;
1303
- React25__namespace.default.useEffect(() => {
1742
+ React37__namespace.default.useEffect(() => {
1304
1743
  if (ref.current) ref.current.indeterminate = mixed;
1305
1744
  }, [mixed]);
1306
1745
  if (process.env.NODE_ENV !== "production" && !label && !description && !rest["aria-label"] && !rest["aria-labelledby"]) {
@@ -1373,6 +1812,10 @@ var COLORPICKER_CSS = `
1373
1812
  .twc-cp__hue { position: relative; height: 12px; margin-top: var(--space-3); border-radius: var(--radius-full); cursor: pointer; touch-action: none;
1374
1813
  background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%); }
1375
1814
  .twc-cp__hue-knob { position: absolute; top: 50%; width: 16px; height: 16px; border-radius: var(--radius-full); background: #fff; box-shadow: var(--shadow-sm), inset 0 0 0 1px rgb(0 0 0 / 0.2); transform: translate(-50%, -50%); pointer-events: none; }
1815
+ .twc-cp__alpha { position: relative; height: 12px; margin-top: var(--space-2); border-radius: var(--radius-full); cursor: pointer; touch-action: none;
1816
+ background-image: linear-gradient(to right, transparent, var(--_solid, #000)), conic-gradient(#c8c8c8 0 25%, #fff 0 50%, #c8c8c8 0 75%, #fff 0);
1817
+ background-size: 100% 100%, 10px 10px; }
1818
+ .twc-cp__alpha:focus-visible { outline: none; box-shadow: var(--ring); }
1376
1819
  .twc-cp__foot { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-3); }
1377
1820
  .twc-cp__hex { flex: 1; min-width: 0; height: 32px; padding: 0 8px; font-family: var(--font-mono); font-size: var(--text-xs); text-transform: uppercase;
1378
1821
  color: var(--color-text); background: var(--color-surface); border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-sm); outline: none; }
@@ -1410,11 +1853,17 @@ function rgbToHex(r, g, b) {
1410
1853
  function hsvToHex(h, s, v) {
1411
1854
  return rgbToHex(...hsvToRgb(h, s, v));
1412
1855
  }
1856
+ function hsvaToHex8(h, s, v, a) {
1857
+ return rgbToHex(...hsvToRgb(h, s, v)) + Math.round(Math.min(1, Math.max(0, a)) * 255).toString(16).padStart(2, "0");
1858
+ }
1413
1859
  function hexToHsv(hex) {
1414
- const m = /^#?([0-9a-f]{6})$/i.exec(hex || "");
1860
+ let str = String(hex || "").replace(/^#/, "");
1861
+ if (/^[0-9a-f]{3}$/i.test(str)) str = str.split("").map((c) => c + c).join("");
1862
+ const m = /^([0-9a-f]{6})([0-9a-f]{2})?$/i.exec(str);
1415
1863
  if (!m) return null;
1416
1864
  const int = parseInt(m[1], 16);
1417
1865
  const r = (int >> 16) / 255, g = (int >> 8 & 255) / 255, b = (int & 255) / 255;
1866
+ const a = m[2] != null ? parseInt(m[2], 16) / 255 : 1;
1418
1867
  const max = Math.max(r, g, b), min = Math.min(r, g, b), d = max - min;
1419
1868
  let h = 0;
1420
1869
  if (d) {
@@ -1424,7 +1873,7 @@ function hexToHsv(hex) {
1424
1873
  h *= 60;
1425
1874
  if (h < 0) h += 360;
1426
1875
  }
1427
- return { h, s: max ? d / max * 100 : 0, v: max * 100 };
1876
+ return { h, s: max ? d / max * 100 : 0, v: max * 100, a };
1428
1877
  }
1429
1878
  var DEFAULT_PRESETS = ["#6366F1", "#0EA5E9", "#14B8A6", "#22C55E", "#F59E0B", "#F43F5E", "#8B5CF6", "#0F172A"];
1430
1879
  function ColorPicker({
@@ -1436,6 +1885,7 @@ function ColorPicker({
1436
1885
  defaultValue = "#6366F1",
1437
1886
  presets = DEFAULT_PRESETS,
1438
1887
  disabled = false,
1888
+ alpha = false,
1439
1889
  tone = "primary",
1440
1890
  onChange,
1441
1891
  className = "",
@@ -1443,20 +1893,22 @@ function ColorPicker({
1443
1893
  }) {
1444
1894
  const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS);
1445
1895
  const __twcStyles1 = useScopedStyles("twc-colorpicker-styles", COLORPICKER_CSS);
1446
- const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
1896
+ const [internal, setInternal] = React37__namespace.default.useState(defaultValue);
1447
1897
  const hex = (value !== void 0 ? value : internal) || "#000000";
1448
- const lastValidRef = React25__namespace.default.useRef(hex);
1449
- if (/^#[0-9a-f]{6}$/i.test(hex)) lastValidRef.current = hex;
1450
- const [open, setOpen] = React25__namespace.default.useState(false);
1451
- const [hsv, setHsv] = React25__namespace.default.useState(() => hexToHsv(hex) || { h: 239, s: 60, v: 94 });
1452
- const [coords, setCoords] = React25__namespace.default.useState(null);
1453
- const wrapRef = React25__namespace.default.useRef(null);
1454
- const triggerRef = React25__namespace.default.useRef(null);
1455
- const popRef = React25__namespace.default.useRef(null);
1456
- const areaRef = React25__namespace.default.useRef(null);
1457
- const hueRef = React25__namespace.default.useRef(null);
1898
+ const hexRe = alpha ? /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i : /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
1899
+ const lastValidRef = React37__namespace.default.useRef(hex);
1900
+ if (hexRe.test(hex)) lastValidRef.current = hex;
1901
+ const [open, setOpen] = React37__namespace.default.useState(false);
1902
+ const [hsv, setHsv] = React37__namespace.default.useState(() => hexToHsv(hex) || { h: 239, s: 60, v: 94, a: 1 });
1903
+ const [coords, setCoords] = React37__namespace.default.useState(null);
1904
+ const wrapRef = React37__namespace.default.useRef(null);
1905
+ const triggerRef = React37__namespace.default.useRef(null);
1906
+ const popRef = React37__namespace.default.useRef(null);
1907
+ const areaRef = React37__namespace.default.useRef(null);
1908
+ const hueRef = React37__namespace.default.useRef(null);
1909
+ const alphaRef = React37__namespace.default.useRef(null);
1458
1910
  const POP_W = 240;
1459
- const place = React25__namespace.default.useCallback(() => {
1911
+ const place = React37__namespace.default.useCallback(() => {
1460
1912
  const el = triggerRef.current;
1461
1913
  if (!el) return;
1462
1914
  const r = el.getBoundingClientRect();
@@ -1467,7 +1919,7 @@ function ColorPicker({
1467
1919
  left = Math.max(8, left);
1468
1920
  setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
1469
1921
  }, []);
1470
- React25__namespace.default.useEffect(() => {
1922
+ React37__namespace.default.useEffect(() => {
1471
1923
  if (!open) return void 0;
1472
1924
  place();
1473
1925
  const onMove = () => place();
@@ -1478,17 +1930,17 @@ function ColorPicker({
1478
1930
  window.removeEventListener("resize", onMove);
1479
1931
  };
1480
1932
  }, [open, place]);
1481
- const labelId = React25__namespace.default.useId();
1933
+ const labelId = React37__namespace.default.useId();
1482
1934
  const descId = `${labelId}-desc`;
1483
1935
  const invalid = Boolean(error);
1484
- React25__namespace.default.useEffect(() => {
1936
+ React37__namespace.default.useEffect(() => {
1485
1937
  if (disabled) setOpen(false);
1486
1938
  }, [disabled]);
1487
- React25__namespace.default.useEffect(() => {
1939
+ React37__namespace.default.useEffect(() => {
1488
1940
  const v = hexToHsv(hex);
1489
1941
  if (v && hsvToHex(v.h, v.s, v.v).toLowerCase() !== hsvToHex(hsv.h, hsv.s, hsv.v).toLowerCase()) setHsv(v);
1490
1942
  }, [hex]);
1491
- React25__namespace.default.useEffect(() => {
1943
+ React37__namespace.default.useEffect(() => {
1492
1944
  if (!open) return;
1493
1945
  const onDown = (e) => {
1494
1946
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -1505,23 +1957,12 @@ function ColorPicker({
1505
1957
  document.removeEventListener("keydown", onKey);
1506
1958
  };
1507
1959
  }, [open]);
1508
- const prevOpen = React25__namespace.default.useRef(false);
1509
- React25__namespace.default.useEffect(() => {
1510
- let id;
1511
- if (!prevOpen.current && open) {
1512
- id = setTimeout(() => areaRef.current?.focus({ preventScroll: true }), 20);
1513
- } else if (prevOpen.current && !open) {
1514
- const ae = typeof document !== "undefined" ? document.activeElement : null;
1515
- if (!ae || ae === document.body) triggerRef.current?.focus();
1516
- }
1517
- prevOpen.current = open;
1518
- return () => clearTimeout(id);
1519
- }, [open]);
1960
+ useFocusTrap(popRef, open && !!coords, { initialFocus: areaRef });
1520
1961
  const commit = (next) => {
1521
- const h = hsvToHex(next.h, next.s, next.v);
1962
+ const out = alpha ? hsvaToHex8(next.h, next.s, next.v, next.a ?? 1) : hsvToHex(next.h, next.s, next.v);
1522
1963
  setHsv(next);
1523
- if (value === void 0) setInternal(h);
1524
- onChange?.(h);
1964
+ if (value === void 0) setInternal(out);
1965
+ onChange?.(out);
1525
1966
  };
1526
1967
  const dragArea = (e) => {
1527
1968
  const r = areaRef.current.getBoundingClientRect();
@@ -1565,6 +2006,21 @@ function ColorPicker({
1565
2006
  e.preventDefault();
1566
2007
  commit({ ...hsv, h });
1567
2008
  };
2009
+ const dragAlpha = (e) => {
2010
+ const r = alphaRef.current.getBoundingClientRect();
2011
+ const a = Math.min(1, Math.max(0, (e.clientX - r.left) / r.width));
2012
+ commit({ ...hsv, a });
2013
+ };
2014
+ const onAlphaKeyDown = (e) => {
2015
+ let a = hsv.a ?? 1;
2016
+ if (e.key === "ArrowRight" || e.key === "ArrowUp") a = Math.min(1, a + 0.01);
2017
+ else if (e.key === "ArrowLeft" || e.key === "ArrowDown") a = Math.max(0, a - 0.01);
2018
+ else if (e.key === "Home") a = 0;
2019
+ else if (e.key === "End") a = 1;
2020
+ else return;
2021
+ e.preventDefault();
2022
+ commit({ ...hsv, a: Math.round(a * 100) / 100 });
2023
+ };
1568
2024
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-cp twc-field ${className}`, ref: wrapRef, ...rest, children: [
1569
2025
  __twcStyles0,
1570
2026
  __twcStyles1,
@@ -1609,6 +2065,7 @@ function ColorPicker({
1609
2065
  className: "twc-cp__pop",
1610
2066
  ref: popRef,
1611
2067
  role: "dialog",
2068
+ "aria-modal": "true",
1612
2069
  "aria-label": "Color picker",
1613
2070
  style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-tooltip)" },
1614
2071
  children: [
@@ -1650,6 +2107,23 @@ function ColorPicker({
1650
2107
  children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-cp__hue-knob", style: { left: `${hsv.h / 360 * 100}%` } })
1651
2108
  }
1652
2109
  ),
2110
+ alpha ? /* @__PURE__ */ jsxRuntime.jsx(
2111
+ "div",
2112
+ {
2113
+ className: "twc-cp__alpha",
2114
+ ref: alphaRef,
2115
+ onPointerDown: startDrag(dragAlpha),
2116
+ role: "slider",
2117
+ tabIndex: 0,
2118
+ "aria-label": "Alpha",
2119
+ "aria-valuemin": 0,
2120
+ "aria-valuemax": 100,
2121
+ "aria-valuenow": Math.round((hsv.a ?? 1) * 100),
2122
+ onKeyDown: onAlphaKeyDown,
2123
+ style: { "--_solid": hsvToHex(hsv.h, hsv.s, hsv.v) },
2124
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-cp__hue-knob", style: { left: `${(hsv.a ?? 1) * 100}%` } })
2125
+ }
2126
+ ) : null,
1653
2127
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-cp__foot", children: [
1654
2128
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-cp__swatch", style: { background: hex } }),
1655
2129
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1658,10 +2132,10 @@ function ColorPicker({
1658
2132
  className: "twc-cp__hex",
1659
2133
  "data-tone": tone,
1660
2134
  value: hex,
1661
- maxLength: 7,
2135
+ maxLength: alpha ? 9 : 7,
1662
2136
  "aria-label": "Hex color",
1663
- "aria-invalid": !/^#[0-9a-f]{6}$/i.test(hex) || void 0,
1664
- "data-invalid": !/^#[0-9a-f]{6}$/i.test(hex) || void 0,
2137
+ "aria-invalid": !hexRe.test(hex) || void 0,
2138
+ "data-invalid": !hexRe.test(hex) || void 0,
1665
2139
  onChange: (e) => {
1666
2140
  let v = e.target.value;
1667
2141
  if (!v.startsWith("#")) v = "#" + v;
@@ -1671,7 +2145,7 @@ function ColorPicker({
1671
2145
  if (p) setHsv(p);
1672
2146
  },
1673
2147
  onBlur: () => {
1674
- if (/^#[0-9a-f]{6}$/i.test(hex)) return;
2148
+ if (hexRe.test(hex)) return;
1675
2149
  const revert = lastValidRef.current;
1676
2150
  if (revert === hex) return;
1677
2151
  if (value === void 0) setInternal(revert);
@@ -1829,6 +2303,8 @@ function Combobox({
1829
2303
  loading = false,
1830
2304
  emptyText = "No results found",
1831
2305
  name,
2306
+ virtualized = false,
2307
+ overscan = 8,
1832
2308
  id,
1833
2309
  className = "",
1834
2310
  onFocus,
@@ -1836,29 +2312,51 @@ function Combobox({
1836
2312
  ...rest
1837
2313
  }) {
1838
2314
  const __twcStyles = useScopedStyles("twc-combo-styles", COMBO_CSS);
1839
- const groups = React25__namespace.default.useMemo(() => normalizeGroups(options), [options]);
1840
- const flat = React25__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
1841
- const autoId = React25__namespace.default.useId();
2315
+ const groups = React37__namespace.default.useMemo(() => normalizeGroups(options), [options]);
2316
+ const flat = React37__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
2317
+ const autoId = React37__namespace.default.useId();
1842
2318
  const fieldId = id || autoId;
1843
- const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
2319
+ const [internal, setInternal] = React37__namespace.default.useState(defaultValue);
1844
2320
  const current = value !== void 0 ? value : internal;
1845
2321
  const selected = flat.find((o) => o.value === current);
1846
- const [open, setOpen] = React25__namespace.default.useState(false);
1847
- const [query, setQuery] = React25__namespace.default.useState("");
1848
- const [active, setActive] = React25__namespace.default.useState(0);
1849
- const [coords, setCoords] = React25__namespace.default.useState(null);
1850
- const wrapRef = React25__namespace.default.useRef(null);
1851
- const controlRef = React25__namespace.default.useRef(null);
1852
- const inputRef = React25__namespace.default.useRef(null);
1853
- const popRef = React25__namespace.default.useRef(null);
1854
- const listRef = React25__namespace.default.useRef(null);
1855
- const activeRef = React25__namespace.default.useRef(null);
1856
- const fGroups = React25__namespace.default.useMemo(() => {
2322
+ const [open, setOpen] = React37__namespace.default.useState(false);
2323
+ const [query, setQuery] = React37__namespace.default.useState("");
2324
+ const [active, setActive] = React37__namespace.default.useState(0);
2325
+ const [coords, setCoords] = React37__namespace.default.useState(null);
2326
+ const [scrollTop, setScrollTop] = React37__namespace.default.useState(0);
2327
+ const [listH, setListH] = React37__namespace.default.useState(260);
2328
+ const wrapRef = React37__namespace.default.useRef(null);
2329
+ const controlRef = React37__namespace.default.useRef(null);
2330
+ const inputRef = React37__namespace.default.useRef(null);
2331
+ const popRef = React37__namespace.default.useRef(null);
2332
+ const listRef = React37__namespace.default.useRef(null);
2333
+ const activeRef = React37__namespace.default.useRef(null);
2334
+ const fGroups = React37__namespace.default.useMemo(() => {
1857
2335
  const q = query.trim();
1858
2336
  const fn = filter === false ? null : typeof filter === "function" ? filter : matches;
1859
2337
  return groups.map((g) => ({ group: g.group, options: fn ? g.options.filter((o) => fn(o, q)) : g.options })).filter((g) => g.options.length);
1860
2338
  }, [groups, query, filter]);
1861
- const visible = React25__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
2339
+ const visible = React37__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
2340
+ const rowH = React37__namespace.default.useMemo(() => visible.some((o) => o.description) ? 48 : 36, [visible]);
2341
+ const GROUP_H = 30;
2342
+ const { rows, totalH } = React37__namespace.default.useMemo(() => {
2343
+ if (!virtualized) return { rows: [], totalH: 0 };
2344
+ const rows2 = [];
2345
+ let off = 0;
2346
+ let optIdx = -1;
2347
+ fGroups.forEach((g, gi) => {
2348
+ if (g.group) {
2349
+ rows2.push({ kind: "group", gi, label: g.group, top: off, h: GROUP_H });
2350
+ off += GROUP_H;
2351
+ }
2352
+ g.options.forEach((o) => {
2353
+ optIdx += 1;
2354
+ rows2.push({ kind: "option", o, idx: optIdx, top: off, h: rowH });
2355
+ off += rowH;
2356
+ });
2357
+ });
2358
+ return { rows: rows2, totalH: off };
2359
+ }, [virtualized, fGroups, rowH]);
1862
2360
  const nextEnabled = (from, dir) => {
1863
2361
  let i = from + dir;
1864
2362
  while (i >= 0 && i < visible.length) {
@@ -1867,7 +2365,7 @@ function Combobox({
1867
2365
  }
1868
2366
  return from;
1869
2367
  };
1870
- const place = React25__namespace.default.useCallback(() => {
2368
+ const place = React37__namespace.default.useCallback(() => {
1871
2369
  const el = controlRef.current;
1872
2370
  if (!el) return;
1873
2371
  const r = el.getBoundingClientRect();
@@ -1882,7 +2380,7 @@ function Combobox({
1882
2380
  flip
1883
2381
  });
1884
2382
  }, [placement, minWidth]);
1885
- React25__namespace.default.useEffect(() => {
2383
+ React37__namespace.default.useEffect(() => {
1886
2384
  if (!open || !portal) return;
1887
2385
  place();
1888
2386
  const onMove = () => place();
@@ -1893,7 +2391,7 @@ function Combobox({
1893
2391
  window.removeEventListener("resize", onMove);
1894
2392
  };
1895
2393
  }, [open, portal, place]);
1896
- React25__namespace.default.useEffect(() => {
2394
+ React37__namespace.default.useEffect(() => {
1897
2395
  if (!open) return;
1898
2396
  const onDown = (e) => {
1899
2397
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -1903,17 +2401,36 @@ function Combobox({
1903
2401
  document.addEventListener("mousedown", onDown);
1904
2402
  return () => document.removeEventListener("mousedown", onDown);
1905
2403
  }, [open]);
1906
- React25__namespace.default.useEffect(() => {
2404
+ React37__namespace.default.useEffect(() => {
1907
2405
  setActive(0);
1908
2406
  }, [query]);
1909
- React25__namespace.default.useEffect(() => {
2407
+ React37__namespace.default.useEffect(() => {
1910
2408
  if (!open) return;
1911
2409
  const idx = flat.findIndex((o) => o.value === current);
1912
2410
  setActive(idx >= 0 ? idx : 0);
1913
2411
  }, [open]);
1914
- React25__namespace.default.useEffect(() => {
1915
- if (open) ensureVisible(listRef.current, activeRef.current);
1916
- }, [active, open]);
2412
+ React37__namespace.default.useEffect(() => {
2413
+ if (!open || !virtualized) return;
2414
+ const el = listRef.current;
2415
+ if (el && el.clientHeight) setListH(el.clientHeight);
2416
+ }, [open, virtualized]);
2417
+ React37__namespace.default.useEffect(() => {
2418
+ if (!open) return;
2419
+ if (!virtualized) {
2420
+ ensureVisible(listRef.current, activeRef.current);
2421
+ return;
2422
+ }
2423
+ const el = listRef.current;
2424
+ if (!el) return;
2425
+ const row = rows.find((r) => r.kind === "option" && r.idx === active);
2426
+ if (!row) return;
2427
+ const vh = el.clientHeight || listH;
2428
+ let next = el.scrollTop;
2429
+ if (row.top < el.scrollTop) next = row.top;
2430
+ else if (row.top + row.h > el.scrollTop + vh) next = row.top + row.h - vh;
2431
+ if (next !== el.scrollTop) el.scrollTop = next;
2432
+ setScrollTop(next);
2433
+ }, [active, open, virtualized, rows, listH]);
1917
2434
  function openMenu() {
1918
2435
  if (disabled) return;
1919
2436
  setQuery("");
@@ -1958,45 +2475,60 @@ function Combobox({
1958
2475
  const activeId = open && visible[active] ? optionId(active) : void 0;
1959
2476
  const descId = `${fieldId}-desc`;
1960
2477
  const describedBy = error || hint ? descId : void 0;
2478
+ const renderOption = (o, idx) => {
2479
+ const isSel = o.value === current;
2480
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2481
+ "button",
2482
+ {
2483
+ id: optionId(idx),
2484
+ type: "button",
2485
+ className: "twc-opt",
2486
+ role: "option",
2487
+ "aria-selected": isSel,
2488
+ ref: idx === active ? activeRef : null,
2489
+ disabled: o.disabled || void 0,
2490
+ "aria-disabled": o.disabled || void 0,
2491
+ "data-disabled": o.disabled || void 0,
2492
+ "data-selected": isSel || void 0,
2493
+ "data-active": idx === active || void 0,
2494
+ onMouseEnter: () => {
2495
+ if (!o.disabled) setActive(idx);
2496
+ },
2497
+ onMouseDown: (e) => e.preventDefault(),
2498
+ onClick: () => commit(o.value),
2499
+ children: [
2500
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-opt__main", children: [
2501
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__label", children: o.label }),
2502
+ o.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__desc", children: o.description }) : null
2503
+ ] }),
2504
+ isSel ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__check", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) }) }) : null
2505
+ ]
2506
+ },
2507
+ o.value
2508
+ );
2509
+ };
2510
+ let vTop = 0, vBottom = 0, vShown = rows;
2511
+ if (virtualized && rows.length) {
2512
+ const winTop = scrollTop - overscan * rowH;
2513
+ const winBottom = scrollTop + listH + overscan * rowH;
2514
+ vShown = rows.filter((r) => r.top + r.h > winTop && r.top < winBottom);
2515
+ vTop = vShown.length ? vShown[0].top : 0;
2516
+ vBottom = vShown.length ? totalH - (vShown[vShown.length - 1].top + vShown[vShown.length - 1].h) : totalH;
2517
+ }
1961
2518
  let counter = -1;
1962
- const popInner = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-pop__loading", role: "status", children: [
2519
+ const popInner = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, onScroll: virtualized ? (e) => setScrollTop(e.currentTarget.scrollTop) : void 0, children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-pop__loading", role: "status", children: [
1963
2520
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-pop__spinner", "aria-hidden": "true" }),
1964
2521
  "Loading\u2026"
1965
- ] }) : visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: emptyText }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React25__namespace.default.Fragment, { children: [
2522
+ ] }) : visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: emptyText }) : virtualized ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2523
+ vTop > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", style: { height: vTop } }) : null,
2524
+ vShown.map((r) => r.kind === "group" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: r.label }, `g${r.gi}`) : renderOption(r.o, r.idx)),
2525
+ vBottom > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", style: { height: vBottom } }) : null
2526
+ ] }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React37__namespace.default.Fragment, { children: [
1966
2527
  g.group ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: g.group }) : null,
1967
2528
  g.options.map((o) => {
1968
2529
  counter += 1;
1969
2530
  const idx = counter;
1970
- const isSel = o.value === current;
1971
- return /* @__PURE__ */ jsxRuntime.jsxs(
1972
- "button",
1973
- {
1974
- id: optionId(idx),
1975
- type: "button",
1976
- className: "twc-opt",
1977
- role: "option",
1978
- "aria-selected": isSel,
1979
- ref: idx === active ? activeRef : null,
1980
- disabled: o.disabled || void 0,
1981
- "aria-disabled": o.disabled || void 0,
1982
- "data-disabled": o.disabled || void 0,
1983
- "data-selected": isSel || void 0,
1984
- "data-active": idx === active || void 0,
1985
- onMouseEnter: () => {
1986
- if (!o.disabled) setActive(idx);
1987
- },
1988
- onMouseDown: (e) => e.preventDefault(),
1989
- onClick: () => commit(o.value),
1990
- children: [
1991
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-opt__main", children: [
1992
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__label", children: o.label }),
1993
- o.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__desc", children: o.description }) : null
1994
- ] }),
1995
- isSel ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__check", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) }) }) : null
1996
- ]
1997
- },
1998
- o.value
1999
- );
2531
+ return renderOption(o, idx);
2000
2532
  })
2001
2533
  ] }, gi)) });
2002
2534
  const RD = { createPortal: typeof reactDom.createPortal === "function" ? reactDom.createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
@@ -2107,95 +2639,6 @@ function Combobox({
2107
2639
  error ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
2108
2640
  ] });
2109
2641
  }
2110
- var canUseDOM = typeof window !== "undefined" && typeof document !== "undefined";
2111
- var useIsoLayoutEffect = canUseDOM ? React25__namespace.default.useLayoutEffect : React25__namespace.default.useEffect;
2112
- var FOCUSABLE = 'a[href]:not([tabindex="-1"]), button:not([disabled]):not([tabindex="-1"]), textarea:not([disabled]):not([tabindex="-1"]), input:not([disabled]):not([tabindex="-1"]), select:not([disabled]):not([tabindex="-1"]), [tabindex]:not([tabindex="-1"])';
2113
- function useFocusTrap(ref, active = true, { restoreFocus = true } = {}) {
2114
- React25__namespace.default.useEffect(() => {
2115
- if (!active || !canUseDOM) return void 0;
2116
- const node = ref.current;
2117
- if (!node) return void 0;
2118
- const prevFocused = document.activeElement;
2119
- const first = node.querySelector(FOCUSABLE);
2120
- (first || node).focus();
2121
- return () => {
2122
- if (restoreFocus && prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
2123
- };
2124
- }, [active]);
2125
- React25__namespace.default.useEffect(() => {
2126
- if (!active || !canUseDOM) return void 0;
2127
- const node = ref.current;
2128
- const onKey = (e) => {
2129
- if (e.key !== "Tab" || !node) return;
2130
- const f = Array.from(node.querySelectorAll(FOCUSABLE)).filter((el) => el.offsetParent !== null);
2131
- if (!f.length) {
2132
- e.preventDefault();
2133
- node.focus();
2134
- return;
2135
- }
2136
- const first = f[0], last = f[f.length - 1], ae = document.activeElement;
2137
- if (e.shiftKey) {
2138
- if (ae === first || ae === node || !node.contains(ae)) {
2139
- e.preventDefault();
2140
- last.focus();
2141
- }
2142
- } else if (ae === last || !node.contains(ae)) {
2143
- e.preventDefault();
2144
- first.focus();
2145
- }
2146
- };
2147
- document.addEventListener("keydown", onKey);
2148
- return () => document.removeEventListener("keydown", onKey);
2149
- }, [active]);
2150
- }
2151
- function usePortal() {
2152
- return React25__namespace.default.useCallback((node) => {
2153
- if (typeof document === "undefined") return null;
2154
- return typeof reactDom.createPortal === "function" ? reactDom.createPortal(node, document.body) : node;
2155
- }, []);
2156
- }
2157
- var __scrollLockCount = 0;
2158
- var __scrollLockSaved = { overflow: "", paddingRight: "" };
2159
- function useScrollLock(locked = true) {
2160
- useIsoLayoutEffect(() => {
2161
- if (!canUseDOM || !locked) return void 0;
2162
- if (__scrollLockCount === 0) {
2163
- const b = document.body;
2164
- __scrollLockSaved = { overflow: b.style.overflow, paddingRight: b.style.paddingRight };
2165
- const gutter = window.innerWidth - document.documentElement.clientWidth;
2166
- b.style.overflow = "hidden";
2167
- if (gutter > 0) b.style.paddingRight = `${(parseFloat(getComputedStyle(b).paddingRight) || 0) + gutter}px`;
2168
- }
2169
- __scrollLockCount += 1;
2170
- return () => {
2171
- __scrollLockCount -= 1;
2172
- if (__scrollLockCount === 0) {
2173
- document.body.style.overflow = __scrollLockSaved.overflow;
2174
- document.body.style.paddingRight = __scrollLockSaved.paddingRight;
2175
- }
2176
- };
2177
- }, [locked]);
2178
- }
2179
- function useInertBackground(ref, active) {
2180
- React25__namespace.default.useEffect(() => {
2181
- if (!active || !canUseDOM) return void 0;
2182
- const node = ref.current;
2183
- if (!node) return void 0;
2184
- const changed = [];
2185
- Array.from(document.body.children).forEach((el) => {
2186
- if (el.contains(node) || el.hasAttribute("aria-hidden") || el.inert) return;
2187
- el.inert = true;
2188
- el.setAttribute("aria-hidden", "true");
2189
- changed.push(el);
2190
- });
2191
- return () => {
2192
- changed.forEach((el) => {
2193
- el.inert = false;
2194
- el.removeAttribute("aria-hidden");
2195
- });
2196
- };
2197
- }, [active]);
2198
- }
2199
2642
  var COMMAND_CSS = `
2200
2643
  .twc-cmdk__overlay { position: fixed; inset: 0; z-index: var(--z-modal); background: var(--color-overlay); backdrop-filter: blur(3px);
2201
2644
  display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; }
@@ -2243,14 +2686,14 @@ function CommandPalette({
2243
2686
  }) {
2244
2687
  const __twcStyles = useScopedStyles("twc-cmdk-styles", COMMAND_CSS);
2245
2688
  const renderPortal = usePortal();
2246
- const [query, setQuery] = React25__namespace.default.useState("");
2247
- const [active, setActive] = React25__namespace.default.useState(0);
2248
- const inputRef = React25__namespace.default.useRef(null);
2249
- const listRef = React25__namespace.default.useRef(null);
2250
- const paletteRef = React25__namespace.default.useRef(null);
2251
- const baseId = React25__namespace.default.useId();
2252
- const [mounted, setMounted] = React25__namespace.default.useState(open);
2253
- React25__namespace.default.useEffect(() => {
2689
+ const [query, setQuery] = React37__namespace.default.useState("");
2690
+ const [active, setActive] = React37__namespace.default.useState(0);
2691
+ const inputRef = React37__namespace.default.useRef(null);
2692
+ const listRef = React37__namespace.default.useRef(null);
2693
+ const paletteRef = React37__namespace.default.useRef(null);
2694
+ const baseId = React37__namespace.default.useId();
2695
+ const [mounted, setMounted] = React37__namespace.default.useState(open);
2696
+ React37__namespace.default.useEffect(() => {
2254
2697
  if (open) {
2255
2698
  setMounted(true);
2256
2699
  return;
@@ -2259,14 +2702,14 @@ function CommandPalette({
2259
2702
  return () => clearTimeout(t);
2260
2703
  }, [open]);
2261
2704
  useScrollLock(open);
2262
- React25__namespace.default.useEffect(() => {
2705
+ React37__namespace.default.useEffect(() => {
2263
2706
  if (open) {
2264
2707
  setQuery("");
2265
2708
  setActive(0);
2266
2709
  }
2267
2710
  }, [open]);
2268
2711
  useFocusTrap(paletteRef, open && mounted);
2269
- React25__namespace.default.useEffect(() => {
2712
+ React37__namespace.default.useEffect(() => {
2270
2713
  if (!open) return void 0;
2271
2714
  const onKey = (e) => {
2272
2715
  if (e.key === "Escape") {
@@ -2278,7 +2721,7 @@ function CommandPalette({
2278
2721
  return () => document.removeEventListener("keydown", onKey);
2279
2722
  }, [open, onClose]);
2280
2723
  const q = query.trim().toLowerCase();
2281
- const filtered = React25__namespace.default.useMemo(() => commands.filter(
2724
+ const filtered = React37__namespace.default.useMemo(() => commands.filter(
2282
2725
  (c) => !q || c.label.toLowerCase().includes(q) || (c.keywords || "").toLowerCase().includes(q) || (c.group || "").toLowerCase().includes(q)
2283
2726
  ), [commands, q]);
2284
2727
  const groups = [];
@@ -2293,7 +2736,7 @@ function CommandPalette({
2293
2736
  g.items.push(c);
2294
2737
  flat.push(c);
2295
2738
  });
2296
- React25__namespace.default.useEffect(() => {
2739
+ React37__namespace.default.useEffect(() => {
2297
2740
  setActive(0);
2298
2741
  }, [query]);
2299
2742
  const run = (cmd) => {
@@ -2313,7 +2756,7 @@ function CommandPalette({
2313
2756
  if (cmd) run(cmd);
2314
2757
  }
2315
2758
  }
2316
- React25__namespace.default.useEffect(() => {
2759
+ React37__namespace.default.useEffect(() => {
2317
2760
  const node = listRef.current?.querySelector('[data-active="true"]');
2318
2761
  if (node) node.scrollIntoView({ block: "nearest" });
2319
2762
  }, [active]);
@@ -2489,13 +2932,13 @@ function Currency({
2489
2932
  const prec = precision != null ? precision : meta.precision;
2490
2933
  const sym = symbol != null ? symbol : meta.symbol;
2491
2934
  const cur = code != null ? code : meta.code;
2492
- const autoId = React25__namespace.default.useId();
2935
+ const autoId = React37__namespace.default.useId();
2493
2936
  const fieldId = id || autoId;
2494
2937
  const invalid = Boolean(error);
2495
2938
  const controlled = value !== void 0;
2496
- const [internal, setInternal] = React25__namespace.default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
2939
+ const [internal, setInternal] = React37__namespace.default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
2497
2940
  const shown = controlled ? clampPrecision(String(value ?? ""), prec) : internal;
2498
- React25__namespace.default.useEffect(() => {
2941
+ React37__namespace.default.useEffect(() => {
2499
2942
  if (!controlled) return;
2500
2943
  const raw = String(value ?? "");
2501
2944
  if (shown !== raw) {
@@ -2682,6 +3125,8 @@ function Select({
2682
3125
  loading = false,
2683
3126
  emptyText = "No results found",
2684
3127
  name,
3128
+ virtualized = false,
3129
+ overscan = 8,
2685
3130
  id,
2686
3131
  className = "",
2687
3132
  onClick,
@@ -2689,32 +3134,54 @@ function Select({
2689
3134
  ...rest
2690
3135
  }) {
2691
3136
  const __twcStyles = useScopedStyles("twc-select-styles", SELECT_CSS);
2692
- const bufferRef = React25__namespace.default.useRef("");
2693
- const bufferTimerRef = React25__namespace.default.useRef(null);
2694
- const groups = React25__namespace.default.useMemo(() => normalizeGroups2(options), [options]);
2695
- const flat = React25__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
2696
- const autoId = React25__namespace.default.useId();
3137
+ const bufferRef = React37__namespace.default.useRef("");
3138
+ const bufferTimerRef = React37__namespace.default.useRef(null);
3139
+ const groups = React37__namespace.default.useMemo(() => normalizeGroups2(options), [options]);
3140
+ const flat = React37__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
3141
+ const autoId = React37__namespace.default.useId();
2697
3142
  const fieldId = id || autoId;
2698
- const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
3143
+ const [internal, setInternal] = React37__namespace.default.useState(defaultValue);
2699
3144
  const current = value !== void 0 ? value : internal;
2700
- const [open, setOpen] = React25__namespace.default.useState(false);
2701
- const [render, setRender] = React25__namespace.default.useState(false);
2702
- const [active, setActive] = React25__namespace.default.useState(0);
2703
- const [coords, setCoords] = React25__namespace.default.useState(null);
2704
- const [query, setQuery] = React25__namespace.default.useState("");
2705
- const wrapRef = React25__namespace.default.useRef(null);
2706
- const triggerRef = React25__namespace.default.useRef(null);
2707
- const popRef = React25__namespace.default.useRef(null);
2708
- const listRef = React25__namespace.default.useRef(null);
2709
- const activeRef = React25__namespace.default.useRef(null);
2710
- const searchRef = React25__namespace.default.useRef(null);
3145
+ const [open, setOpen] = React37__namespace.default.useState(false);
3146
+ const [render, setRender] = React37__namespace.default.useState(false);
3147
+ const [active, setActive] = React37__namespace.default.useState(0);
3148
+ const [coords, setCoords] = React37__namespace.default.useState(null);
3149
+ const [query, setQuery] = React37__namespace.default.useState("");
3150
+ const [scrollTop, setScrollTop] = React37__namespace.default.useState(0);
3151
+ const [listH, setListH] = React37__namespace.default.useState(260);
3152
+ const wrapRef = React37__namespace.default.useRef(null);
3153
+ const triggerRef = React37__namespace.default.useRef(null);
3154
+ const popRef = React37__namespace.default.useRef(null);
3155
+ const listRef = React37__namespace.default.useRef(null);
3156
+ const activeRef = React37__namespace.default.useRef(null);
3157
+ const searchRef = React37__namespace.default.useRef(null);
2711
3158
  const showSearch = searchable === void 0 ? flat.length > 5 : searchable;
2712
- const fGroups = React25__namespace.default.useMemo(() => {
3159
+ const fGroups = React37__namespace.default.useMemo(() => {
2713
3160
  const q = query.trim().toLowerCase();
2714
3161
  if (!q) return groups;
2715
3162
  return groups.map((g) => ({ group: g.group, options: g.options.filter((o) => o.label.toLowerCase().includes(q) || o.description && o.description.toLowerCase().includes(q)) })).filter((g) => g.options.length);
2716
3163
  }, [groups, query]);
2717
- const visible = React25__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
3164
+ const visible = React37__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
3165
+ const rowH = React37__namespace.default.useMemo(() => visible.some((o) => o.description) ? 48 : 36, [visible]);
3166
+ const GROUP_H = 30;
3167
+ const { rows, totalH } = React37__namespace.default.useMemo(() => {
3168
+ if (!virtualized) return { rows: [], totalH: 0 };
3169
+ const rows2 = [];
3170
+ let off = 0;
3171
+ let optIdx = -1;
3172
+ fGroups.forEach((g, gi) => {
3173
+ if (g.group) {
3174
+ rows2.push({ kind: "group", gi, label: g.group, top: off, h: GROUP_H });
3175
+ off += GROUP_H;
3176
+ }
3177
+ g.options.forEach((o) => {
3178
+ optIdx += 1;
3179
+ rows2.push({ kind: "option", o, idx: optIdx, top: off, h: rowH });
3180
+ off += rowH;
3181
+ });
3182
+ });
3183
+ return { rows: rows2, totalH: off };
3184
+ }, [virtualized, fGroups, rowH]);
2718
3185
  const selected = flat.find((o) => o.value === current);
2719
3186
  const nextEnabled = (from, dir) => {
2720
3187
  let i = from + dir;
@@ -2724,7 +3191,7 @@ function Select({
2724
3191
  }
2725
3192
  return from;
2726
3193
  };
2727
- const place = React25__namespace.default.useCallback(() => {
3194
+ const place = React37__namespace.default.useCallback(() => {
2728
3195
  const el = triggerRef.current;
2729
3196
  if (!el) return;
2730
3197
  const r = el.getBoundingClientRect();
@@ -2740,7 +3207,7 @@ function Select({
2740
3207
  flip
2741
3208
  });
2742
3209
  }, [placement, minWidth, matchTriggerWidth]);
2743
- React25__namespace.default.useEffect(() => {
3210
+ React37__namespace.default.useEffect(() => {
2744
3211
  if (!open || !portal) return;
2745
3212
  place();
2746
3213
  const onMove = () => place();
@@ -2751,7 +3218,7 @@ function Select({
2751
3218
  window.removeEventListener("resize", onMove);
2752
3219
  };
2753
3220
  }, [open, portal, place]);
2754
- React25__namespace.default.useEffect(() => {
3221
+ React37__namespace.default.useEffect(() => {
2755
3222
  if (!open) return;
2756
3223
  const idx = flat.findIndex((o) => o.value === current);
2757
3224
  setActive(idx >= 0 ? idx : 0);
@@ -2767,13 +3234,32 @@ function Select({
2767
3234
  document.addEventListener("mousedown", onDown);
2768
3235
  return () => document.removeEventListener("mousedown", onDown);
2769
3236
  }, [open]);
2770
- React25__namespace.default.useEffect(() => {
3237
+ React37__namespace.default.useEffect(() => {
2771
3238
  setActive(0);
2772
3239
  }, [query]);
2773
- React25__namespace.default.useEffect(() => {
2774
- if (open) ensureVisible2(listRef.current, activeRef.current);
2775
- }, [active, open]);
2776
- React25__namespace.default.useEffect(() => {
3240
+ React37__namespace.default.useEffect(() => {
3241
+ if (!open || !virtualized) return;
3242
+ const el = listRef.current;
3243
+ if (el && el.clientHeight) setListH(el.clientHeight);
3244
+ }, [open, virtualized, render]);
3245
+ React37__namespace.default.useEffect(() => {
3246
+ if (!open) return;
3247
+ if (!virtualized) {
3248
+ ensureVisible2(listRef.current, activeRef.current);
3249
+ return;
3250
+ }
3251
+ const el = listRef.current;
3252
+ if (!el) return;
3253
+ const row = rows.find((r) => r.kind === "option" && r.idx === active);
3254
+ if (!row) return;
3255
+ const vh = el.clientHeight || listH;
3256
+ let next = el.scrollTop;
3257
+ if (row.top < el.scrollTop) next = row.top;
3258
+ else if (row.top + row.h > el.scrollTop + vh) next = row.top + row.h - vh;
3259
+ if (next !== el.scrollTop) el.scrollTop = next;
3260
+ setScrollTop(next);
3261
+ }, [active, open, virtualized, rows, listH]);
3262
+ React37__namespace.default.useEffect(() => {
2777
3263
  if (open) {
2778
3264
  setRender(true);
2779
3265
  return;
@@ -2781,8 +3267,8 @@ function Select({
2781
3267
  const t = setTimeout(() => setRender(false), 170);
2782
3268
  return () => clearTimeout(t);
2783
3269
  }, [open]);
2784
- const prevOpen = React25__namespace.default.useRef(false);
2785
- React25__namespace.default.useEffect(() => {
3270
+ const prevOpen = React37__namespace.default.useRef(false);
3271
+ React37__namespace.default.useEffect(() => {
2786
3272
  if (prevOpen.current && !open) {
2787
3273
  const ae = typeof document !== "undefined" ? document.activeElement : null;
2788
3274
  if (popRef.current && ae && popRef.current.contains(ae)) triggerRef.current?.focus();
@@ -2846,6 +3332,45 @@ function Select({
2846
3332
  const activeId = open && visible[active] ? optionId(active) : void 0;
2847
3333
  const descId = `${fieldId}-desc`;
2848
3334
  const describedBy = error || hint ? descId : void 0;
3335
+ const renderOption = (o, idx) => {
3336
+ const isSel = o.value === current;
3337
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3338
+ "button",
3339
+ {
3340
+ id: optionId(idx),
3341
+ type: "button",
3342
+ className: "twc-opt",
3343
+ role: "option",
3344
+ "aria-selected": isSel,
3345
+ ref: idx === active ? activeRef : null,
3346
+ disabled: o.disabled || void 0,
3347
+ "aria-disabled": o.disabled || void 0,
3348
+ "data-disabled": o.disabled || void 0,
3349
+ "data-selected": isSel || void 0,
3350
+ "data-active": idx === active || void 0,
3351
+ onMouseEnter: () => {
3352
+ if (!o.disabled) setActive(idx);
3353
+ },
3354
+ onClick: () => commit(o.value),
3355
+ children: [
3356
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-opt__main", children: [
3357
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__label", children: o.label }),
3358
+ o.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__desc", children: o.description }) : null
3359
+ ] }),
3360
+ isSel ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__check", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) }) }) : null
3361
+ ]
3362
+ },
3363
+ o.value
3364
+ );
3365
+ };
3366
+ let vTop = 0, vBottom = 0, vShown = rows;
3367
+ if (virtualized && rows.length) {
3368
+ const winTop = scrollTop - overscan * rowH;
3369
+ const winBottom = scrollTop + listH + overscan * rowH;
3370
+ vShown = rows.filter((r) => r.top + r.h > winTop && r.top < winBottom);
3371
+ vTop = vShown.length ? vShown[0].top : 0;
3372
+ vBottom = vShown.length ? totalH - (vShown[vShown.length - 1].top + vShown[vShown.length - 1].h) : totalH;
3373
+ }
2849
3374
  let counter = -1;
2850
3375
  const popInner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2851
3376
  showSearch ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-pop__search", children: [
@@ -2873,43 +3398,19 @@ function Select({
2873
3398
  searchRef.current?.focus();
2874
3399
  }, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
2875
3400
  ] }) : null,
2876
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-pop__loading", role: "status", children: [
3401
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, onScroll: virtualized ? (e) => setScrollTop(e.currentTarget.scrollTop) : void 0, children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-pop__loading", role: "status", children: [
2877
3402
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-pop__spinner", "aria-hidden": "true" }),
2878
3403
  "Loading\u2026"
2879
- ] }) : visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: emptyText }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React25__namespace.default.Fragment, { children: [
3404
+ ] }) : visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: emptyText }) : virtualized ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3405
+ vTop > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", style: { height: vTop } }) : null,
3406
+ vShown.map((r) => r.kind === "group" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: r.label }, `g${r.gi}`) : renderOption(r.o, r.idx)),
3407
+ vBottom > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", style: { height: vBottom } }) : null
3408
+ ] }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React37__namespace.default.Fragment, { children: [
2880
3409
  g.group ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: g.group }) : null,
2881
3410
  g.options.map((o) => {
2882
3411
  counter += 1;
2883
3412
  const idx = counter;
2884
- const isSel = o.value === current;
2885
- return /* @__PURE__ */ jsxRuntime.jsxs(
2886
- "button",
2887
- {
2888
- id: optionId(idx),
2889
- type: "button",
2890
- className: "twc-opt",
2891
- role: "option",
2892
- "aria-selected": isSel,
2893
- ref: idx === active ? activeRef : null,
2894
- disabled: o.disabled || void 0,
2895
- "aria-disabled": o.disabled || void 0,
2896
- "data-disabled": o.disabled || void 0,
2897
- "data-selected": isSel || void 0,
2898
- "data-active": idx === active || void 0,
2899
- onMouseEnter: () => {
2900
- if (!o.disabled) setActive(idx);
2901
- },
2902
- onClick: () => commit(o.value),
2903
- children: [
2904
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-opt__main", children: [
2905
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__label", children: o.label }),
2906
- o.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__desc", children: o.description }) : null
2907
- ] }),
2908
- isSel ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__check", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) }) }) : null
2909
- ]
2910
- },
2911
- o.value
2912
- );
3413
+ return renderOption(o, idx);
2913
3414
  })
2914
3415
  ] }, gi)) }),
2915
3416
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-sel__sr", role: "status", "aria-live": "polite", children: loading ? "Loading\u2026" : visible.length === 0 ? emptyText : `${visible.length} result${visible.length === 1 ? "" : "s"}` })
@@ -3059,21 +3560,21 @@ function CurrencyField({
3059
3560
  ...rest
3060
3561
  }) {
3061
3562
  const __twcStyles = useScopedStyles("twc-curf-styles", CURF_CSS);
3062
- const autoId = React25__namespace.default.useId();
3563
+ const autoId = React37__namespace.default.useId();
3063
3564
  const fieldId = id || autoId;
3064
3565
  const invalid = Boolean(error);
3065
3566
  const curControlled = currency !== void 0;
3066
- const [curInternal, setCurInternal] = React25__namespace.default.useState(defaultCurrency);
3567
+ const [curInternal, setCurInternal] = React37__namespace.default.useState(defaultCurrency);
3067
3568
  const cur = curControlled ? currency : curInternal;
3068
3569
  const meta = CURRENCIES[cur] || CURRENCIES.USD;
3069
3570
  const prec = meta.precision;
3070
3571
  const valControlled = value !== void 0;
3071
- const [valInternal, setValInternal] = React25__namespace.default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
3572
+ const [valInternal, setValInternal] = React37__namespace.default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
3072
3573
  const shown = valControlled ? clampPrecision(String(value ?? ""), prec) : valInternal;
3073
3574
  const descId = `${fieldId}-desc`;
3074
3575
  const describedBy = [error || hint ? descId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
3075
3576
  const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
3076
- React25__namespace.default.useEffect(() => {
3577
+ React37__namespace.default.useEffect(() => {
3077
3578
  if (!valControlled) {
3078
3579
  const clamped = clampPrecision(valInternal, prec);
3079
3580
  if (clamped !== valInternal) {
@@ -3089,7 +3590,7 @@ function CurrencyField({
3089
3590
  }
3090
3591
  }
3091
3592
  }, [prec, cur, shown, value, valControlled, valInternal]);
3092
- const options = React25__namespace.default.useMemo(() => {
3593
+ const options = React37__namespace.default.useMemo(() => {
3093
3594
  if (!currencies) return CURRENCY_OPTIONS;
3094
3595
  return currencies.map((c) => typeof c === "string" ? { value: c, label: `${c} \u2014 ${(CURRENCIES[c] || {}).label || c}` } : c);
3095
3596
  }, [currencies]);
@@ -3243,13 +3744,13 @@ function Input({
3243
3744
  }) {
3244
3745
  const __twcStyles = useScopedStyles("twc-field-styles", FIELD_CSS2);
3245
3746
  const __twcExtra = useScopedStyles("twc-input-extra-styles", INPUT_EXTRA_CSS);
3246
- const autoId = React25__namespace.default.useId();
3747
+ const autoId = React37__namespace.default.useId();
3247
3748
  const fieldId = id || autoId;
3248
3749
  const descId = `${fieldId}-desc`;
3249
3750
  const countId = `${fieldId}-count`;
3250
3751
  const invalid = Boolean(error);
3251
3752
  const countControlled = rest.value !== void 0;
3252
- const [len2, setLen] = React25__namespace.default.useState(() => String(rest.defaultValue ?? "").length);
3753
+ const [len2, setLen] = React37__namespace.default.useState(() => String(rest.defaultValue ?? "").length);
3253
3754
  const count = countControlled ? String(rest.value ?? "").length : len2;
3254
3755
  const max = rest.maxLength;
3255
3756
  const showCounter = showCount && max != null;
@@ -3261,7 +3762,7 @@ function Input({
3261
3762
  const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
3262
3763
  const describedBy = [error || hint ? descId : null, showCounter ? countId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
3263
3764
  const isPassword = type === "password";
3264
- const [revealed, setRevealed] = React25__namespace.default.useState(false);
3765
+ const [revealed, setRevealed] = React37__namespace.default.useState(false);
3265
3766
  const effectiveType = isPassword && revealed ? "text" : type;
3266
3767
  const suffix = rightIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-input__affix", children: rightIcon }) : isPassword ? /* @__PURE__ */ jsxRuntime.jsx(
3267
3768
  "button",
@@ -3455,6 +3956,8 @@ function MultiSelect({
3455
3956
  name,
3456
3957
  max,
3457
3958
  maxTagCount,
3959
+ virtualized = false,
3960
+ overscan = 8,
3458
3961
  id,
3459
3962
  className = "",
3460
3963
  onFocus,
@@ -3462,27 +3965,49 @@ function MultiSelect({
3462
3965
  ...rest
3463
3966
  }) {
3464
3967
  const __twcStyles = useScopedStyles("twc-ms-styles", MULTI_CSS);
3465
- const groups = React25__namespace.default.useMemo(() => normalizeGroups3(options), [options]);
3466
- const flat = React25__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
3467
- const autoId = React25__namespace.default.useId();
3968
+ const groups = React37__namespace.default.useMemo(() => normalizeGroups3(options), [options]);
3969
+ const flat = React37__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
3970
+ const autoId = React37__namespace.default.useId();
3468
3971
  const fieldId = id || autoId;
3469
- const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
3972
+ const [internal, setInternal] = React37__namespace.default.useState(defaultValue);
3470
3973
  const selected = value !== void 0 ? value : internal;
3471
- const [open, setOpen] = React25__namespace.default.useState(false);
3472
- const [query, setQuery] = React25__namespace.default.useState("");
3473
- const [active, setActive] = React25__namespace.default.useState(0);
3474
- const [coords, setCoords] = React25__namespace.default.useState(null);
3475
- const wrapRef = React25__namespace.default.useRef(null);
3476
- const controlRef = React25__namespace.default.useRef(null);
3477
- const inputRef = React25__namespace.default.useRef(null);
3478
- const popRef = React25__namespace.default.useRef(null);
3479
- const listRef = React25__namespace.default.useRef(null);
3480
- const activeRef = React25__namespace.default.useRef(null);
3481
- const fGroups = React25__namespace.default.useMemo(
3974
+ const [open, setOpen] = React37__namespace.default.useState(false);
3975
+ const [query, setQuery] = React37__namespace.default.useState("");
3976
+ const [active, setActive] = React37__namespace.default.useState(0);
3977
+ const [coords, setCoords] = React37__namespace.default.useState(null);
3978
+ const [scrollTop, setScrollTop] = React37__namespace.default.useState(0);
3979
+ const [listH, setListH] = React37__namespace.default.useState(260);
3980
+ const wrapRef = React37__namespace.default.useRef(null);
3981
+ const controlRef = React37__namespace.default.useRef(null);
3982
+ const inputRef = React37__namespace.default.useRef(null);
3983
+ const popRef = React37__namespace.default.useRef(null);
3984
+ const listRef = React37__namespace.default.useRef(null);
3985
+ const activeRef = React37__namespace.default.useRef(null);
3986
+ const fGroups = React37__namespace.default.useMemo(
3482
3987
  () => groups.map((g) => ({ group: g.group, options: g.options.filter((o) => matches2(o, query.trim())) })).filter((g) => g.options.length),
3483
3988
  [groups, query]
3484
3989
  );
3485
- const visible = React25__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
3990
+ const visible = React37__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
3991
+ const rowH = React37__namespace.default.useMemo(() => visible.some((o) => o.description) ? 48 : 36, [visible]);
3992
+ const GROUP_H = 30;
3993
+ const { rows, totalH } = React37__namespace.default.useMemo(() => {
3994
+ if (!virtualized) return { rows: [], totalH: 0 };
3995
+ const rows2 = [];
3996
+ let off = 0;
3997
+ let optIdx = -1;
3998
+ fGroups.forEach((g, gi) => {
3999
+ if (g.group) {
4000
+ rows2.push({ kind: "group", gi, label: g.group, top: off, h: GROUP_H });
4001
+ off += GROUP_H;
4002
+ }
4003
+ g.options.forEach((o) => {
4004
+ optIdx += 1;
4005
+ rows2.push({ kind: "option", o, idx: optIdx, top: off, h: rowH });
4006
+ off += rowH;
4007
+ });
4008
+ });
4009
+ return { rows: rows2, totalH: off };
4010
+ }, [virtualized, fGroups, rowH]);
3486
4011
  const capReached = max != null && (value !== void 0 ? value : internal).length >= max;
3487
4012
  const isOptDisabled = (o) => o.disabled || capReached && !(value !== void 0 ? value : internal).includes(o.value);
3488
4013
  const nextEnabled = (from, dir) => {
@@ -3493,7 +4018,7 @@ function MultiSelect({
3493
4018
  }
3494
4019
  return from;
3495
4020
  };
3496
- const place = React25__namespace.default.useCallback(() => {
4021
+ const place = React37__namespace.default.useCallback(() => {
3497
4022
  const el = controlRef.current;
3498
4023
  if (!el) return;
3499
4024
  const r = el.getBoundingClientRect();
@@ -3508,7 +4033,7 @@ function MultiSelect({
3508
4033
  flip
3509
4034
  });
3510
4035
  }, [placement, minWidth]);
3511
- React25__namespace.default.useEffect(() => {
4036
+ React37__namespace.default.useEffect(() => {
3512
4037
  if (!open || !portal) return;
3513
4038
  place();
3514
4039
  const onMove = () => place();
@@ -3519,7 +4044,7 @@ function MultiSelect({
3519
4044
  window.removeEventListener("resize", onMove);
3520
4045
  };
3521
4046
  }, [open, portal, place]);
3522
- React25__namespace.default.useEffect(() => {
4047
+ React37__namespace.default.useEffect(() => {
3523
4048
  if (!open) return;
3524
4049
  const onDown = (e) => {
3525
4050
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -3530,12 +4055,31 @@ function MultiSelect({
3530
4055
  document.addEventListener("mousedown", onDown);
3531
4056
  return () => document.removeEventListener("mousedown", onDown);
3532
4057
  }, [open]);
3533
- React25__namespace.default.useEffect(() => {
4058
+ React37__namespace.default.useEffect(() => {
3534
4059
  setActive(0);
3535
4060
  }, [query]);
3536
- React25__namespace.default.useEffect(() => {
3537
- if (open) ensureVisible3(listRef.current, activeRef.current);
3538
- }, [active, open]);
4061
+ React37__namespace.default.useEffect(() => {
4062
+ if (!open || !virtualized) return;
4063
+ const el = listRef.current;
4064
+ if (el && el.clientHeight) setListH(el.clientHeight);
4065
+ }, [open, virtualized]);
4066
+ React37__namespace.default.useEffect(() => {
4067
+ if (!open) return;
4068
+ if (!virtualized) {
4069
+ ensureVisible3(listRef.current, activeRef.current);
4070
+ return;
4071
+ }
4072
+ const el = listRef.current;
4073
+ if (!el) return;
4074
+ const row = rows.find((r) => r.kind === "option" && r.idx === active);
4075
+ if (!row) return;
4076
+ const vh = el.clientHeight || listH;
4077
+ let next = el.scrollTop;
4078
+ if (row.top < el.scrollTop) next = row.top;
4079
+ else if (row.top + row.h > el.scrollTop + vh) next = row.top + row.h - vh;
4080
+ if (next !== el.scrollTop) el.scrollTop = next;
4081
+ setScrollTop(next);
4082
+ }, [active, open, virtualized, rows, listH]);
3539
4083
  function commit(next) {
3540
4084
  if (value === void 0) setInternal(next);
3541
4085
  onChange?.(next);
@@ -3572,48 +4116,74 @@ function MultiSelect({
3572
4116
  const activeId = open && visible[active] ? optionId(active) : void 0;
3573
4117
  const descId = `${fieldId}-desc`;
3574
4118
  const describedBy = error || hint ? descId : void 0;
3575
- let counter = -1;
3576
- const popInner = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", id: listboxId, ref: listRef, role: "listbox", "aria-multiselectable": "true", children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-pop__loading", role: "status", children: [
3577
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-pop__spinner", "aria-hidden": "true" }),
3578
- "Loading\u2026"
3579
- ] }) : visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: emptyText }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React25__namespace.default.Fragment, { children: [
3580
- g.group ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: g.group }) : null,
3581
- g.options.map((o) => {
3582
- counter += 1;
3583
- const idx = counter;
3584
- const isSel = selected.includes(o.value);
3585
- const optDisabled = isOptDisabled(o);
3586
- return /* @__PURE__ */ jsxRuntime.jsxs(
3587
- "button",
3588
- {
3589
- id: optionId(idx),
3590
- type: "button",
3591
- className: "twc-opt",
3592
- role: "option",
3593
- "aria-selected": isSel,
3594
- ref: idx === active ? activeRef : null,
3595
- disabled: optDisabled || void 0,
3596
- "aria-disabled": optDisabled || void 0,
3597
- "data-disabled": optDisabled || void 0,
3598
- "data-selected": isSel || void 0,
3599
- "data-active": idx === active || void 0,
3600
- onMouseEnter: () => {
3601
- if (!optDisabled) setActive(idx);
3602
- },
3603
- onMouseDown: (e) => e.preventDefault(),
3604
- onClick: () => toggle(o.value),
3605
- children: [
3606
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__box", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) }) }),
3607
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-opt__main", children: [
3608
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__label", children: o.label }),
3609
- o.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__desc", children: o.description }) : null
3610
- ] })
3611
- ]
4119
+ const renderOption = (o, idx) => {
4120
+ const isSel = selected.includes(o.value);
4121
+ const optDisabled = isOptDisabled(o);
4122
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4123
+ "button",
4124
+ {
4125
+ id: optionId(idx),
4126
+ type: "button",
4127
+ className: "twc-opt",
4128
+ role: "option",
4129
+ "aria-selected": isSel,
4130
+ ref: idx === active ? activeRef : null,
4131
+ disabled: optDisabled || void 0,
4132
+ "aria-disabled": optDisabled || void 0,
4133
+ "data-disabled": optDisabled || void 0,
4134
+ "data-selected": isSel || void 0,
4135
+ "data-active": idx === active || void 0,
4136
+ onMouseEnter: () => {
4137
+ if (!optDisabled) setActive(idx);
3612
4138
  },
3613
- o.value
3614
- );
3615
- })
3616
- ] }, gi)) });
4139
+ onMouseDown: (e) => e.preventDefault(),
4140
+ onClick: () => toggle(o.value),
4141
+ children: [
4142
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__box", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) }) }),
4143
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-opt__main", children: [
4144
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__label", children: o.label }),
4145
+ o.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-opt__desc", children: o.description }) : null
4146
+ ] })
4147
+ ]
4148
+ },
4149
+ o.value
4150
+ );
4151
+ };
4152
+ let vTop = 0, vBottom = 0, vShown = rows;
4153
+ if (virtualized && rows.length) {
4154
+ const winTop = scrollTop - overscan * rowH;
4155
+ const winBottom = scrollTop + listH + overscan * rowH;
4156
+ vShown = rows.filter((r) => r.top + r.h > winTop && r.top < winBottom);
4157
+ vTop = vShown.length ? vShown[0].top : 0;
4158
+ vBottom = vShown.length ? totalH - (vShown[vShown.length - 1].top + vShown[vShown.length - 1].h) : totalH;
4159
+ }
4160
+ let counter = -1;
4161
+ const popInner = /* @__PURE__ */ jsxRuntime.jsx(
4162
+ "div",
4163
+ {
4164
+ className: "twc-pop__list",
4165
+ id: listboxId,
4166
+ ref: listRef,
4167
+ role: "listbox",
4168
+ "aria-multiselectable": "true",
4169
+ onScroll: virtualized ? (e) => setScrollTop(e.currentTarget.scrollTop) : void 0,
4170
+ children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-pop__loading", role: "status", children: [
4171
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-pop__spinner", "aria-hidden": "true" }),
4172
+ "Loading\u2026"
4173
+ ] }) : visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: emptyText }) : virtualized ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4174
+ vTop > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", style: { height: vTop } }) : null,
4175
+ vShown.map((r) => r.kind === "group" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: r.label }, `g${r.gi}`) : renderOption(r.o, r.idx)),
4176
+ vBottom > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", style: { height: vBottom } }) : null
4177
+ ] }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React37__namespace.default.Fragment, { children: [
4178
+ g.group ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: g.group }) : null,
4179
+ g.options.map((o) => {
4180
+ counter += 1;
4181
+ const idx = counter;
4182
+ return renderOption(o, idx);
4183
+ })
4184
+ ] }, gi))
4185
+ }
4186
+ );
3617
4187
  const RD = { createPortal: typeof reactDom.createPortal === "function" ? reactDom.createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
3618
4188
  const canPortal = portal && RD && RD.createPortal;
3619
4189
  let popEl = null;
@@ -3806,7 +4376,7 @@ function Pagination({
3806
4376
  }
3807
4377
  const jumperEnabled = showPageJumper ?? showJumper;
3808
4378
  const __twcStyles = useScopedStyles("twc-pagination-styles", PAGINATION_CSS);
3809
- const [internal, setInternal] = React25__namespace.default.useState(defaultPage);
4379
+ const [internal, setInternal] = React37__namespace.default.useState(defaultPage);
3810
4380
  const page = pageProp !== void 0 ? pageProp : internal;
3811
4381
  const pages = buildPages(page, total, siblings, boundaries);
3812
4382
  const go = (p) => {
@@ -3814,7 +4384,7 @@ function Pagination({
3814
4384
  if (pageProp === void 0) setInternal(p);
3815
4385
  onChange?.(p);
3816
4386
  };
3817
- const [jump, setJump] = React25__namespace.default.useState("");
4387
+ const [jump, setJump] = React37__namespace.default.useState("");
3818
4388
  const submitJump = () => {
3819
4389
  const n = parseInt(jump, 10);
3820
4390
  if (!Number.isNaN(n)) go(Math.min(Math.max(n, 1), total));
@@ -3897,13 +4467,13 @@ function Tooltip({
3897
4467
  ...rest
3898
4468
  }) {
3899
4469
  const __twcStyles = useScopedStyles("twc-tooltip-styles", TOOLTIP_CSS);
3900
- const id = React25__namespace.default.useId();
3901
- const [show, setShow] = React25__namespace.default.useState(false);
3902
- const [coords, setCoords] = React25__namespace.default.useState(null);
3903
- const timer = React25__namespace.default.useRef(null);
3904
- const closeTimer = React25__namespace.default.useRef(null);
3905
- const wrapRef = React25__namespace.default.useRef(null);
3906
- const tipRef = React25__namespace.default.useRef(null);
4470
+ const id = React37__namespace.default.useId();
4471
+ const [show, setShow] = React37__namespace.default.useState(false);
4472
+ const [coords, setCoords] = React37__namespace.default.useState(null);
4473
+ const timer = React37__namespace.default.useRef(null);
4474
+ const closeTimer = React37__namespace.default.useRef(null);
4475
+ const wrapRef = React37__namespace.default.useRef(null);
4476
+ const tipRef = React37__namespace.default.useRef(null);
3907
4477
  const open = () => {
3908
4478
  clearTimeout(closeTimer.current);
3909
4479
  clearTimeout(timer.current);
@@ -3917,11 +4487,11 @@ function Tooltip({
3917
4487
  const cancelClose = () => {
3918
4488
  clearTimeout(closeTimer.current);
3919
4489
  };
3920
- React25__namespace.default.useEffect(() => () => {
4490
+ React37__namespace.default.useEffect(() => () => {
3921
4491
  clearTimeout(timer.current);
3922
4492
  clearTimeout(closeTimer.current);
3923
4493
  }, []);
3924
- const place = React25__namespace.default.useCallback(() => {
4494
+ const place = React37__namespace.default.useCallback(() => {
3925
4495
  const el = wrapRef.current;
3926
4496
  if (!el) return;
3927
4497
  const r = el.getBoundingClientRect();
@@ -3944,10 +4514,10 @@ function Tooltip({
3944
4514
  else if (side === "right") setCoords({ ...base, top: clampY(cy), left: Math.round(r.right + gap) });
3945
4515
  else setCoords({ ...base, left: clampX(cx), bottom: Math.round(vh - r.top + gap) });
3946
4516
  }, [placement]);
3947
- React25__namespace.default.useEffect(() => {
4517
+ React37__namespace.default.useEffect(() => {
3948
4518
  place();
3949
4519
  }, [place]);
3950
- React25__namespace.default.useEffect(() => {
4520
+ React37__namespace.default.useEffect(() => {
3951
4521
  if (!show) return void 0;
3952
4522
  place();
3953
4523
  const onMove = () => place();
@@ -3958,7 +4528,7 @@ function Tooltip({
3958
4528
  window.removeEventListener("resize", onMove);
3959
4529
  };
3960
4530
  }, [show, place]);
3961
- React25__namespace.default.useEffect(() => {
4531
+ React37__namespace.default.useEffect(() => {
3962
4532
  if (!show) return;
3963
4533
  const onKeyDown = (e) => {
3964
4534
  if (e.key === "Escape") {
@@ -3970,7 +4540,7 @@ function Tooltip({
3970
4540
  return () => document.removeEventListener("keydown", onKeyDown);
3971
4541
  }, [show]);
3972
4542
  const describedBy = show ? id : void 0;
3973
- const trigger = React25__namespace.default.isValidElement(children) && children.type !== React25__namespace.default.Fragment ? React25__namespace.default.cloneElement(children, {
4543
+ const trigger = React37__namespace.default.isValidElement(children) && children.type !== React37__namespace.default.Fragment ? React37__namespace.default.cloneElement(children, {
3974
4544
  "aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
3975
4545
  }) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-describedby": describedBy, children });
3976
4546
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -4574,9 +5144,9 @@ function runDatatableQuery(rows, query, options = {}) {
4574
5144
  return { rows: page, total, filtered: out };
4575
5145
  }
4576
5146
  function useFloating() {
4577
- const [pos, setPos] = React25__namespace.default.useState(null);
4578
- const cfg = React25__namespace.default.useRef(null);
4579
- const place = React25__namespace.default.useCallback(() => {
5147
+ const [pos, setPos] = React37__namespace.default.useState(null);
5148
+ const cfg = React37__namespace.default.useRef(null);
5149
+ const place = React37__namespace.default.useCallback(() => {
4580
5150
  const c = cfg.current;
4581
5151
  if (!c || !c.el || !c.el.isConnected) return null;
4582
5152
  const r = c.el.getBoundingClientRect();
@@ -4587,17 +5157,17 @@ function useFloating() {
4587
5157
  const top = r.bottom + 6;
4588
5158
  return { top, left, width: c.width, anchorX: r.left + r.width / 2, maxHeight: Math.max(180, vh - top - M) };
4589
5159
  }, []);
4590
- const open = React25__namespace.default.useCallback((el, align = "left", width = 220) => {
5160
+ const open = React37__namespace.default.useCallback((el, align = "left", width = 220) => {
4591
5161
  cfg.current = { el, align, width };
4592
5162
  const p = place();
4593
5163
  if (p) setPos(p);
4594
5164
  }, [place]);
4595
- const close = React25__namespace.default.useCallback(() => {
5165
+ const close = React37__namespace.default.useCallback(() => {
4596
5166
  cfg.current = null;
4597
5167
  setPos(null);
4598
5168
  }, []);
4599
5169
  const isOpen = pos != null;
4600
- React25__namespace.default.useEffect(() => {
5170
+ React37__namespace.default.useEffect(() => {
4601
5171
  if (!isOpen) return void 0;
4602
5172
  const update = () => {
4603
5173
  const p = place();
@@ -4621,9 +5191,9 @@ function Caret({ pos }) {
4621
5191
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__caret", style: { left } });
4622
5192
  }
4623
5193
  function EditCell({ col, value, options, onChange, onCommit, onCommitValue, onCancel, onKeyDown }) {
4624
- const ref = React25__namespace.default.useRef(null);
5194
+ const ref = React37__namespace.default.useRef(null);
4625
5195
  const isSelect = col.editType === "select" || options && col.editType !== "text";
4626
- React25__namespace.default.useEffect(() => {
5196
+ React37__namespace.default.useEffect(() => {
4627
5197
  if (isSelect) {
4628
5198
  const t = setTimeout(() => ref.current?.querySelector(".twc-sel__trigger")?.click(), 0);
4629
5199
  return () => clearTimeout(t);
@@ -4787,6 +5357,9 @@ function Datatable({
4787
5357
  density: densityProp = "comfortable",
4788
5358
  pageSize = 10,
4789
5359
  pageSizeOptions = [5, 10, 25, 50],
5360
+ page,
5361
+ onPageChange,
5362
+ onPageSizeChange,
4790
5363
  height = 440,
4791
5364
  serverMode = false,
4792
5365
  rowCount,
@@ -4828,7 +5401,7 @@ function Datatable({
4828
5401
  ...rest
4829
5402
  }) {
4830
5403
  const __twcStyles = useScopedStyles("twc-dt-styles", DT_CSS);
4831
- const cols = React25__namespace.default.useMemo(() => {
5404
+ const cols = React37__namespace.default.useMemo(() => {
4832
5405
  const out = columns.map((c) => {
4833
5406
  const isActions = c.type === "actions";
4834
5407
  return {
@@ -4863,7 +5436,7 @@ function Datatable({
4863
5436
  }
4864
5437
  return out;
4865
5438
  }, [columns, rowPinning]);
4866
- const _autoKey = React25__namespace.default.useRef();
5439
+ const _autoKey = React37__namespace.default.useRef();
4867
5440
  if (!_autoKey.current) _autoKey.current = { map: /* @__PURE__ */ new WeakMap(), n: 0 };
4868
5441
  const keyOf = rowKey || ((r, i) => {
4869
5442
  if (r != null && r.id != null) return r.id;
@@ -4878,17 +5451,17 @@ function Datatable({
4878
5451
  }
4879
5452
  return i;
4880
5453
  });
4881
- const [sort, setSort] = React25__namespace.default.useState(null);
4882
- const [filters, setFilters] = React25__namespace.default.useState([]);
4883
- const [hidden, setHidden] = React25__namespace.default.useState(() => /* @__PURE__ */ new Set());
4884
- const [showRowNum, setShowRowNum] = React25__namespace.default.useState(rowNumbers);
4885
- const [wrapped, setWrapped] = React25__namespace.default.useState(() => new Set((columns || []).filter((c) => c.wrapText).map((c) => c.field)));
5454
+ const [sort, setSort] = React37__namespace.default.useState(null);
5455
+ const [filters, setFilters] = React37__namespace.default.useState([]);
5456
+ const [hidden, setHidden] = React37__namespace.default.useState(() => /* @__PURE__ */ new Set());
5457
+ const [showRowNum, setShowRowNum] = React37__namespace.default.useState(rowNumbers);
5458
+ const [wrapped, setWrapped] = React37__namespace.default.useState(() => new Set((columns || []).filter((c) => c.wrapText).map((c) => c.field)));
4886
5459
  const toggleWrap = (field) => setWrapped((w) => {
4887
5460
  const n = new Set(w);
4888
5461
  n.has(field) ? n.delete(field) : n.add(field);
4889
5462
  return n;
4890
5463
  });
4891
- const [pins, setPins] = React25__namespace.default.useState(() => {
5464
+ const [pins, setPins] = React37__namespace.default.useState(() => {
4892
5465
  const left = [], right = [];
4893
5466
  columns.forEach((c) => {
4894
5467
  if (c.pinned === "left") left.push(c.field);
@@ -4896,34 +5469,47 @@ function Datatable({
4896
5469
  });
4897
5470
  return { left, right };
4898
5471
  });
4899
- const [density, setDensity] = React25__namespace.default.useState(densityProp);
4900
- const [quick, setQuick] = React25__namespace.default.useState("");
4901
- const [selected, setSelected] = React25__namespace.default.useState(() => /* @__PURE__ */ new Set());
4902
- const [activeRow, setActiveRow] = React25__namespace.default.useState(null);
4903
- const [activeCell, setActiveCell] = React25__namespace.default.useState(null);
4904
- const [page, setPage] = React25__namespace.default.useState(0);
4905
- const [rowsPerPage, setRowsPerPage] = React25__namespace.default.useState(pageSize > 0 ? pageSize : 10);
4906
- const [colQuery, setColQuery] = React25__namespace.default.useState("");
4907
- const [widths, setWidths] = React25__namespace.default.useState({});
4908
- const [order, setOrder] = React25__namespace.default.useState(() => columns.map((c) => c.field));
4909
- const [drag, setDrag] = React25__namespace.default.useState({ from: null, over: null, after: false });
4910
- const [aggOn, setAggOn] = React25__namespace.default.useState(showAggregation);
4911
- const [focus, setFocus] = React25__namespace.default.useState({ r: 0, c: 0 });
4912
- const gridRef = React25__namespace.default.useRef(null);
4913
- const [groupBy, setGroupBy] = React25__namespace.default.useState(rowGrouping || []);
4914
- const [collapsed, setCollapsed] = React25__namespace.default.useState(() => /* @__PURE__ */ new Set());
4915
- const [pinnedRows, setPinnedRows] = React25__namespace.default.useState({ top: [], bottom: [] });
4916
- const [headH, setHeadH] = React25__namespace.default.useState(41);
4917
- const theadRef = React25__namespace.default.useRef(null);
4918
- const [rowOrder, setRowOrder] = React25__namespace.default.useState(null);
4919
- const [rowHeights, setRowHeights] = React25__namespace.default.useState({});
4920
- const [rowDrag, setRowDrag] = React25__namespace.default.useState({ from: null, over: null, after: false });
4921
- const [rowGrab, setRowGrab] = React25__namespace.default.useState(null);
4922
- const [reorderMsg, setReorderMsg] = React25__namespace.default.useState("");
4923
- const rowFocusRef = React25__namespace.default.useRef(null);
4924
- const rootRef = React25__namespace.default.useRef(null);
4925
- const [compact, setCompact] = React25__namespace.default.useState(false);
4926
- React25__namespace.default.useEffect(() => {
5472
+ const [density, setDensity] = React37__namespace.default.useState(densityProp);
5473
+ const [quick, setQuick] = React37__namespace.default.useState("");
5474
+ const [selected, setSelected] = React37__namespace.default.useState(() => /* @__PURE__ */ new Set());
5475
+ const [activeRow, setActiveRow] = React37__namespace.default.useState(null);
5476
+ const [activeCell, setActiveCell] = React37__namespace.default.useState(null);
5477
+ const [internalPage, setInternalPage] = React37__namespace.default.useState(0);
5478
+ const [internalRpp, setInternalRpp] = React37__namespace.default.useState(pageSize > 0 ? pageSize : 10);
5479
+ const pageControlled = page !== void 0;
5480
+ const pageSizeControlled = onPageSizeChange !== void 0;
5481
+ const pageVal = pageControlled ? page : internalPage;
5482
+ const sizeVal = pageSizeControlled ? pageSize > 0 ? pageSize : 10 : internalRpp;
5483
+ const commitPage = (next) => {
5484
+ onPageChange?.(next);
5485
+ if (!pageControlled) setInternalPage(next);
5486
+ };
5487
+ const commitPageSize = (next) => {
5488
+ onPageSizeChange?.(next);
5489
+ if (!pageSizeControlled) setInternalRpp(next);
5490
+ commitPage(0);
5491
+ };
5492
+ const [colQuery, setColQuery] = React37__namespace.default.useState("");
5493
+ const [widths, setWidths] = React37__namespace.default.useState({});
5494
+ const [order, setOrder] = React37__namespace.default.useState(() => columns.map((c) => c.field));
5495
+ const [drag, setDrag] = React37__namespace.default.useState({ from: null, over: null, after: false });
5496
+ const [aggOn, setAggOn] = React37__namespace.default.useState(showAggregation);
5497
+ const [focus, setFocus] = React37__namespace.default.useState({ r: 0, c: 0 });
5498
+ const gridRef = React37__namespace.default.useRef(null);
5499
+ const [groupBy, setGroupBy] = React37__namespace.default.useState(rowGrouping || []);
5500
+ const [collapsed, setCollapsed] = React37__namespace.default.useState(() => /* @__PURE__ */ new Set());
5501
+ const [pinnedRows, setPinnedRows] = React37__namespace.default.useState({ top: [], bottom: [] });
5502
+ const [headH, setHeadH] = React37__namespace.default.useState(41);
5503
+ const theadRef = React37__namespace.default.useRef(null);
5504
+ const [rowOrder, setRowOrder] = React37__namespace.default.useState(null);
5505
+ const [rowHeights, setRowHeights] = React37__namespace.default.useState({});
5506
+ const [rowDrag, setRowDrag] = React37__namespace.default.useState({ from: null, over: null, after: false });
5507
+ const [rowGrab, setRowGrab] = React37__namespace.default.useState(null);
5508
+ const [reorderMsg, setReorderMsg] = React37__namespace.default.useState("");
5509
+ const rowFocusRef = React37__namespace.default.useRef(null);
5510
+ const rootRef = React37__namespace.default.useRef(null);
5511
+ const [compact, setCompact] = React37__namespace.default.useState(false);
5512
+ React37__namespace.default.useEffect(() => {
4927
5513
  const el = rootRef.current;
4928
5514
  if (!el) return void 0;
4929
5515
  const measure = () => setCompact((el.clientWidth || 0) < 720);
@@ -4936,11 +5522,11 @@ function Datatable({
4936
5522
  else if (typeof window !== "undefined") window.removeEventListener("resize", measure);
4937
5523
  };
4938
5524
  }, []);
4939
- const scrollRef = React25__namespace.default.useRef(null);
4940
- const [scrollTop, setScrollTop] = React25__namespace.default.useState(0);
4941
- const [viewportH, setViewportH] = React25__namespace.default.useState(0);
4942
- const [pivotOn, setPivotOn] = React25__namespace.default.useState(pivotMode);
4943
- const [aggConfig, setAggConfig] = React25__namespace.default.useState(() => {
5525
+ const scrollRef = React37__namespace.default.useRef(null);
5526
+ const [scrollTop, setScrollTop] = React37__namespace.default.useState(0);
5527
+ const [viewportH, setViewportH] = React37__namespace.default.useState(0);
5528
+ const [pivotOn, setPivotOn] = React37__namespace.default.useState(pivotMode);
5529
+ const [aggConfig, setAggConfig] = React37__namespace.default.useState(() => {
4944
5530
  const m = {};
4945
5531
  (columns || []).forEach((c) => {
4946
5532
  if (typeof c.aggregation === "string") m[c.field] = c.aggregation;
@@ -4948,13 +5534,13 @@ function Datatable({
4948
5534
  return m;
4949
5535
  });
4950
5536
  const aggOf = (c) => aggConfig[c.field] || (typeof c.aggregation === "function" ? c.aggregation : null);
4951
- const [pivotConfig, setPivotConfig] = React25__namespace.default.useState(() => ({
5537
+ const [pivotConfig, setPivotConfig] = React37__namespace.default.useState(() => ({
4952
5538
  rows: pivot && pivot.rows || [],
4953
5539
  columns: pivot && pivot.columns || [],
4954
5540
  values: pivot && pivot.values || []
4955
5541
  }));
4956
5542
  const pivotActive = pivotOn && pivotConfig.rows.length > 0 && pivotConfig.values.length > 0;
4957
- React25__namespace.default.useEffect(() => {
5543
+ React37__namespace.default.useEffect(() => {
4958
5544
  setOrder((prev) => {
4959
5545
  const fields = columns.map((c) => c.field);
4960
5546
  const kept = prev.filter((f) => fields.includes(f));
@@ -4962,32 +5548,37 @@ function Datatable({
4962
5548
  return [...kept, ...added];
4963
5549
  });
4964
5550
  }, [columns]);
4965
- React25__namespace.default.useEffect(() => {
5551
+ React37__namespace.default.useEffect(() => {
4966
5552
  setDensity(densityProp);
4967
5553
  }, [densityProp]);
4968
- React25__namespace.default.useEffect(() => {
5554
+ React37__namespace.default.useEffect(() => {
4969
5555
  setAggOn(showAggregation);
4970
5556
  }, [showAggregation]);
5557
+ React37__namespace.default.useEffect(() => {
5558
+ if (pageSizeControlled) return;
5559
+ setInternalRpp(pageSize > 0 ? pageSize : 10);
5560
+ setInternalPage(0);
5561
+ }, [pageSize]);
4971
5562
  const rowGroupingKey = (rowGrouping || []).join("\0");
4972
- const rowGroupingKeyRef = React25__namespace.default.useRef(rowGroupingKey);
4973
- React25__namespace.default.useEffect(() => {
5563
+ const rowGroupingKeyRef = React37__namespace.default.useRef(rowGroupingKey);
5564
+ React37__namespace.default.useEffect(() => {
4974
5565
  if (rowGroupingKeyRef.current === rowGroupingKey) return;
4975
5566
  rowGroupingKeyRef.current = rowGroupingKey;
4976
5567
  setGroupBy(rowGrouping || []);
4977
5568
  }, [rowGroupingKey]);
4978
5569
  const widthOf = (c) => widths[c.field] ?? c.width ?? 160;
4979
- const [colMenu, setColMenu] = React25__namespace.default.useState(null);
5570
+ const [colMenu, setColMenu] = React37__namespace.default.useState(null);
4980
5571
  const [menuPos, openMenu, closeMenu] = useFloating();
4981
- const [panel, setPanel] = React25__namespace.default.useState(null);
5572
+ const [panel, setPanel] = React37__namespace.default.useState(null);
4982
5573
  const [panelPos, openPanel, closePanel] = useFloating();
4983
- const [rowMenu, setRowMenu] = React25__namespace.default.useState(null);
5574
+ const [rowMenu, setRowMenu] = React37__namespace.default.useState(null);
4984
5575
  const [rowMenuPos, openRowMenu, closeRowMenu] = useFloating();
4985
- const [exportOpen, setExportOpen] = React25__namespace.default.useState(false);
5576
+ const [exportOpen, setExportOpen] = React37__namespace.default.useState(false);
4986
5577
  const [exportPos, openExport, closeExport] = useFloating();
4987
- const menuTriggerRef = React25__namespace.default.useRef(null);
4988
- const colMenuRef = React25__namespace.default.useRef(null);
4989
- const rowMenuRef = React25__namespace.default.useRef(null);
4990
- const exportMenuRef = React25__namespace.default.useRef(null);
5578
+ const menuTriggerRef = React37__namespace.default.useRef(null);
5579
+ const colMenuRef = React37__namespace.default.useRef(null);
5580
+ const rowMenuRef = React37__namespace.default.useRef(null);
5581
+ const exportMenuRef = React37__namespace.default.useRef(null);
4991
5582
  function focusFirstItem(container) {
4992
5583
  if (!container) return;
4993
5584
  const first = container.querySelector('[role="menuitem"]:not([disabled])');
@@ -5026,16 +5617,16 @@ function Datatable({
5026
5617
  restoreTriggerFocus();
5027
5618
  }
5028
5619
  }
5029
- React25__namespace.default.useEffect(() => {
5620
+ React37__namespace.default.useEffect(() => {
5030
5621
  if (colMenu) focusFirstItem(colMenuRef.current);
5031
5622
  }, [colMenu]);
5032
- React25__namespace.default.useEffect(() => {
5623
+ React37__namespace.default.useEffect(() => {
5033
5624
  if (rowMenu) focusFirstItem(rowMenuRef.current);
5034
5625
  }, [rowMenu]);
5035
- React25__namespace.default.useEffect(() => {
5626
+ React37__namespace.default.useEffect(() => {
5036
5627
  if (exportOpen) focusFirstItem(exportMenuRef.current);
5037
5628
  }, [exportOpen]);
5038
- React25__namespace.default.useEffect(() => {
5629
+ React37__namespace.default.useEffect(() => {
5039
5630
  if (!colMenu && !panel && !rowMenu) return;
5040
5631
  const closeAll = () => {
5041
5632
  setColMenu(null);
@@ -5058,7 +5649,7 @@ function Datatable({
5058
5649
  document.removeEventListener("keydown", onKey);
5059
5650
  };
5060
5651
  }, [colMenu, panel, rowMenu]);
5061
- React25__namespace.default.useEffect(() => {
5652
+ React37__namespace.default.useEffect(() => {
5062
5653
  if (!exportOpen) return;
5063
5654
  const close = () => {
5064
5655
  setExportOpen(false);
@@ -5077,9 +5668,9 @@ function Datatable({
5077
5668
  document.removeEventListener("keydown", onKey);
5078
5669
  };
5079
5670
  }, [exportOpen]);
5080
- const colByField = React25__namespace.default.useMemo(() => Object.fromEntries(cols.map((c) => [c.field, c])), [cols]);
5671
+ const colByField = React37__namespace.default.useMemo(() => Object.fromEntries(cols.map((c) => [c.field, c])), [cols]);
5081
5672
  const visibleCols = cols.filter((c) => !hidden.has(c.field));
5082
- const ordered = React25__namespace.default.useMemo(() => {
5673
+ const ordered = React37__namespace.default.useMemo(() => {
5083
5674
  const orderIdx = (f) => {
5084
5675
  const i = order.indexOf(f);
5085
5676
  return i === -1 ? 9999 : i;
@@ -5114,7 +5705,7 @@ function Datatable({
5114
5705
  }
5115
5706
  return {};
5116
5707
  };
5117
- const processed = React25__namespace.default.useMemo(() => {
5708
+ const processed = React37__namespace.default.useMemo(() => {
5118
5709
  if (serverMode) {
5119
5710
  if (rowOrder) {
5120
5711
  const idx = new Map(rowOrder.map((k, i) => [k, i]));
@@ -5151,12 +5742,12 @@ function Datatable({
5151
5742
  const paginated = pageSize > 0;
5152
5743
  const serverTotal = rowCount == null ? processed.length : rowCount;
5153
5744
  const totalRows = serverMode ? serverTotal : processed.length;
5154
- const totalPages = paginated ? Math.max(1, Math.ceil(totalRows / rowsPerPage)) : 1;
5155
- const paged = !paginated || serverMode ? processed : processed.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
5156
- React25__namespace.default.useEffect(() => {
5157
- if (page > totalPages - 1) setPage(0);
5745
+ const totalPages = paginated ? Math.max(1, Math.ceil(totalRows / sizeVal)) : 1;
5746
+ const paged = !paginated || serverMode ? processed : processed.slice(pageVal * sizeVal, pageVal * sizeVal + sizeVal);
5747
+ React37__namespace.default.useEffect(() => {
5748
+ if (pageVal > totalPages - 1) commitPage(0);
5158
5749
  }, [totalPages]);
5159
- const activeGroupBy = React25__namespace.default.useMemo(() => groupBy.filter((f) => colByField[f]), [groupBy, colByField]);
5750
+ const activeGroupBy = React37__namespace.default.useMemo(() => groupBy.filter((f) => colByField[f]), [groupBy, colByField]);
5160
5751
  function subtotalText(rowsIn) {
5161
5752
  const parts = [];
5162
5753
  for (const c of ordered) {
@@ -5183,7 +5774,7 @@ function Datatable({
5183
5774
  if (agg === "max") return Math.max(...nums);
5184
5775
  return null;
5185
5776
  }
5186
- const displayItems = React25__namespace.default.useMemo(() => {
5777
+ const displayItems = React37__namespace.default.useMemo(() => {
5187
5778
  if (!activeGroupBy.length) return null;
5188
5779
  const build = (rowsIn, depth, prefix) => {
5189
5780
  if (depth >= activeGroupBy.length) return rowsIn.map((row) => ({ kind: "leaf", row }));
@@ -5225,7 +5816,7 @@ function Datatable({
5225
5816
  return { top, bottom };
5226
5817
  });
5227
5818
  }
5228
- React25__namespace.default.useEffect(() => {
5819
+ React37__namespace.default.useEffect(() => {
5229
5820
  if (!rowPinning) return;
5230
5821
  const measure = () => {
5231
5822
  if (theadRef.current) setHeadH(theadRef.current.offsetHeight || 41);
@@ -5239,12 +5830,12 @@ function Datatable({
5239
5830
  const pinnedTopRows = canPinRows ? pinnedRows.top.map((k) => leafRows.find((r, i) => keyOf(r, i) === k)).filter(Boolean) : [];
5240
5831
  const pinnedBottomRows = canPinRows ? pinnedRows.bottom.map((k) => leafRows.find((r, i) => keyOf(r, i) === k)).filter(Boolean) : [];
5241
5832
  const middleRows = canPinRows ? leafRows.filter((r, i) => !pinSideOf(keyOf(r, i))) : leafRows;
5242
- const keyIndex = React25__namespace.default.useMemo(() => {
5833
+ const keyIndex = React37__namespace.default.useMemo(() => {
5243
5834
  const m = /* @__PURE__ */ new Map();
5244
5835
  leafRows.forEach((r, i) => m.set(keyOf(r, i), i));
5245
5836
  return m;
5246
5837
  }, [leafRows]);
5247
- const keyIndexMid = React25__namespace.default.useMemo(() => {
5838
+ const keyIndexMid = React37__namespace.default.useMemo(() => {
5248
5839
  const m = /* @__PURE__ */ new Map();
5249
5840
  middleRows.forEach((r, i) => m.set(keyOf(r, keyIndex.get(keyOf(r)) ?? i), i));
5250
5841
  return m;
@@ -5329,7 +5920,7 @@ function Datatable({
5329
5920
  setReorderMsg("Reorder cancelled.");
5330
5921
  }
5331
5922
  }
5332
- React25__namespace.default.useEffect(() => {
5923
+ React37__namespace.default.useEffect(() => {
5333
5924
  if (rowFocusRef.current == null) return;
5334
5925
  const key = rowFocusRef.current;
5335
5926
  rowFocusRef.current = null;
@@ -5341,7 +5932,7 @@ function Datatable({
5341
5932
  });
5342
5933
  const estRowH = rowHeight ?? (density === "compact" ? 36 : density === "comfortable" ? 56 : 44);
5343
5934
  const virtualizing = virtualized && !paginated && !activeGroupBy.length && !loading;
5344
- React25__namespace.default.useEffect(() => {
5935
+ React37__namespace.default.useEffect(() => {
5345
5936
  if (!virtualizing) return;
5346
5937
  const el = scrollRef.current;
5347
5938
  if (!el) return;
@@ -5351,13 +5942,13 @@ function Datatable({
5351
5942
  if (ro) ro.observe(el);
5352
5943
  return () => ro && ro.disconnect();
5353
5944
  }, [virtualizing, height]);
5354
- const onScrollVirtual = React25__namespace.default.useCallback((e) => {
5945
+ const onScrollVirtual = React37__namespace.default.useCallback((e) => {
5355
5946
  setScrollTop(e.currentTarget.scrollTop);
5356
5947
  }, []);
5357
5948
  const vh = viewportH || (typeof height === "number" ? height : 440);
5358
- const rowHRef = React25__namespace.default.useRef(/* @__PURE__ */ new Map());
5359
- const [measureTick, setMeasureTick] = React25__namespace.default.useState(0);
5360
- const offsets = React25__namespace.default.useMemo(() => {
5949
+ const rowHRef = React37__namespace.default.useRef(/* @__PURE__ */ new Map());
5950
+ const [measureTick, setMeasureTick] = React37__namespace.default.useState(0);
5951
+ const offsets = React37__namespace.default.useMemo(() => {
5361
5952
  if (!virtualizing) return null;
5362
5953
  const total = middleRows.length;
5363
5954
  const arr = new Float64Array(total + 1);
@@ -5367,7 +5958,7 @@ function Datatable({
5367
5958
  }
5368
5959
  return arr;
5369
5960
  }, [virtualizing, middleRows, estRowH, measureTick]);
5370
- const vWindow = React25__namespace.default.useMemo(() => {
5961
+ const vWindow = React37__namespace.default.useMemo(() => {
5371
5962
  if (!virtualizing || !offsets) return null;
5372
5963
  const total = middleRows.length;
5373
5964
  const totalH = offsets[total];
@@ -5396,7 +5987,7 @@ function Datatable({
5396
5987
  if (start > end) start = end;
5397
5988
  return { start, end, padTop: offsets[start], padBottom: Math.max(0, totalH - offsets[end]) };
5398
5989
  }, [virtualizing, offsets, middleRows.length, vh, scrollTop, overscan]);
5399
- React25__namespace.default.useLayoutEffect(() => {
5990
+ React37__namespace.default.useLayoutEffect(() => {
5400
5991
  if (!virtualizing) return;
5401
5992
  const el = scrollRef.current;
5402
5993
  if (!el) return;
@@ -5411,21 +6002,21 @@ function Datatable({
5411
6002
  }
5412
6003
  if (changed) setMeasureTick((t) => t + 1);
5413
6004
  });
5414
- const onServerChangeRef = React25__namespace.default.useRef(onServerChange);
6005
+ const onServerChangeRef = React37__namespace.default.useRef(onServerChange);
5415
6006
  onServerChangeRef.current = onServerChange;
5416
- React25__namespace.default.useEffect(() => {
6007
+ React37__namespace.default.useEffect(() => {
5417
6008
  if (!serverMode) return;
5418
6009
  const t = setTimeout(() => {
5419
6010
  onServerChangeRef.current?.({
5420
- page,
5421
- pageSize: rowsPerPage,
6011
+ page: pageVal,
6012
+ pageSize: sizeVal,
5422
6013
  sort,
5423
6014
  filters: filters.map(({ id, ...f }) => f),
5424
6015
  quickFilter: quick.trim()
5425
6016
  });
5426
6017
  }, 250);
5427
6018
  return () => clearTimeout(t);
5428
- }, [serverMode, page, rowsPerPage, sort, filters, quick]);
6019
+ }, [serverMode, pageVal, sizeVal, sort, filters, quick]);
5429
6020
  function cycleSort(field) {
5430
6021
  setSort((s) => !s || s.field !== field ? { field, dir: "asc" } : s.dir === "asc" ? { field, dir: "desc" } : null);
5431
6022
  }
@@ -5448,7 +6039,7 @@ function Datatable({
5448
6039
  return n;
5449
6040
  });
5450
6041
  }
5451
- const movableMidFields = React25__namespace.default.useMemo(
6042
+ const movableMidFields = React37__namespace.default.useMemo(
5452
6043
  () => ordered.filter((c) => !pins.left.includes(c.field) && !pins.right.includes(c.field) && c.reorderable !== false).map((c) => c.field),
5453
6044
  [ordered, pins]
5454
6045
  );
@@ -5479,7 +6070,7 @@ function Datatable({
5479
6070
  }
5480
6071
  return [...set].sort((a, b) => a.localeCompare(b)).map((v) => ({ value: v, label: v }));
5481
6072
  }
5482
- const [resizing, setResizing] = React25__namespace.default.useState(false);
6073
+ const [resizing, setResizing] = React37__namespace.default.useState(false);
5483
6074
  function startResize(e, field) {
5484
6075
  e.preventDefault();
5485
6076
  e.stopPropagation();
@@ -5586,7 +6177,7 @@ function Datatable({
5586
6177
  if (!agg) return null;
5587
6178
  if (aggregationValues && col.field in aggregationValues) {
5588
6179
  const pre = aggregationValues[col.field];
5589
- if (pre && typeof pre === "object" && !React25__namespace.default.isValidElement(pre)) {
6180
+ if (pre && typeof pre === "object" && !React37__namespace.default.isValidElement(pre)) {
5590
6181
  if (typeof agg === "string" && agg in pre) return pre[agg];
5591
6182
  } else {
5592
6183
  return pre;
@@ -5704,14 +6295,14 @@ function Datatable({
5704
6295
  focusCell(r, c);
5705
6296
  }
5706
6297
  }
5707
- React25__namespace.default.useEffect(() => {
6298
+ React37__namespace.default.useEffect(() => {
5708
6299
  setFocus((f) => ({ r: Math.min(f.r, Math.max(0, leafRows.length - 1)), c: Math.min(f.c, Math.max(0, ordered.length - 1)) }));
5709
- }, [leafRows.length, ordered.length, page]);
5710
- const selectedRows = React25__namespace.default.useMemo(() => rows.filter((r, i) => selected.has(keyOf(r, i))), [rows, selected]);
6300
+ }, [leafRows.length, ordered.length, pageVal]);
6301
+ const selectedRows = React37__namespace.default.useMemo(() => rows.filter((r, i) => selected.has(keyOf(r, i))), [rows, selected]);
5711
6302
  function clearSelection() {
5712
6303
  setSelected(/* @__PURE__ */ new Set());
5713
6304
  }
5714
- const [editing, setEditing] = React25__namespace.default.useState(null);
6305
+ const [editing, setEditing] = React37__namespace.default.useState(null);
5715
6306
  const isColEditable = (c) => c.type !== "actions" && (c.editable ?? (editMode && c.editable !== false));
5716
6307
  function beginEdit(rowK, col, row) {
5717
6308
  if (!isColEditable(col)) return;
@@ -5746,17 +6337,17 @@ function Datatable({
5746
6337
  cancelEdit();
5747
6338
  }
5748
6339
  }
5749
- const batchEditableCols = React25__namespace.default.useMemo(
6340
+ const batchEditableCols = React37__namespace.default.useMemo(
5750
6341
  () => cols.filter((c) => c.type !== "actions" && (c.editable ?? (editMode && c.editable !== false))),
5751
6342
  [cols, editMode]
5752
6343
  );
5753
- const [batchEdit, setBatchEdit] = React25__namespace.default.useState(null);
6344
+ const [batchEdit, setBatchEdit] = React37__namespace.default.useState(null);
5754
6345
  const [batchEditPos, openBatchEdit, closeBatchEdit] = useFloating();
5755
6346
  function openBatchEditor(el) {
5756
6347
  setBatchEdit({ fields: {}, values: {} });
5757
6348
  openBatchEdit(el, "left", 320);
5758
6349
  }
5759
- React25__namespace.default.useEffect(() => {
6350
+ React37__namespace.default.useEffect(() => {
5760
6351
  if (!batchEdit) return;
5761
6352
  const close = () => {
5762
6353
  setBatchEdit(null);
@@ -5775,7 +6366,7 @@ function Datatable({
5775
6366
  document.removeEventListener("keydown", onKey);
5776
6367
  };
5777
6368
  }, [batchEdit]);
5778
- React25__namespace.default.useEffect(() => {
6369
+ React37__namespace.default.useEffect(() => {
5779
6370
  if (batchEdit && selected.size === 0) {
5780
6371
  setBatchEdit(null);
5781
6372
  closeBatchEdit();
@@ -5812,7 +6403,7 @@ function Datatable({
5812
6403
  setBatchEdit(null);
5813
6404
  closeBatchEdit();
5814
6405
  }
5815
- React25__namespace.default.useEffect(() => {
6406
+ React37__namespace.default.useEffect(() => {
5816
6407
  if (!editing) return;
5817
6408
  const onDown = (e) => {
5818
6409
  if (e.target.closest(".twc-dt__editor-wrap") || e.target.closest(".twc-pop")) return;
@@ -5951,7 +6542,7 @@ function Datatable({
5951
6542
  {
5952
6543
  className: "twc-dt__row",
5953
6544
  role: "row",
5954
- "aria-rowindex": (paginated && !serverMode ? page * rowsPerPage : 0) + ri + 2,
6545
+ "aria-rowindex": (paginated && !serverMode ? pageVal * sizeVal : 0) + ri + 2,
5955
6546
  "aria-selected": (checkboxSelection ? sel : rowActive) || void 0,
5956
6547
  "data-selected": sel || void 0,
5957
6548
  "data-active": rowActive || void 0,
@@ -6009,7 +6600,7 @@ function Datatable({
6009
6600
  ] }),
6010
6601
  rowResize && !pinSide ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__row-resizer", title: "Drag to resize row", onPointerDown: (e) => startRowResize(e, k, e.currentTarget.closest("tr")), onClick: (e) => e.stopPropagation() }) : null
6011
6602
  ] }) : null,
6012
- showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td twc-dt__rownum", role: "gridcell", "aria-hidden": "true", "data-pin": "left", "data-pin-edge": pins.left.length ? void 0 : "left", style: { insetInlineStart: numLeft, width: NUM_W }, children: typeof ri === "number" ? (paginated || serverMode ? page * rowsPerPage : 0) + ri + 1 : "" }) : null,
6603
+ showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td twc-dt__rownum", role: "gridcell", "aria-hidden": "true", "data-pin": "left", "data-pin-edge": pins.left.length ? void 0 : "left", style: { insetInlineStart: numLeft, width: NUM_W }, children: typeof ri === "number" ? (paginated || serverMode ? pageVal * sizeVal : 0) + ri + 1 : "" }) : null,
6013
6604
  ordered.map((c, ci) => {
6014
6605
  const st = stickyOf(c.field);
6015
6606
  const val = row[c.field];
@@ -6337,7 +6928,7 @@ function Datatable({
6337
6928
  /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.search }),
6338
6929
  /* @__PURE__ */ jsxRuntime.jsx("input", { placeholder: "Search\u2026", "aria-label": "Search rows", value: quick, onChange: (e) => {
6339
6930
  setQuick(e.target.value);
6340
- setPage(0);
6931
+ commitPage(0);
6341
6932
  } })
6342
6933
  ] })
6343
6934
  ] }),
@@ -6539,7 +7130,7 @@ function Datatable({
6539
7130
  );
6540
7131
  })
6541
7132
  ] }) }),
6542
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: loading ? Array.from({ length: paginated ? Math.min(rowsPerPage, 8) : 8 }).map((_, ri) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "twc-dt__row", role: "row", children: [
7133
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: loading ? Array.from({ length: paginated ? Math.min(sizeVal, 8) : 8 }).map((_, ri) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "twc-dt__row", role: "row", children: [
6543
7134
  checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", role: "gridcell", "data-pin": "left", style: { insetInlineStart: 0, width: 44 }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": "18px", height: 18, borderRadius: 4 } }) }) : null,
6544
7135
  showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td twc-dt__rownum", role: "gridcell", "aria-hidden": "true", "data-pin": "left", style: { insetInlineStart: numLeft, width: NUM_W }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": "16px", height: 14, borderRadius: 4 } }) }) : null,
6545
7136
  ordered.map((c, ci) => {
@@ -6583,7 +7174,7 @@ function Datatable({
6583
7174
  const nf = (n) => n.toLocaleString();
6584
7175
  if (totalRows === 0) return "No rows";
6585
7176
  const shown = paged.length;
6586
- const start = paginated ? page * rowsPerPage + 1 : 1;
7177
+ const start = paginated ? pageVal * sizeVal + 1 : 1;
6587
7178
  const end = paginated ? start + shown - 1 : shown;
6588
7179
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6589
7180
  paginated ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -6611,13 +7202,10 @@ function Datatable({
6611
7202
  })() }),
6612
7203
  paginated ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__rpp", children: [
6613
7204
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__rpp-label", children: "Rows per page" }),
6614
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: 78 }, children: /* @__PURE__ */ jsxRuntime.jsx(Select, { size: "sm", portal: true, searchable: false, value: String(rowsPerPage), options: rppOptions, placement: "top", onChange: (v) => {
6615
- setRowsPerPage(Number(v));
6616
- setPage(0);
6617
- } }) })
7205
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: 78 }, children: /* @__PURE__ */ jsxRuntime.jsx(Select, { size: "sm", portal: true, searchable: false, value: String(sizeVal), options: rppOptions, placement: "top", onChange: (v) => commitPageSize(Number(v)) }) })
6618
7206
  ] }) : null
6619
7207
  ] }),
6620
- paginated ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__footer-row", "data-pager": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Pagination, { size: "sm", page: page + 1, total: totalPages, boundaries: 3, showPageJumper: showPageJumper && totalPages > 5, onChange: (p) => setPage(p - 1) }) }) : null
7208
+ paginated ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__footer-row", "data-pager": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Pagination, { size: "sm", page: pageVal + 1, total: totalPages, boundaries: 3, showPageJumper: showPageJumper && totalPages > 5, onChange: (p) => commitPage(p - 1) }) }) : null
6621
7209
  ] }) : null,
6622
7210
  exportOpen && exportPos ? /* @__PURE__ */ jsxRuntime.jsxs(
6623
7211
  "div",
@@ -7266,6 +7854,18 @@ var DATEPICKER_CSS = `
7266
7854
  .twc-dp__clear { position: absolute; inset-inline-end: 10px; top: 50%; transform: translateY(-50%); display: inline-grid; place-items: center; width: 20px; height: 20px; border: none; background: transparent; color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-full); }
7267
7855
  .twc-dp__clear:hover { background: var(--color-surface-sunken); color: var(--color-text); }
7268
7856
  .twc-dp__clear svg { width: 14px; height: 14px; }
7857
+ /* #105: editable (typed entry) variant \u2014 the control wraps a real text input + a trailing toggle. */
7858
+ .twc-dp__control--editable { cursor: text; gap: 0; padding-inline-end: var(--space-1); }
7859
+ .twc-dp__input { flex: 1; min-width: 0; height: 100%; border: none; background: transparent; outline: none; padding: 0;
7860
+ font-family: inherit; font-size: var(--text-sm); color: var(--color-text); }
7861
+ .twc-dp__input::placeholder { color: var(--color-text-subtle); }
7862
+ .twc-dp__input:disabled { cursor: not-allowed; }
7863
+ .twc-dp__clear--inline { position: static; transform: none; flex: none; }
7864
+ .twc-dp__toggle { flex: none; display: inline-grid; place-items: center; width: 26px; height: 26px; border: none; background: transparent;
7865
+ color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-md); transition: background-color var(--duration-fast), color var(--duration-fast); }
7866
+ .twc-dp__toggle:hover:not(:disabled) { background: var(--color-surface-sunken); color: var(--color-text); }
7867
+ .twc-dp__toggle:disabled { cursor: not-allowed; }
7868
+ .twc-dp__toggle svg { width: 17px; height: 17px; }
7269
7869
 
7270
7870
  .twc-dp__pop {
7271
7871
  position: fixed; z-index: var(--z-popover); width: 280px;
@@ -7325,6 +7925,8 @@ function DatePicker({
7325
7925
  disabled = false,
7326
7926
  tone = "primary",
7327
7927
  clearable = true,
7928
+ editable = false,
7929
+ parse,
7328
7930
  format,
7329
7931
  locale,
7330
7932
  weekStartsOn = 0,
@@ -7335,23 +7937,25 @@ function DatePicker({
7335
7937
  }) {
7336
7938
  const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS3);
7337
7939
  const __twcStyles1 = useScopedStyles("twc-datepicker-styles", DATEPICKER_CSS);
7338
- const autoId = React25__namespace.default.useId();
7940
+ const autoId = React37__namespace.default.useId();
7339
7941
  const fieldId = id || autoId;
7340
7942
  const descId = `${fieldId}-desc`;
7341
7943
  const invalid = Boolean(error);
7342
- const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
7944
+ const [internal, setInternal] = React37__namespace.default.useState(defaultValue);
7343
7945
  const selected = value !== void 0 ? value : internal;
7344
- const [open, setOpen] = React25__namespace.default.useState(false);
7345
- const [view, setView] = React25__namespace.default.useState(selected || /* @__PURE__ */ new Date());
7346
- const [mode, setMode] = React25__namespace.default.useState("days");
7347
- const [focusDate, setFocusDate] = React25__namespace.default.useState(null);
7348
- const [coords, setCoords] = React25__namespace.default.useState(null);
7349
- const wrapRef = React25__namespace.default.useRef(null);
7350
- const triggerRef = React25__namespace.default.useRef(null);
7351
- const popRef = React25__namespace.default.useRef(null);
7352
- const gridRef = React25__namespace.default.useRef(null);
7946
+ const [open, setOpen] = React37__namespace.default.useState(false);
7947
+ const [view, setView] = React37__namespace.default.useState(selected || /* @__PURE__ */ new Date());
7948
+ const [mode, setMode] = React37__namespace.default.useState("days");
7949
+ const [focusDate, setFocusDate] = React37__namespace.default.useState(null);
7950
+ const [focusMonth, setFocusMonth] = React37__namespace.default.useState(null);
7951
+ const [editText, setEditText] = React37__namespace.default.useState(null);
7952
+ const [coords, setCoords] = React37__namespace.default.useState(null);
7953
+ const wrapRef = React37__namespace.default.useRef(null);
7954
+ const triggerRef = React37__namespace.default.useRef(null);
7955
+ const popRef = React37__namespace.default.useRef(null);
7956
+ const gridRef = React37__namespace.default.useRef(null);
7353
7957
  const POP_W = 280;
7354
- const place = React25__namespace.default.useCallback(() => {
7958
+ const place = React37__namespace.default.useCallback(() => {
7355
7959
  const el = triggerRef.current;
7356
7960
  if (!el) return;
7357
7961
  const r = el.getBoundingClientRect();
@@ -7362,7 +7966,7 @@ function DatePicker({
7362
7966
  left = Math.max(8, left);
7363
7967
  setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
7364
7968
  }, []);
7365
- React25__namespace.default.useEffect(() => {
7969
+ React37__namespace.default.useEffect(() => {
7366
7970
  if (!open) return void 0;
7367
7971
  place();
7368
7972
  const onMove = () => place();
@@ -7373,7 +7977,7 @@ function DatePicker({
7373
7977
  window.removeEventListener("resize", onMove);
7374
7978
  };
7375
7979
  }, [open, place]);
7376
- React25__namespace.default.useEffect(() => {
7980
+ React37__namespace.default.useEffect(() => {
7377
7981
  if (!open) return;
7378
7982
  setView(selected || /* @__PURE__ */ new Date());
7379
7983
  setMode("days");
@@ -7393,21 +7997,10 @@ function DatePicker({
7393
7997
  document.removeEventListener("keydown", onKey);
7394
7998
  };
7395
7999
  }, [open]);
7396
- const prevOpen = React25__namespace.default.useRef(false);
7397
- React25__namespace.default.useEffect(() => {
7398
- let id2;
7399
- if (!prevOpen.current && open) {
7400
- id2 = setTimeout(() => gridRef.current?.querySelector('[tabindex="0"]')?.focus({ preventScroll: true }), 30);
7401
- } else if (prevOpen.current && !open) {
7402
- const ae = typeof document !== "undefined" ? document.activeElement : null;
7403
- if (!ae || ae === document.body) triggerRef.current?.focus();
7404
- }
7405
- prevOpen.current = open;
7406
- return () => clearTimeout(id2);
7407
- }, [open]);
7408
- const months = React25__namespace.default.useMemo(() => locale === void 0 ? MONTHS : monthNames(locale), [locale]);
7409
- const monthsShort = React25__namespace.default.useMemo(() => locale === void 0 ? MONTHS.map((n) => n.slice(0, 3)) : monthShortNames(locale), [locale]);
7410
- const dows = React25__namespace.default.useMemo(
8000
+ useFocusTrap(popRef, open && !!coords, { initialFocus: () => gridRef.current?.querySelector('[tabindex="0"]') });
8001
+ const months = React37__namespace.default.useMemo(() => locale === void 0 ? MONTHS : monthNames(locale), [locale]);
8002
+ const monthsShort = React37__namespace.default.useMemo(() => locale === void 0 ? MONTHS.map((n) => n.slice(0, 3)) : monthShortNames(locale), [locale]);
8003
+ const dows = React37__namespace.default.useMemo(
7411
8004
  () => locale === void 0 ? Array.from({ length: 7 }, (_, i) => DOW[(i + weekStartsOn) % 7]) : weekdayNames(locale, weekStartsOn),
7412
8005
  [locale, weekStartsOn]
7413
8006
  );
@@ -7419,8 +8012,33 @@ function DatePicker({
7419
8012
  const pick = (d) => {
7420
8013
  if (value === void 0) setInternal(d);
7421
8014
  onChange?.(d);
8015
+ setEditText(null);
7422
8016
  setOpen(false);
7423
8017
  };
8018
+ const parseTyped = (s) => {
8019
+ const str = s.trim();
8020
+ if (str === "") return null;
8021
+ if (parse) {
8022
+ const d = parse(str);
8023
+ return d instanceof Date && !Number.isNaN(d.getTime()) ? d : void 0;
8024
+ }
8025
+ const t = Date.parse(str);
8026
+ return Number.isNaN(t) ? void 0 : new Date(t);
8027
+ };
8028
+ const commitText = () => {
8029
+ if (editText == null) return;
8030
+ const parsed = parseTyped(editText);
8031
+ if (parsed === null) {
8032
+ setEditText(null);
8033
+ if (selected) pick(null);
8034
+ return;
8035
+ }
8036
+ if (parsed === void 0 || outOfRange(parsed)) {
8037
+ setEditText(null);
8038
+ return;
8039
+ }
8040
+ pick(parsed);
8041
+ };
7424
8042
  const y = view.getFullYear(), m = view.getMonth();
7425
8043
  const first = new Date(y, m, 1);
7426
8044
  const startOffset = (first.getDay() - weekStartsOn + 7) % 7;
@@ -7435,10 +8053,34 @@ function DatePicker({
7435
8053
  };
7436
8054
  const cells = Array.from({ length: 42 }, (_, i) => new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + i));
7437
8055
  const tabbableDate = (focusDate && cells.some((c) => sameDay(c, focusDate)) ? focusDate : null) || (selected && cells.some((c) => sameDay(c, selected)) ? selected : null) || (cells.some((c) => sameDay(c, today)) ? today : null) || new Date(y, m, 1);
7438
- React25__namespace.default.useEffect(() => {
8056
+ React37__namespace.default.useEffect(() => {
7439
8057
  if (!open || mode !== "days" || !focusDate) return;
7440
8058
  gridRef.current?.querySelector(`[data-key="${keyOf(focusDate)}"]`)?.focus();
7441
8059
  }, [focusDate, open, mode]);
8060
+ React37__namespace.default.useEffect(() => {
8061
+ if (!open || mode !== "months" || focusMonth == null) return;
8062
+ gridRef.current?.querySelector(`[data-mo="${focusMonth}"]`)?.focus();
8063
+ }, [focusMonth, open, mode]);
8064
+ const onMonthsKeyDown = (e) => {
8065
+ const cur = focusMonth == null ? m : focusMonth;
8066
+ let next;
8067
+ if (e.key === "ArrowRight") next = cur + 1;
8068
+ else if (e.key === "ArrowLeft") next = cur - 1;
8069
+ else if (e.key === "ArrowDown") next = cur + 3;
8070
+ else if (e.key === "ArrowUp") next = cur - 3;
8071
+ else if (e.key === "Home") next = 0;
8072
+ else if (e.key === "End") next = 11;
8073
+ else return;
8074
+ e.preventDefault();
8075
+ if (next < 0) {
8076
+ setView(new Date(y - 1, 0, 1));
8077
+ next += 12;
8078
+ } else if (next > 11) {
8079
+ setView(new Date(y + 1, 0, 1));
8080
+ next -= 12;
8081
+ }
8082
+ setFocusMonth(next);
8083
+ };
7442
8084
  const onGridKeyDown = (e) => {
7443
8085
  const btn = e.target.closest?.("[data-key]");
7444
8086
  if (!btn) return;
@@ -7472,7 +8114,82 @@ function DatePicker({
7472
8114
  label,
7473
8115
  required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
7474
8116
  ] }) : null,
7475
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dp__field", children: [
8117
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dp__field", children: editable ? (
8118
+ // #105: typed entry — the trigger is a real text input with a trailing
8119
+ // calendar toggle button; typing commits via `parse` on Enter/blur.
8120
+ /* @__PURE__ */ jsxRuntime.jsxs(
8121
+ "div",
8122
+ {
8123
+ className: "twc-dp__control twc-dp__control--editable",
8124
+ "data-open": open || void 0,
8125
+ "data-disabled": disabled || void 0,
8126
+ "data-tone": tone,
8127
+ "data-invalid": invalid || void 0,
8128
+ children: [
8129
+ /* @__PURE__ */ jsxRuntime.jsx(
8130
+ "input",
8131
+ {
8132
+ ref: triggerRef,
8133
+ className: "twc-dp__input",
8134
+ id: fieldId,
8135
+ type: "text",
8136
+ inputMode: "numeric",
8137
+ autoComplete: "off",
8138
+ disabled,
8139
+ placeholder,
8140
+ value: editText != null ? editText : selected ? fmt(selected) : "",
8141
+ "aria-haspopup": "dialog",
8142
+ "aria-expanded": open,
8143
+ "aria-labelledby": label ? `${fieldId}-label` : void 0,
8144
+ "aria-invalid": invalid || void 0,
8145
+ "aria-describedby": error || hint ? descId : void 0,
8146
+ onChange: (e) => setEditText(e.target.value),
8147
+ onKeyDown: (e) => {
8148
+ if (e.key === "Enter") {
8149
+ e.preventDefault();
8150
+ commitText();
8151
+ } else if (e.key === "ArrowDown" && (e.altKey || !open)) {
8152
+ e.preventDefault();
8153
+ setOpen(true);
8154
+ } else if (e.key === "Escape" && open) setOpen(false);
8155
+ },
8156
+ onBlur: (e) => {
8157
+ if (popRef.current && popRef.current.contains(e.relatedTarget)) return;
8158
+ commitText();
8159
+ }
8160
+ }
8161
+ ),
8162
+ clearable && selected && !disabled ? /* @__PURE__ */ jsxRuntime.jsx(
8163
+ "button",
8164
+ {
8165
+ type: "button",
8166
+ className: "twc-dp__clear twc-dp__clear--inline",
8167
+ "aria-label": "Clear",
8168
+ tabIndex: -1,
8169
+ onMouseDown: (e) => e.preventDefault(),
8170
+ onClick: () => pick(null),
8171
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
8172
+ }
8173
+ ) : null,
8174
+ /* @__PURE__ */ jsxRuntime.jsx(
8175
+ "button",
8176
+ {
8177
+ type: "button",
8178
+ className: "twc-dp__toggle",
8179
+ "aria-label": "Open calendar",
8180
+ tabIndex: -1,
8181
+ disabled,
8182
+ onClick: () => !disabled && setOpen((o) => !o),
8183
+ children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
8184
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
8185
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 2v4M8 2v4M3 10h18" })
8186
+ ] })
8187
+ }
8188
+ )
8189
+ ]
8190
+ }
8191
+ )
8192
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7476
8193
  /* @__PURE__ */ jsxRuntime.jsxs(
7477
8194
  "div",
7478
8195
  {
@@ -7511,7 +8228,7 @@ function DatePicker({
7511
8228
  e.stopPropagation();
7512
8229
  pick(null);
7513
8230
  }, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
7514
- ] }),
8231
+ ] }) }),
7515
8232
  open && coords ? reactDom.createPortal(
7516
8233
  /* @__PURE__ */ jsxRuntime.jsxs(
7517
8234
  "div",
@@ -7519,12 +8236,16 @@ function DatePicker({
7519
8236
  className: "twc-dp__pop",
7520
8237
  ref: popRef,
7521
8238
  role: "dialog",
8239
+ "aria-modal": "true",
7522
8240
  "aria-label": "Choose date",
7523
8241
  style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-tooltip)" },
7524
8242
  children: [
7525
8243
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dp__head", children: [
7526
8244
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__nav", "aria-label": "Previous", onClick: () => setView(mode === "months" ? new Date(y - 1, m, 1) : new Date(y, m - 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
7527
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__title", onClick: () => setMode(mode === "days" ? "months" : "days"), children: mode === "days" ? `${months[m]} ${y}` : y }),
8245
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__title", onClick: () => {
8246
+ if (mode === "days") setFocusMonth(m);
8247
+ setMode(mode === "days" ? "months" : "days");
8248
+ }, children: mode === "days" ? `${months[m]} ${y}` : y }),
7528
8249
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dp__sr", "aria-live": "polite", children: mode === "days" ? `${months[m]} ${y}` : y }),
7529
8250
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__nav", "aria-label": "Next", onClick: () => setView(mode === "months" ? new Date(y + 1, m, 1) : new Date(y, m + 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) }) })
7530
8251
  ] }),
@@ -7552,11 +8273,14 @@ function DatePicker({
7552
8273
  i
7553
8274
  );
7554
8275
  })
7555
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dp__months", children: monthsShort.map((name, i) => /* @__PURE__ */ jsxRuntime.jsx(
8276
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dp__months", ref: gridRef, onKeyDown: onMonthsKeyDown, role: "grid", children: monthsShort.map((name, i) => /* @__PURE__ */ jsxRuntime.jsx(
7556
8277
  "button",
7557
8278
  {
7558
8279
  type: "button",
7559
8280
  className: "twc-dp__mo",
8281
+ role: "gridcell",
8282
+ "data-mo": i,
8283
+ tabIndex: i === (focusMonth ?? m) ? 0 : -1,
7560
8284
  "data-selected": selected && selected.getFullYear() === y && selected.getMonth() === i || void 0,
7561
8285
  onClick: () => {
7562
8286
  setView(new Date(y, i, 1));
@@ -7603,6 +8327,17 @@ var RANGE_CSS = `
7603
8327
  .twc-drp__ic svg { width: 17px; height: 17px; }
7604
8328
  .twc-drp__text { flex: 1; font-size: var(--text-sm); color: var(--color-text); white-space: nowrap; }
7605
8329
  .twc-drp__text[data-placeholder="true"] { color: var(--color-text-subtle); }
8330
+ /* #105: editable (typed entry) variant. */
8331
+ .twc-drp__control--editable { cursor: text; gap: 0; padding-inline-end: var(--space-1); }
8332
+ .twc-drp__input { flex: 1; min-width: 0; height: 100%; border: none; background: transparent; outline: none; padding: 0;
8333
+ font-family: inherit; font-size: var(--text-sm); color: var(--color-text); }
8334
+ .twc-drp__input::placeholder { color: var(--color-text-subtle); }
8335
+ .twc-drp__input:disabled { cursor: not-allowed; }
8336
+ .twc-drp__toggle { flex: none; display: inline-grid; place-items: center; width: 26px; height: 26px; border: none; background: transparent;
8337
+ color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-md); transition: background-color var(--duration-fast), color var(--duration-fast); }
8338
+ .twc-drp__toggle:hover:not(:disabled) { background: var(--color-surface-sunken); color: var(--color-text); }
8339
+ .twc-drp__toggle:disabled { cursor: not-allowed; }
8340
+ .twc-drp__toggle svg { width: 17px; height: 17px; }
7606
8341
  .twc-drp__pop { position: fixed; z-index: var(--z-popover); display: flex;
7607
8342
  background: var(--color-surface-raised); border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-lg);
7608
8343
  box-shadow: var(--shadow-lg); animation: twico-scale-in var(--duration-fast) var(--ease-spring); transform-origin: top; }
@@ -7657,29 +8392,34 @@ function DateRangePicker({
7657
8392
  disabledDate,
7658
8393
  disabled = false,
7659
8394
  tone = "primary",
8395
+ editable = false,
8396
+ parse,
7660
8397
  onChange,
7661
8398
  className = "",
7662
8399
  ...rest
7663
8400
  }) {
7664
8401
  const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS4);
7665
8402
  const __twcStyles1 = useScopedStyles("twc-drp-styles", RANGE_CSS);
7666
- const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
8403
+ const [internal, setInternal] = React37__namespace.default.useState(defaultValue);
7667
8404
  const range = value !== void 0 ? value : internal;
7668
- const [open, setOpen] = React25__namespace.default.useState(false);
7669
- const [view, setView] = React25__namespace.default.useState(range.start || /* @__PURE__ */ new Date());
7670
- const [hover, setHover] = React25__namespace.default.useState(null);
7671
- const [coords, setCoords] = React25__namespace.default.useState(null);
7672
- const wrapRef = React25__namespace.default.useRef(null);
7673
- const triggerRef = React25__namespace.default.useRef(null);
7674
- const popRef = React25__namespace.default.useRef(null);
7675
- const labelId = React25__namespace.default.useId();
8405
+ const [open, setOpen] = React37__namespace.default.useState(false);
8406
+ const [view, setView] = React37__namespace.default.useState(range.start || /* @__PURE__ */ new Date());
8407
+ const [hover, setHover] = React37__namespace.default.useState(null);
8408
+ const [focusDate, setFocusDate] = React37__namespace.default.useState(null);
8409
+ const [editText, setEditText] = React37__namespace.default.useState(null);
8410
+ const [coords, setCoords] = React37__namespace.default.useState(null);
8411
+ const wrapRef = React37__namespace.default.useRef(null);
8412
+ const triggerRef = React37__namespace.default.useRef(null);
8413
+ const popRef = React37__namespace.default.useRef(null);
8414
+ const gridRef = React37__namespace.default.useRef(null);
8415
+ const labelId = React37__namespace.default.useId();
7676
8416
  const descId = `${labelId}-desc`;
7677
8417
  const invalid = Boolean(error);
7678
- React25__namespace.default.useEffect(() => {
8418
+ React37__namespace.default.useEffect(() => {
7679
8419
  if (disabled) setOpen(false);
7680
8420
  }, [disabled]);
7681
8421
  const POP_W = 420;
7682
- const place = React25__namespace.default.useCallback(() => {
8422
+ const place = React37__namespace.default.useCallback(() => {
7683
8423
  const el = triggerRef.current;
7684
8424
  if (!el) return;
7685
8425
  const r = el.getBoundingClientRect();
@@ -7690,7 +8430,7 @@ function DateRangePicker({
7690
8430
  left = Math.max(8, left);
7691
8431
  setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
7692
8432
  }, []);
7693
- React25__namespace.default.useEffect(() => {
8433
+ React37__namespace.default.useEffect(() => {
7694
8434
  if (!open) return void 0;
7695
8435
  place();
7696
8436
  const onMove = () => place();
@@ -7701,7 +8441,7 @@ function DateRangePicker({
7701
8441
  window.removeEventListener("resize", onMove);
7702
8442
  };
7703
8443
  }, [open, place]);
7704
- React25__namespace.default.useEffect(() => {
8444
+ React37__namespace.default.useEffect(() => {
7705
8445
  if (!open) return;
7706
8446
  const onDown = (e) => {
7707
8447
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -7722,7 +8462,86 @@ function DateRangePicker({
7722
8462
  if (value === void 0) setInternal(r);
7723
8463
  onChange?.(r);
7724
8464
  };
8465
+ const parseOne = (s) => {
8466
+ const str = s.trim();
8467
+ if (str === "") return null;
8468
+ if (parse) {
8469
+ const d = parse(str);
8470
+ return d instanceof Date && !Number.isNaN(d.getTime()) ? d : void 0;
8471
+ }
8472
+ const t = Date.parse(str);
8473
+ return Number.isNaN(t) ? void 0 : new Date(t);
8474
+ };
8475
+ const commitText = () => {
8476
+ if (editText == null) return;
8477
+ const raw = editText.trim();
8478
+ if (raw === "") {
8479
+ setEditText(null);
8480
+ if (range.start || range.end) set({ start: null, end: null });
8481
+ return;
8482
+ }
8483
+ const parts = raw.split(/\s*(?:–|—|\bto\b|\.\.+)\s*/i).map((p) => p.trim());
8484
+ let a = parseOne(parts[0] || "");
8485
+ let b = parts.length > 1 ? parseOne(parts[1] || "") : null;
8486
+ if (a === void 0 || b === void 0 || a && outOfRange(a) || b && outOfRange(b)) {
8487
+ setEditText(null);
8488
+ return;
8489
+ }
8490
+ if (a && b && ymd(b) < ymd(a)) {
8491
+ const t = a;
8492
+ a = b;
8493
+ b = t;
8494
+ }
8495
+ set({ start: a || null, end: b || null });
8496
+ setEditText(null);
8497
+ setOpen(false);
8498
+ };
8499
+ useFocusTrap(popRef, open && !!coords, { initialFocus: () => gridRef.current?.querySelector('[tabindex="0"]') });
7725
8500
  const outOfRange = (d) => min && ymd(d) < ymd(min) || max && ymd(d) > ymd(max) || Boolean(disabledDate && disabledDate(d));
8501
+ const sameDay2 = (a, b) => a && b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
8502
+ const keyOf = (d) => `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
8503
+ const addDays = (d, n) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
8504
+ const addMonths = (d, n) => {
8505
+ const last = new Date(d.getFullYear(), d.getMonth() + n + 1, 0);
8506
+ return new Date(last.getFullYear(), last.getMonth(), Math.min(d.getDate(), last.getDate()));
8507
+ };
8508
+ React37__namespace.default.useEffect(() => {
8509
+ if (!open) {
8510
+ setFocusDate(null);
8511
+ setHover(null);
8512
+ }
8513
+ }, [open]);
8514
+ React37__namespace.default.useEffect(() => {
8515
+ if (!open || !focusDate) return;
8516
+ gridRef.current?.querySelector(`[data-key="${keyOf(focusDate)}"]`)?.focus();
8517
+ }, [focusDate, open]);
8518
+ const onGridKeyDown = (e) => {
8519
+ const btn = e.target.closest && e.target.closest("[data-key]");
8520
+ if (!btn) return;
8521
+ const [fy, fm, fd] = btn.getAttribute("data-key").split("-").map(Number);
8522
+ const cur = new Date(fy, fm, fd);
8523
+ let step;
8524
+ if (e.key === "ArrowLeft") step = (d) => addDays(d, -1);
8525
+ else if (e.key === "ArrowRight") step = (d) => addDays(d, 1);
8526
+ else if (e.key === "ArrowUp") step = (d) => addDays(d, -7);
8527
+ else if (e.key === "ArrowDown") step = (d) => addDays(d, 7);
8528
+ else if (e.key === "Home") step = (d) => addDays(d, -((d.getDay() - weekStartsOn + 7) % 7));
8529
+ else if (e.key === "End") step = (d) => addDays(d, 6 - (d.getDay() - weekStartsOn + 7) % 7);
8530
+ else if (e.key === "PageUp") step = (d) => addMonths(d, -1);
8531
+ else if (e.key === "PageDown") step = (d) => addMonths(d, 1);
8532
+ else return;
8533
+ e.preventDefault();
8534
+ let next = step(cur), guard = 0;
8535
+ while (outOfRange(next) && guard < 366) {
8536
+ next = step(next);
8537
+ guard += 1;
8538
+ }
8539
+ if (outOfRange(next)) return;
8540
+ setFocusDate(next);
8541
+ setHover(next);
8542
+ if (next.getFullYear() !== view.getFullYear() || next.getMonth() !== view.getMonth()) setView(new Date(next.getFullYear(), next.getMonth(), 1));
8543
+ };
8544
+ const tabbableDate = focusDate || range.start || /* @__PURE__ */ new Date();
7726
8545
  const clickDay = (d) => {
7727
8546
  if (outOfRange(d)) return;
7728
8547
  if (!range.start || range.start && range.end) {
@@ -7741,8 +8560,8 @@ function DateRangePicker({
7741
8560
  setView(start);
7742
8561
  setOpen(false);
7743
8562
  };
7744
- const months = React25__namespace.default.useMemo(() => locale === void 0 ? MONTHS2 : monthNames2(locale), [locale]);
7745
- const dows = React25__namespace.default.useMemo(
8563
+ const months = React37__namespace.default.useMemo(() => locale === void 0 ? MONTHS2 : monthNames2(locale), [locale]);
8564
+ const dows = React37__namespace.default.useMemo(
7746
8565
  () => locale === void 0 ? Array.from({ length: 7 }, (_, i) => DOW2[(i + weekStartsOn) % 7]) : weekdayNames2(locale, weekStartsOn),
7747
8566
  [locale, weekStartsOn]
7748
8567
  );
@@ -7772,7 +8591,57 @@ function DateRangePicker({
7772
8591
  label,
7773
8592
  required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
7774
8593
  ] }) : null,
7775
- /* @__PURE__ */ jsxRuntime.jsxs(
8594
+ editable ? (
8595
+ // #105: typed entry — a text input accepting "start – end"; commits via `parse` on Enter/blur.
8596
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drp__control twc-drp__control--editable", "data-open": open || void 0, "data-disabled": disabled || void 0, "data-invalid": invalid || void 0, "data-tone": tone, children: [
8597
+ /* @__PURE__ */ jsxRuntime.jsx(
8598
+ "input",
8599
+ {
8600
+ ref: triggerRef,
8601
+ className: "twc-drp__input",
8602
+ type: "text",
8603
+ autoComplete: "off",
8604
+ disabled,
8605
+ placeholder,
8606
+ value: editText != null ? editText : text,
8607
+ "aria-haspopup": "dialog",
8608
+ "aria-expanded": open,
8609
+ "aria-labelledby": label ? labelId : void 0,
8610
+ "aria-invalid": invalid || void 0,
8611
+ "aria-describedby": error || hint ? descId : void 0,
8612
+ onChange: (e) => setEditText(e.target.value),
8613
+ onKeyDown: (e) => {
8614
+ if (e.key === "Enter") {
8615
+ e.preventDefault();
8616
+ commitText();
8617
+ } else if (e.key === "ArrowDown" && (e.altKey || !open)) {
8618
+ e.preventDefault();
8619
+ setOpen(true);
8620
+ } else if (e.key === "Escape" && open) setOpen(false);
8621
+ },
8622
+ onBlur: (e) => {
8623
+ if (popRef.current && popRef.current.contains(e.relatedTarget)) return;
8624
+ commitText();
8625
+ }
8626
+ }
8627
+ ),
8628
+ /* @__PURE__ */ jsxRuntime.jsx(
8629
+ "button",
8630
+ {
8631
+ type: "button",
8632
+ className: "twc-drp__toggle",
8633
+ "aria-label": "Open calendar",
8634
+ tabIndex: -1,
8635
+ disabled,
8636
+ onClick: () => !disabled && setOpen((o) => !o),
8637
+ children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
8638
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
8639
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 2v4M8 2v4M3 10h18" })
8640
+ ] })
8641
+ }
8642
+ )
8643
+ ] })
8644
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
7776
8645
  "div",
7777
8646
  {
7778
8647
  ref: triggerRef,
@@ -7812,6 +8681,7 @@ function DateRangePicker({
7812
8681
  className: "twc-drp__pop",
7813
8682
  ref: popRef,
7814
8683
  role: "dialog",
8684
+ "aria-modal": "true",
7815
8685
  "aria-label": "Choose date range",
7816
8686
  style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-tooltip)" },
7817
8687
  children: [
@@ -7831,7 +8701,7 @@ function DateRangePicker({
7831
8701
  ] }),
7832
8702
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-drp__nav", "aria-label": "Next month", onClick: () => setView(new Date(y, m + 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) }) })
7833
8703
  ] }),
7834
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drp__grid", children: [
8704
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drp__grid", ref: gridRef, onKeyDown: onGridKeyDown, role: "grid", children: [
7835
8705
  dows.map((d, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drp__dow", children: d }, i)),
7836
8706
  Array.from({ length: 42 }).map((_, i) => {
7837
8707
  const d = new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + i);
@@ -7843,6 +8713,8 @@ function DateRangePicker({
7843
8713
  className: "twc-drp__day",
7844
8714
  "data-outside": outside || void 0,
7845
8715
  disabled: outOfRange(d) || void 0,
8716
+ "data-key": keyOf(d),
8717
+ tabIndex: sameDay2(d, tabbableDate) ? 0 : -1,
7846
8718
  "data-in": inRange(t) || void 0,
7847
8719
  "data-edge": edgeOf(t) || void 0,
7848
8720
  "aria-pressed": !!edgeOf(t),
@@ -7929,14 +8801,14 @@ function Dialog({
7929
8801
  className = "",
7930
8802
  ...rest
7931
8803
  }) {
7932
- const autoId = React25__namespace.default.useId();
8804
+ const autoId = React37__namespace.default.useId();
7933
8805
  const titleId = `${autoId}-title`;
7934
8806
  const descId = `${autoId}-desc`;
7935
- const dialogRef = React25__namespace.default.useRef(null);
8807
+ const dialogRef = React37__namespace.default.useRef(null);
7936
8808
  const __twcStyles = useScopedStyles("twc-dialog-styles", DIALOG_CSS);
7937
8809
  const renderPortal = usePortal();
7938
- const [mounted, setMounted] = React25__namespace.default.useState(open);
7939
- React25__namespace.default.useEffect(() => {
8810
+ const [mounted, setMounted] = React37__namespace.default.useState(open);
8811
+ React37__namespace.default.useEffect(() => {
7940
8812
  if (open) {
7941
8813
  setMounted(true);
7942
8814
  return;
@@ -7947,7 +8819,7 @@ function Dialog({
7947
8819
  useScrollLock(open);
7948
8820
  useInertBackground(dialogRef, open && mounted);
7949
8821
  useFocusTrap(dialogRef, open && mounted);
7950
- React25__namespace.default.useEffect(() => {
8822
+ React37__namespace.default.useEffect(() => {
7951
8823
  if (!open) return void 0;
7952
8824
  const onKey = (e) => {
7953
8825
  if (e.key === "Escape") {
@@ -8094,14 +8966,14 @@ function Drawer({
8094
8966
  style,
8095
8967
  ...rest
8096
8968
  }) {
8097
- const autoId = React25__namespace.default.useId();
8969
+ const autoId = React37__namespace.default.useId();
8098
8970
  const titleId = `${autoId}-title`;
8099
8971
  const descId = `${autoId}-desc`;
8100
- const panelRef = React25__namespace.default.useRef(null);
8972
+ const panelRef = React37__namespace.default.useRef(null);
8101
8973
  const __twcStyles = useScopedStyles("twc-drawer-styles", DRAWER_CSS);
8102
8974
  const renderPortal = usePortal();
8103
- const [mounted, setMounted] = React25__namespace.default.useState(open);
8104
- React25__namespace.default.useEffect(() => {
8975
+ const [mounted, setMounted] = React37__namespace.default.useState(open);
8976
+ React37__namespace.default.useEffect(() => {
8105
8977
  if (open) {
8106
8978
  setMounted(true);
8107
8979
  return;
@@ -8112,7 +8984,7 @@ function Drawer({
8112
8984
  useScrollLock(open);
8113
8985
  useInertBackground(panelRef, open && mounted);
8114
8986
  useFocusTrap(panelRef, open && mounted);
8115
- React25__namespace.default.useEffect(() => {
8987
+ React37__namespace.default.useEffect(() => {
8116
8988
  if (!open) return void 0;
8117
8989
  const onKey = (e) => {
8118
8990
  if (e.key === "Escape") {
@@ -8201,11 +9073,11 @@ function Field({
8201
9073
  ...rest
8202
9074
  }) {
8203
9075
  const __twcStyles = useScopedStyles("twc-field-styles", FIELD_CSS5);
8204
- const autoId = React25__namespace.default.useId();
9076
+ const autoId = React37__namespace.default.useId();
8205
9077
  const fieldId = id || autoId;
8206
9078
  const descId = `${fieldId}-desc`;
8207
9079
  const hasMsg = Boolean(error || hint);
8208
- const control = React25__namespace.default.isValidElement(children) ? React25__namespace.default.cloneElement(children, {
9080
+ const control = React37__namespace.default.isValidElement(children) ? React37__namespace.default.cloneElement(children, {
8209
9081
  "aria-describedby": [children.props["aria-describedby"], hasMsg ? descId : null].filter(Boolean).join(" ") || void 0,
8210
9082
  "aria-invalid": children.props["aria-invalid"] !== void 0 ? children.props["aria-invalid"] : error ? true : void 0
8211
9083
  }) : children;
@@ -8297,11 +9169,11 @@ function FileUpload({
8297
9169
  ...rest
8298
9170
  }) {
8299
9171
  const __twcStyles = useScopedStyles("twc-upload-styles", UPLOAD_CSS);
8300
- const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
9172
+ const [internal, setInternal] = React37__namespace.default.useState(defaultValue);
8301
9173
  const files = value !== void 0 ? value : internal;
8302
- const [drag, setDrag] = React25__namespace.default.useState(false);
8303
- const inputRef = React25__namespace.default.useRef(null);
8304
- const autoId = React25__namespace.default.useId();
9174
+ const [drag, setDrag] = React37__namespace.default.useState(false);
9175
+ const inputRef = React37__namespace.default.useRef(null);
9176
+ const autoId = React37__namespace.default.useId();
8305
9177
  const fieldId = id || autoId;
8306
9178
  const descId = `${fieldId}-desc`;
8307
9179
  const invalid = Boolean(error);
@@ -8524,15 +9396,15 @@ function Kanban({
8524
9396
  ...rest
8525
9397
  }) {
8526
9398
  const __twcStyles = useScopedStyles("twc-kanban-styles", KANBAN_CSS);
8527
- const [internal, setInternal] = React25__namespace.default.useState(cards ?? defaultCards ?? []);
9399
+ const [internal, setInternal] = React37__namespace.default.useState(cards ?? defaultCards ?? []);
8528
9400
  const items = cards !== void 0 ? cards : internal;
8529
- const [drag, setDrag] = React25__namespace.default.useState(null);
8530
- const [overCol, setOverCol] = React25__namespace.default.useState(null);
8531
- const [grab, setGrab] = React25__namespace.default.useState(null);
8532
- const [announce, setAnnounce] = React25__namespace.default.useState("");
8533
- const rootRef = React25__namespace.default.useRef(null);
8534
- const focusIdRef = React25__namespace.default.useRef(null);
8535
- React25__namespace.default.useEffect(() => {
9401
+ const [drag, setDrag] = React37__namespace.default.useState(null);
9402
+ const [overCol, setOverCol] = React37__namespace.default.useState(null);
9403
+ const [grab, setGrab] = React37__namespace.default.useState(null);
9404
+ const [announce, setAnnounce] = React37__namespace.default.useState("");
9405
+ const rootRef = React37__namespace.default.useRef(null);
9406
+ const focusIdRef = React37__namespace.default.useRef(null);
9407
+ React37__namespace.default.useEffect(() => {
8536
9408
  if (focusIdRef.current == null) return void 0;
8537
9409
  const raf = requestAnimationFrame(() => {
8538
9410
  const id = focusIdRef.current;
@@ -8681,7 +9553,7 @@ var LIST_CSS = `
8681
9553
  `;
8682
9554
  function List({ items, plain = false, emptyMessage, className = "", ...rest }) {
8683
9555
  const __twcStyles = useScopedStyles("twc-list-styles", LIST_CSS);
8684
- const safeHref12 = (url) => {
9556
+ const safeHref13 = (url) => {
8685
9557
  if (url == null) return void 0;
8686
9558
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
8687
9559
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -8693,7 +9565,7 @@ function List({ items, plain = false, emptyMessage, className = "", ...rest }) {
8693
9565
  /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: `twc-list ${className}`, role: "list", "data-plain": plain || void 0, ...rest, children: [
8694
9566
  __twcStyles,
8695
9567
  items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("li", { role: "presentation", style: { display: "contents" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-list__empty", children: emptyMessage ?? "Nothing here yet" }) }) : items.map((it, i) => {
8696
- const href = safeHref12(it.href);
9568
+ const href = safeHref13(it.href);
8697
9569
  const interactive = Boolean(it.onClick || href);
8698
9570
  const Tag2 = href ? "a" : interactive ? "button" : "div";
8699
9571
  const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -8749,7 +9621,7 @@ button.twc-navbar__brand, a.twc-navbar__brand { cursor: pointer; }
8749
9621
  .twc-navbar__menu-btn { display: inline-grid; }
8750
9622
  }
8751
9623
  `;
8752
- function safeHref4(url) {
9624
+ function safeHref5(url) {
8753
9625
  if (url == null) return void 0;
8754
9626
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
8755
9627
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -8772,9 +9644,9 @@ function Navbar({
8772
9644
  return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: `twc-navbar ${className}`, "data-sticky": sticky || void 0, ...rest, children: [
8773
9645
  __twcStyles,
8774
9646
  onMenuClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-navbar__menu-btn", "aria-expanded": menuOpen, "aria-controls": menuControls, "aria-label": menuOpen ? "Close menu" : "Open menu", onClick: onMenuClick, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 6h16M4 12h16M4 18h16" }) }) }) : null,
8775
- brand ? brandHref ? /* @__PURE__ */ jsxRuntime.jsx("a", { className: "twc-navbar__brand", href: safeHref4(brandHref), children: brand }) : onBrandClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-navbar__brand", onClick: onBrandClick, children: brand }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-navbar__brand", children: brand }) : null,
9647
+ brand ? brandHref ? /* @__PURE__ */ jsxRuntime.jsx("a", { className: "twc-navbar__brand", href: safeHref5(brandHref), children: brand }) : onBrandClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-navbar__brand", onClick: onBrandClick, children: brand }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-navbar__brand", children: brand }) : null,
8776
9648
  /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "twc-navbar__links", "aria-label": navLabel, children: links.map((l, i) => {
8777
- const href = safeHref4(l.href);
9649
+ const href = safeHref5(l.href);
8778
9650
  const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8779
9651
  l.icon,
8780
9652
  l.label
@@ -8842,21 +9714,21 @@ function Popover({
8842
9714
  ...rest
8843
9715
  }) {
8844
9716
  const __twcStyles = useScopedStyles("twc-popover-styles", POPOVER_CSS);
8845
- const [openState, setOpenState] = React25__namespace.default.useState(defaultOpen);
8846
- const [render, setRender] = React25__namespace.default.useState(false);
8847
- const [pos, setPos] = React25__namespace.default.useState(null);
8848
- const wrapRef = React25__namespace.default.useRef(null);
8849
- const popRef = React25__namespace.default.useRef(null);
8850
- const popId = React25__namespace.default.useId();
9717
+ const [openState, setOpenState] = React37__namespace.default.useState(defaultOpen);
9718
+ const [render, setRender] = React37__namespace.default.useState(false);
9719
+ const [pos, setPos] = React37__namespace.default.useState(null);
9720
+ const wrapRef = React37__namespace.default.useRef(null);
9721
+ const popRef = React37__namespace.default.useRef(null);
9722
+ const popId = React37__namespace.default.useId();
8851
9723
  const controlled = openProp !== void 0;
8852
9724
  const open = controlled ? !!openProp : openState;
8853
- const openRef = React25__namespace.default.useRef(open);
9725
+ const openRef = React37__namespace.default.useRef(open);
8854
9726
  openRef.current = open;
8855
- const controlledRef = React25__namespace.default.useRef(controlled);
9727
+ const controlledRef = React37__namespace.default.useRef(controlled);
8856
9728
  controlledRef.current = controlled;
8857
- const onOpenChangeRef = React25__namespace.default.useRef(onOpenChange);
9729
+ const onOpenChangeRef = React37__namespace.default.useRef(onOpenChange);
8858
9730
  onOpenChangeRef.current = onOpenChange;
8859
- const setOpen = React25__namespace.default.useCallback((next) => {
9731
+ const setOpen = React37__namespace.default.useCallback((next) => {
8860
9732
  const value = typeof next === "function" ? next(openRef.current) : next;
8861
9733
  if (value === openRef.current) return;
8862
9734
  if (!controlledRef.current) setOpenState(value);
@@ -8864,7 +9736,7 @@ function Popover({
8864
9736
  }, []);
8865
9737
  const toggle = () => setOpen((o) => !o);
8866
9738
  const RD = { createPortal: typeof reactDom.createPortal === "function" ? reactDom.createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
8867
- const place = React25__namespace.default.useCallback(() => {
9739
+ const place = React37__namespace.default.useCallback(() => {
8868
9740
  const t = wrapRef.current;
8869
9741
  if (!t) return;
8870
9742
  const r = t.getBoundingClientRect();
@@ -8901,7 +9773,7 @@ function Popover({
8901
9773
  arrow = { top: Math.min(Math.max(cy - top - 5.5, 8), ph - 18), [onRight ? "left" : "right"]: -6 };
8902
9774
  setPos({ top, left, width: w, flip: false, arrow });
8903
9775
  }, [placement, align, width]);
8904
- React25__namespace.default.useEffect(() => {
9776
+ React37__namespace.default.useEffect(() => {
8905
9777
  if (!open) return;
8906
9778
  place();
8907
9779
  const onMove = () => place();
@@ -8924,7 +9796,7 @@ function Popover({
8924
9796
  document.removeEventListener("keydown", onKey);
8925
9797
  };
8926
9798
  }, [open, place]);
8927
- React25__namespace.default.useEffect(() => {
9799
+ React37__namespace.default.useEffect(() => {
8928
9800
  if (open) {
8929
9801
  setRender(true);
8930
9802
  return;
@@ -8932,12 +9804,12 @@ function Popover({
8932
9804
  const t = setTimeout(() => setRender(false), 170);
8933
9805
  return () => clearTimeout(t);
8934
9806
  }, [open]);
8935
- React25__namespace.default.useEffect(() => {
9807
+ React37__namespace.default.useEffect(() => {
8936
9808
  if (render && open) place();
8937
9809
  }, [render, place]);
8938
- const restoreRef = React25__namespace.default.useRef(null);
8939
- const needFocusRef = React25__namespace.default.useRef(false);
8940
- React25__namespace.default.useEffect(() => {
9810
+ const restoreRef = React37__namespace.default.useRef(null);
9811
+ const needFocusRef = React37__namespace.default.useRef(false);
9812
+ React37__namespace.default.useEffect(() => {
8941
9813
  if (open) {
8942
9814
  restoreRef.current = document.activeElement;
8943
9815
  needFocusRef.current = true;
@@ -8972,7 +9844,7 @@ function Popover({
8972
9844
  ]
8973
9845
  }
8974
9846
  ) : null;
8975
- const triggerEl = React25__namespace.default.isValidElement(trigger) ? React25__namespace.default.cloneElement(trigger, {
9847
+ const triggerEl = React37__namespace.default.isValidElement(trigger) ? React37__namespace.default.cloneElement(trigger, {
8976
9848
  onClick: (e) => {
8977
9849
  trigger.props.onClick?.(e);
8978
9850
  toggle();
@@ -9015,7 +9887,7 @@ function Progress({
9015
9887
  className = "",
9016
9888
  ...rest
9017
9889
  }) {
9018
- const labelId = React25__namespace.default.useId();
9890
+ const labelId = React37__namespace.default.useId();
9019
9891
  const { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, ...restProps } = rest;
9020
9892
  const __twcStyles = useScopedStyles("twc-progress-styles", `
9021
9893
  .twc-progress-wrap { display: flex; flex-direction: column; gap: 6px; font-family: var(--font-sans); }
@@ -9138,7 +10010,7 @@ function Radio({
9138
10010
  .twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
9139
10011
  .twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
9140
10012
  `);
9141
- const autoId = React25__namespace.default.useId();
10013
+ const autoId = React37__namespace.default.useId();
9142
10014
  const fieldId = id || autoId;
9143
10015
  const errId = `${fieldId}-error`;
9144
10016
  const invalid = Boolean(error);
@@ -9208,13 +10080,13 @@ function RadioGroup({
9208
10080
  ...rest
9209
10081
  }) {
9210
10082
  const __twcStyles = useScopedStyles("twc-radio-group-styles", RADIO_GROUP_CSS);
9211
- const autoId = React25__namespace.default.useId();
10083
+ const autoId = React37__namespace.default.useId();
9212
10084
  const fieldId = id || autoId;
9213
10085
  const labelId = `${fieldId}-label`;
9214
10086
  const descId = `${fieldId}-desc`;
9215
10087
  const groupName = name || `${fieldId}-name`;
9216
10088
  const invalid = Boolean(error);
9217
- const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
10089
+ const [internal, setInternal] = React37__namespace.default.useState(defaultValue);
9218
10090
  const current = value !== void 0 ? value : internal;
9219
10091
  const select = (v) => {
9220
10092
  if (value === void 0) setInternal(v);
@@ -9235,10 +10107,10 @@ function RadioGroup({
9235
10107
  tone
9236
10108
  },
9237
10109
  o.value
9238
- )) : React25__namespace.default.Children.map(children, (child) => {
9239
- if (!React25__namespace.default.isValidElement(child)) return child;
10110
+ )) : React37__namespace.default.Children.map(children, (child) => {
10111
+ if (!React37__namespace.default.isValidElement(child)) return child;
9240
10112
  const v = child.props.value;
9241
- return React25__namespace.default.cloneElement(child, {
10113
+ return React37__namespace.default.cloneElement(child, {
9242
10114
  name: child.props.name ?? groupName,
9243
10115
  checked: child.props.checked ?? current === v,
9244
10116
  onChange: child.props.onChange ?? (() => select(v)),
@@ -9318,12 +10190,12 @@ function Rating({
9318
10190
  ...rest
9319
10191
  }) {
9320
10192
  const __twcStyles = useScopedStyles("twc-rating-styles", RATING_CSS);
9321
- const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
9322
- const [hover, setHover] = React25__namespace.default.useState(0);
10193
+ const [internal, setInternal] = React37__namespace.default.useState(defaultValue);
10194
+ const [hover, setHover] = React37__namespace.default.useState(0);
9323
10195
  const val = value !== void 0 ? value : internal;
9324
10196
  const shown = hover || val;
9325
10197
  const interactive = !readOnly && !disabled;
9326
- const btnRefs = React25__namespace.default.useRef([]);
10198
+ const btnRefs = React37__namespace.default.useRef([]);
9327
10199
  const tabStar = Math.min(count, Math.max(1, Math.round(val) || 1));
9328
10200
  const fmt = (v) => format ? format(v) : Number.isInteger(v) ? String(v) : v.toFixed(1);
9329
10201
  if (process.env.NODE_ENV !== "production" && interactive && !Number.isInteger(val)) {
@@ -9510,24 +10382,24 @@ function Sidebar({
9510
10382
  ...rest
9511
10383
  }) {
9512
10384
  const __twcStyles = useScopedStyles("twc-sidebar-styles", SIDEBAR_CSS);
9513
- const navId = React25__namespace.default.useId();
9514
- const panelRef = React25__namespace.default.useRef(null);
10385
+ const navId = React37__namespace.default.useId();
10386
+ const panelRef = React37__namespace.default.useRef(null);
9515
10387
  const renderPortal = usePortal();
9516
- const [internal, setInternal] = React25__namespace.default.useState(defaultCollapsed);
10388
+ const [internal, setInternal] = React37__namespace.default.useState(defaultCollapsed);
9517
10389
  const collapsed = collapsedProp !== void 0 ? collapsedProp : internal;
9518
10390
  const toggle = () => {
9519
10391
  const next = !collapsed;
9520
10392
  if (collapsedProp === void 0) setInternal(next);
9521
10393
  onCollapsedChange?.(next);
9522
10394
  };
9523
- const [openInternal, setOpenInternal] = React25__namespace.default.useState(defaultOpen);
10395
+ const [openInternal, setOpenInternal] = React37__namespace.default.useState(defaultOpen);
9524
10396
  const open = openProp !== void 0 ? openProp : openInternal;
9525
10397
  const setOpen = (next) => {
9526
10398
  if (openProp === void 0) setOpenInternal(next);
9527
10399
  onOpenChange?.(next);
9528
10400
  };
9529
- const [mounted, setMounted] = React25__namespace.default.useState(open);
9530
- React25__namespace.default.useEffect(() => {
10401
+ const [mounted, setMounted] = React37__namespace.default.useState(open);
10402
+ React37__namespace.default.useEffect(() => {
9531
10403
  if (!overlay) return void 0;
9532
10404
  if (open) {
9533
10405
  setMounted(true);
@@ -9536,7 +10408,7 @@ function Sidebar({
9536
10408
  const t = setTimeout(() => setMounted(false), 170);
9537
10409
  return () => clearTimeout(t);
9538
10410
  }, [overlay, open]);
9539
- React25__namespace.default.useEffect(() => {
10411
+ React37__namespace.default.useEffect(() => {
9540
10412
  if (!overlay || !open) return void 0;
9541
10413
  const prev = document.body.style.overflow;
9542
10414
  document.body.style.overflow = "hidden";
@@ -9545,7 +10417,7 @@ function Sidebar({
9545
10417
  };
9546
10418
  }, [overlay, open]);
9547
10419
  useFocusTrap(panelRef, overlay && open && mounted);
9548
- React25__namespace.default.useEffect(() => {
10420
+ React37__namespace.default.useEffect(() => {
9549
10421
  if (!overlay || !open) return void 0;
9550
10422
  const onKey = (e) => {
9551
10423
  if (e.key === "Escape") {
@@ -9557,13 +10429,13 @@ function Sidebar({
9557
10429
  document.addEventListener("keydown", onKey);
9558
10430
  return () => document.removeEventListener("keydown", onKey);
9559
10431
  }, [overlay, open, openProp, onOpenChange]);
9560
- const safeHref12 = (url) => {
10432
+ const safeHref13 = (url) => {
9561
10433
  if (url == null) return void 0;
9562
10434
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
9563
10435
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
9564
10436
  };
9565
10437
  const renderItem = (it, i) => {
9566
- const href = safeHref12(it.href);
10438
+ const href = safeHref13(it.href);
9567
10439
  const labelStr = typeof it.label === "string" ? it.label : void 0;
9568
10440
  const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9569
10441
  it.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__ic", "aria-hidden": "true", children: it.icon }) : labelStr != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__ic twc-sidebar__ic--initial", "aria-hidden": "true", children: labelStr.charAt(0) }) : null,
@@ -9597,7 +10469,7 @@ function Sidebar({
9597
10469
  const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9598
10470
  __twcStyles,
9599
10471
  brand ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-sidebar__head", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__brand", children: brand }) }) : null,
9600
- /* @__PURE__ */ jsxRuntime.jsx("nav", { id: navId, className: "twc-sidebar__nav", "aria-label": navLabel, children: groups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React25__namespace.default.Fragment, { children: [
10472
+ /* @__PURE__ */ jsxRuntime.jsx("nav", { id: navId, className: "twc-sidebar__nav", "aria-label": navLabel, children: groups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React37__namespace.default.Fragment, { children: [
9601
10473
  g.section != null ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-sidebar__section", id: g.sid, children: g.section }) : null,
9602
10474
  /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "twc-sidebar__list", ...g.section != null ? { "aria-labelledby": g.sid } : {}, children: g.entries.map(({ it, i }) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: renderItem(it) }, i)) })
9603
10475
  ] }, gi)) }),
@@ -9766,10 +10638,10 @@ function Slider({
9766
10638
  return Math.min(max, Math.max(min, Math.round(stepped * 1e6) / 1e6));
9767
10639
  };
9768
10640
  const __twcStyles = useScopedStyles("twc-slider-styles", SLIDER_CSS);
9769
- const autoId = React25__namespace.default.useId();
10641
+ const autoId = React37__namespace.default.useId();
9770
10642
  const fieldId = id || autoId;
9771
10643
  const isRange = range || Array.isArray(value) || Array.isArray(defaultValue);
9772
- const [internal, setInternal] = React25__namespace.default.useState(() => {
10644
+ const [internal, setInternal] = React37__namespace.default.useState(() => {
9773
10645
  if (isRange) {
9774
10646
  const dv = Array.isArray(defaultValue) ? defaultValue : [min, max];
9775
10647
  return [clampSnap(dv[0]), clampSnap(dv[1])];
@@ -9779,8 +10651,8 @@ function Slider({
9779
10651
  const rawVal = value !== void 0 ? value : internal;
9780
10652
  const clampedVals = (isRange ? [Number(rawVal[0]), Number(rawVal[1])] : [Number(rawVal)]).map((v) => Math.min(max, Math.max(min, Number.isFinite(v) ? v : min)));
9781
10653
  const indices = isRange ? [0, 1] : [0];
9782
- const trackRef = React25__namespace.default.useRef(null);
9783
- const [dragging, setDragging] = React25__namespace.default.useState(false);
10654
+ const trackRef = React37__namespace.default.useRef(null);
10655
+ const [dragging, setDragging] = React37__namespace.default.useState(false);
9784
10656
  const fmt = (v) => formatValue ? formatValue(v) : v.toFixed(decimals);
9785
10657
  const valueTextFor = (v) => {
9786
10658
  if (getAriaValueText) return getAriaValueText(v);
@@ -9811,8 +10683,8 @@ function Slider({
9811
10683
  const ratio = Math.min(1, Math.max(0, (clientX - r.left) / r.width));
9812
10684
  return clampSnap(min + ratio * (max - min));
9813
10685
  };
9814
- const dragCleanupRef = React25__namespace.default.useRef(null);
9815
- React25__namespace.default.useEffect(() => () => dragCleanupRef.current?.(), []);
10686
+ const dragCleanupRef = React37__namespace.default.useRef(null);
10687
+ React37__namespace.default.useEffect(() => () => dragCleanupRef.current?.(), []);
9816
10688
  function onPointerDown(e) {
9817
10689
  if (disabled) return;
9818
10690
  e.preventDefault();
@@ -10043,7 +10915,7 @@ function Stepper({
10043
10915
  ...rest
10044
10916
  }) {
10045
10917
  const __twcStyles = useScopedStyles("twc-stepper-styles", STEPPER_CSS);
10046
- const [activeInternal, setActiveInternal] = React25__namespace.default.useState(defaultActive);
10918
+ const [activeInternal, setActiveInternal] = React37__namespace.default.useState(defaultActive);
10047
10919
  const active = activeProp !== void 0 ? activeProp : activeInternal;
10048
10920
  const handleStep = (i) => {
10049
10921
  if (activeProp === void 0) setActiveInternal(i);
@@ -10175,7 +11047,7 @@ function Switch({
10175
11047
  .twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
10176
11048
  .twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
10177
11049
  `);
10178
- const autoId = React25__namespace.default.useId();
11050
+ const autoId = React37__namespace.default.useId();
10179
11051
  const fieldId = id || autoId;
10180
11052
  const errId = `${fieldId}-error`;
10181
11053
  const invalid = Boolean(error);
@@ -10278,14 +11150,14 @@ function Table({
10278
11150
  ...rest
10279
11151
  }) {
10280
11152
  const __twcStyles = useScopedStyles("twc-table-styles", TABLE_CSS);
10281
- const cols = React25__namespace.default.useMemo(
11153
+ const cols = React37__namespace.default.useMemo(
10282
11154
  () => (columns || []).map((c) => ({ ...c, header: c.headerName, render: c.renderCell })),
10283
11155
  [columns]
10284
11156
  );
10285
11157
  const dataRows = rowsProp || [];
10286
- const [internalSort, setInternalSort] = React25__namespace.default.useState(defaultSort || { field: null, dir: "asc" });
11158
+ const [internalSort, setInternalSort] = React37__namespace.default.useState(defaultSort || { field: null, dir: "asc" });
10287
11159
  const sort = (sortProp !== void 0 ? sortProp : internalSort) || { field: null, dir: "asc" };
10288
- const rows = React25__namespace.default.useMemo(() => {
11160
+ const rows = React37__namespace.default.useMemo(() => {
10289
11161
  if (!sortable || !sort.field) return dataRows;
10290
11162
  const col = cols.find((c) => c.field === sort.field);
10291
11163
  if (!col) return dataRows;
@@ -10432,15 +11304,15 @@ function Tabs({
10432
11304
  }) {
10433
11305
  const vertical = orientation === "vertical";
10434
11306
  const __twcStyles = useScopedStyles("twc-tabs-styles", TABS_CSS);
10435
- const [internal, setInternal] = React25__namespace.default.useState(defaultValue ?? items[0]?.value);
11307
+ const [internal, setInternal] = React37__namespace.default.useState(defaultValue ?? items[0]?.value);
10436
11308
  const active = value ?? internal;
10437
- const listRef = React25__namespace.default.useRef(null);
10438
- const [ind, setInd] = React25__namespace.default.useState({ left: 0, width: 0, top: 0, height: 0 });
10439
- const baseId = React25__namespace.default.useId();
11309
+ const listRef = React37__namespace.default.useRef(null);
11310
+ const [ind, setInd] = React37__namespace.default.useState({ left: 0, width: 0, top: 0, height: 0 });
11311
+ const baseId = React37__namespace.default.useId();
10440
11312
  const tabIdAt = (i) => `${baseId}-tab-${i}`;
10441
11313
  const panelId = `${baseId}-panel`;
10442
11314
  const activeIndex = items.findIndex((it) => it.value === active);
10443
- const updateIndicator = React25__namespace.default.useCallback(() => {
11315
+ const updateIndicator = React37__namespace.default.useCallback(() => {
10444
11316
  const list = listRef.current;
10445
11317
  if (!list) return;
10446
11318
  const el = list.querySelector('[data-active="true"]');
@@ -10449,10 +11321,10 @@ function Tabs({
10449
11321
  if (!vertical) el.scrollIntoView?.({ inline: "nearest", block: "nearest" });
10450
11322
  }
10451
11323
  }, [vertical]);
10452
- React25__namespace.default.useEffect(() => {
11324
+ React37__namespace.default.useEffect(() => {
10453
11325
  updateIndicator();
10454
11326
  }, [active, updateIndicator, items, orientation]);
10455
- React25__namespace.default.useEffect(() => {
11327
+ React37__namespace.default.useEffect(() => {
10456
11328
  const r = () => updateIndicator();
10457
11329
  window.addEventListener("resize", r);
10458
11330
  if (typeof document !== "undefined" && document.fonts && document.fonts.ready) {
@@ -10597,7 +11469,7 @@ function Tag({
10597
11469
  }, "aria-label": _removeLabel, type: "button", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
10598
11470
  ] });
10599
11471
  }
10600
- var useIso = typeof document !== "undefined" ? React25__namespace.default.useLayoutEffect : React25__namespace.default.useEffect;
11472
+ var useIso = typeof document !== "undefined" ? React37__namespace.default.useLayoutEffect : React37__namespace.default.useEffect;
10601
11473
  var TEXTAREA_CSS = `
10602
11474
  .twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
10603
11475
  .twc-field__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); display: flex; gap: 4px; align-items: center; }
@@ -10633,7 +11505,7 @@ var TEXTAREA_CSS = `
10633
11505
  .twc-field__count { margin-inline-start: auto; font-size: var(--text-xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; flex: none; }
10634
11506
  .twc-field__count[data-danger="true"] { color: var(--color-danger-subtle-fg); }
10635
11507
  `;
10636
- var Textarea = React25__namespace.default.forwardRef(function Textarea2({
11508
+ var Textarea = React37__namespace.default.forwardRef(function Textarea2({
10637
11509
  label,
10638
11510
  hint,
10639
11511
  error,
@@ -10651,19 +11523,19 @@ var Textarea = React25__namespace.default.forwardRef(function Textarea2({
10651
11523
  ...rest
10652
11524
  }, ref) {
10653
11525
  const __twcStyles = useScopedStyles("twc-textarea-styles", TEXTAREA_CSS);
10654
- const autoId = React25__namespace.default.useId();
11526
+ const autoId = React37__namespace.default.useId();
10655
11527
  const fieldId = id || autoId;
10656
11528
  const descId = `${fieldId}-desc`;
10657
11529
  const countId = `${fieldId}-count`;
10658
11530
  const invalid = Boolean(error);
10659
- const innerRef = React25__namespace.default.useRef(null);
11531
+ const innerRef = React37__namespace.default.useRef(null);
10660
11532
  const setRef = (el) => {
10661
11533
  innerRef.current = el;
10662
11534
  if (typeof ref === "function") ref(el);
10663
11535
  else if (ref) ref.current = el;
10664
11536
  };
10665
11537
  const countControlled = rest.value !== void 0;
10666
- const [len2, setLen] = React25__namespace.default.useState(() => String(rest.defaultValue ?? "").length);
11538
+ const [len2, setLen] = React37__namespace.default.useState(() => String(rest.defaultValue ?? "").length);
10667
11539
  const count = countControlled ? String(rest.value ?? "").length : len2;
10668
11540
  const max = rest.maxLength;
10669
11541
  const showCounter = showCount && max != null;
@@ -10841,19 +11713,19 @@ function Toast({
10841
11713
  }) {
10842
11714
  const resolvedTone = tone === "neutral" ? "default" : tone;
10843
11715
  const __twcStyles = useScopedStyles("twc-toast-styles", TOAST_CSS);
10844
- const onCloseRef = React25__namespace.default.useRef(onClose);
10845
- React25__namespace.default.useEffect(() => {
11716
+ const onCloseRef = React37__namespace.default.useRef(onClose);
11717
+ React37__namespace.default.useEffect(() => {
10846
11718
  onCloseRef.current = onClose;
10847
11719
  }, [onClose]);
10848
- const timer = React25__namespace.default.useRef();
10849
- const stop = React25__namespace.default.useCallback(() => clearTimeout(timer.current), []);
10850
- const start = React25__namespace.default.useCallback(() => {
11720
+ const timer = React37__namespace.default.useRef();
11721
+ const stop = React37__namespace.default.useCallback(() => clearTimeout(timer.current), []);
11722
+ const start = React37__namespace.default.useCallback(() => {
10851
11723
  stop();
10852
11724
  if (duration && duration !== Infinity && onCloseRef.current) {
10853
11725
  timer.current = setTimeout(() => onCloseRef.current && onCloseRef.current(), duration);
10854
11726
  }
10855
11727
  }, [duration, stop]);
10856
- React25__namespace.default.useEffect(() => {
11728
+ React37__namespace.default.useEffect(() => {
10857
11729
  start();
10858
11730
  return stop;
10859
11731
  }, [start, stop]);
@@ -10898,30 +11770,30 @@ function Toast({
10898
11770
  }
10899
11771
  function ToastViewport({ children, limit, className = "", ...rest }) {
10900
11772
  const __twcStyles = useScopedStyles("twc-toast-styles", TOAST_CSS);
10901
- const shown = limit && limit > 0 ? React25__namespace.default.Children.toArray(children).slice(-limit) : children;
11773
+ const shown = limit && limit > 0 ? React37__namespace.default.Children.toArray(children).slice(-limit) : children;
10902
11774
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-toast-viewport ${className}`, role: "region", "aria-label": "Notifications", ...rest, children: [
10903
11775
  __twcStyles,
10904
11776
  shown
10905
11777
  ] });
10906
11778
  }
10907
- var ToastContext = React25__namespace.default.createContext(null);
11779
+ var ToastContext = React37__namespace.default.createContext(null);
10908
11780
  function useToast() {
10909
- const ctx = React25__namespace.default.useContext(ToastContext);
11781
+ const ctx = React37__namespace.default.useContext(ToastContext);
10910
11782
  if (!ctx) throw new Error("useToast must be used within a <ToastProvider>.");
10911
11783
  return ctx;
10912
11784
  }
10913
11785
  function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps }) {
10914
- const [toasts, setToasts] = React25__namespace.default.useState([]);
10915
- const idRef = React25__namespace.default.useRef(0);
10916
- const limitRef = React25__namespace.default.useRef(limit);
10917
- React25__namespace.default.useEffect(() => {
11786
+ const [toasts, setToasts] = React37__namespace.default.useState([]);
11787
+ const idRef = React37__namespace.default.useRef(0);
11788
+ const limitRef = React37__namespace.default.useRef(limit);
11789
+ React37__namespace.default.useEffect(() => {
10918
11790
  limitRef.current = limit;
10919
11791
  }, [limit]);
10920
- const dismiss = React25__namespace.default.useCallback((id) => {
11792
+ const dismiss = React37__namespace.default.useCallback((id) => {
10921
11793
  setToasts((s) => s.filter((t) => t.id !== id));
10922
11794
  }, []);
10923
- const clear = React25__namespace.default.useCallback(() => setToasts([]), []);
10924
- const api = React25__namespace.default.useMemo(() => {
11795
+ const clear = React37__namespace.default.useCallback(() => setToasts([]), []);
11796
+ const api = React37__namespace.default.useMemo(() => {
10925
11797
  const push = (opts) => {
10926
11798
  const id = idRef.current += 1;
10927
11799
  const next = typeof opts === "string" ? { title: opts } : opts && typeof opts === "object" ? opts : {};
@@ -10942,7 +11814,7 @@ function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps
10942
11814
  toast.show = withTone("default");
10943
11815
  return { toast, dismiss, clear };
10944
11816
  }, [dismiss, clear]);
10945
- const value = React25__namespace.default.useMemo(() => ({ ...api, toasts }), [api, toasts]);
11817
+ const value = React37__namespace.default.useMemo(() => ({ ...api, toasts }), [api, toasts]);
10946
11818
  return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value, children: [
10947
11819
  children,
10948
11820
  /* @__PURE__ */ jsxRuntime.jsx(ToastViewport, { limit, ...viewportProps, children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -11050,13 +11922,13 @@ function TreeView({
11050
11922
  }) {
11051
11923
  const nodes = items;
11052
11924
  const __twcStyles = useScopedStyles("twc-tree-styles", TREE_CSS);
11053
- const [expInternal, setExpInternal] = React25__namespace.default.useState(() => new Set(defaultExpanded));
11925
+ const [expInternal, setExpInternal] = React37__namespace.default.useState(() => new Set(defaultExpanded));
11054
11926
  const expanded = expandedProp !== void 0 ? new Set(expandedProp) : expInternal;
11055
- const [selInternal, setSelInternal] = React25__namespace.default.useState(defaultSelectedId);
11927
+ const [selInternal, setSelInternal] = React37__namespace.default.useState(defaultSelectedId);
11056
11928
  const selectedId = selectedProp !== void 0 ? selectedProp : selInternal;
11057
- const [focusId, setFocusId] = React25__namespace.default.useState(null);
11058
- const rowRefs = React25__namespace.default.useRef(/* @__PURE__ */ new Map());
11059
- const taRef = React25__namespace.default.useRef({ str: "", t: 0 });
11929
+ const [focusId, setFocusId] = React37__namespace.default.useState(null);
11930
+ const rowRefs = React37__namespace.default.useRef(/* @__PURE__ */ new Map());
11931
+ const taRef = React37__namespace.default.useRef({ str: "", t: 0 });
11060
11932
  const toggle = (id) => {
11061
11933
  const n = new Set(expanded);
11062
11934
  n.has(id) ? n.delete(id) : n.add(id);
@@ -11188,7 +12060,7 @@ function AppShell({
11188
12060
  ...rest
11189
12061
  }) {
11190
12062
  const __twcStyles = useScopedStyles("twc-shell-styles", SHELL_CSS);
11191
- const wiredSidebar = React25__namespace.default.isValidElement(sidebar) && (sidebarOpen !== void 0 || onSidebarOpenChange !== void 0) ? React25__namespace.default.cloneElement(sidebar, {
12063
+ const wiredSidebar = React37__namespace.default.isValidElement(sidebar) && (sidebarOpen !== void 0 || onSidebarOpenChange !== void 0) ? React37__namespace.default.cloneElement(sidebar, {
11192
12064
  overlay: sidebar.props.overlay !== void 0 ? sidebar.props.overlay : true,
11193
12065
  open: sidebar.props.open !== void 0 ? sidebar.props.open : sidebarOpen,
11194
12066
  onOpenChange: sidebar.props.onOpenChange !== void 0 ? sidebar.props.onOpenChange : onSidebarOpenChange
@@ -11218,12 +12090,12 @@ function bgValue(bg) {
11218
12090
  if (BG[bg]) return `var(${BG[bg]})`;
11219
12091
  return String(bg).startsWith("--") ? `var(${bg})` : bg;
11220
12092
  }
11221
- function safeHref5(url) {
12093
+ function safeHref6(url) {
11222
12094
  if (url == null) return void 0;
11223
12095
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
11224
12096
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
11225
12097
  }
11226
- function Box({
12098
+ var Box = React37__namespace.default.forwardRef(function Box2({
11227
12099
  as: Tag2 = "div",
11228
12100
  p,
11229
12101
  px,
@@ -11243,11 +12115,13 @@ function Box({
11243
12115
  border = false,
11244
12116
  radius,
11245
12117
  shadow,
12118
+ sx,
11246
12119
  className = "",
11247
12120
  style,
11248
12121
  children,
11249
12122
  ...rest
11250
- }) {
12123
+ }, ref) {
12124
+ const { flatStyle, styleNode, sxAttr } = useSx(sx);
11251
12125
  const s = {
11252
12126
  paddingTop: sp(pt ?? py ?? p),
11253
12127
  paddingRight: sp(pr ?? px ?? p),
@@ -11261,44 +12135,58 @@ function Box({
11261
12135
  border: border ? "var(--border-thin, 1px) solid var(--color-border)" : void 0,
11262
12136
  borderRadius: radius ? `var(--radius-${radius})` : void 0,
11263
12137
  boxShadow: shadow ? `var(--shadow-${shadow})` : void 0,
11264
- ...style
12138
+ ...style,
12139
+ ...flatStyle
11265
12140
  };
11266
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref5(rest.href);
11267
- return /* @__PURE__ */ jsxRuntime.jsx(Tag2, { className: `twc-box ${className}`.trim(), style: s, ...rest, children });
11268
- }
12141
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref6(rest.href);
12142
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tag2, { ref, className: `twc-box ${className}`.trim(), style: s, "data-twc-sx": sxAttr, ...rest, children: [
12143
+ styleNode,
12144
+ children
12145
+ ] });
12146
+ });
12147
+ Box.displayName = "Box";
11269
12148
  var SIZES = { sm: 640, md: 768, lg: 1024, xl: 1280, full: "100%" };
11270
- function safeHref6(url) {
12149
+ function safeHref7(url) {
11271
12150
  if (url == null) return void 0;
11272
12151
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
11273
12152
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
11274
12153
  }
11275
- function Container({
12154
+ var Container = React37__namespace.default.forwardRef(function Container2({
11276
12155
  as: Tag2 = "div",
11277
12156
  size = "lg",
11278
12157
  padded = true,
12158
+ sx,
11279
12159
  className = "",
11280
12160
  style,
11281
12161
  children,
11282
12162
  ...rest
11283
- }) {
12163
+ }, ref) {
12164
+ const { flatStyle, styleNode, sxAttr } = useSx(sx);
11284
12165
  const max = SIZES[size] ?? size;
11285
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref6(rest.href);
11286
- return /* @__PURE__ */ jsxRuntime.jsx(
12166
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref7(rest.href);
12167
+ return /* @__PURE__ */ jsxRuntime.jsxs(
11287
12168
  Tag2,
11288
12169
  {
12170
+ ref,
11289
12171
  className: `twc-container ${className}`.trim(),
12172
+ "data-twc-sx": sxAttr,
11290
12173
  style: {
11291
12174
  width: "100%",
11292
12175
  maxWidth: typeof max === "number" ? `${max}px` : max,
11293
12176
  marginInline: "auto",
11294
12177
  paddingInline: padded ? "var(--space-5)" : void 0,
11295
- ...style
12178
+ ...style,
12179
+ ...flatStyle
11296
12180
  },
11297
12181
  ...rest,
11298
- children
12182
+ children: [
12183
+ styleNode,
12184
+ children
12185
+ ]
11299
12186
  }
11300
12187
  );
11301
- }
12188
+ });
12189
+ Container.displayName = "Container";
11302
12190
  function space(v) {
11303
12191
  if (v == null) return void 0;
11304
12192
  if (typeof v === "number") return `var(--space-${String(v).replace(".", "-")})`;
@@ -11308,12 +12196,12 @@ function len(v) {
11308
12196
  return typeof v === "number" ? `${v}px` : v;
11309
12197
  }
11310
12198
  var BP = { sm: 640, md: 768, lg: 1024, xl: 1280 };
11311
- function safeHref7(url) {
12199
+ function safeHref8(url) {
11312
12200
  if (url == null) return void 0;
11313
12201
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
11314
12202
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
11315
12203
  }
11316
- function Grid({
12204
+ var Grid = React37__namespace.default.forwardRef(function Grid2({
11317
12205
  as: Tag2 = "div",
11318
12206
  columns,
11319
12207
  minChildWidth,
@@ -11324,13 +12212,15 @@ function Grid({
11324
12212
  justify,
11325
12213
  alignContent,
11326
12214
  justifyContent,
12215
+ sx,
11327
12216
  className = "",
11328
12217
  style,
11329
12218
  children,
11330
12219
  ...rest
11331
- }) {
12220
+ }, ref) {
12221
+ const { flatStyle, styleNode, sxAttr } = useSx(sx);
11332
12222
  const responsive = columns != null && typeof columns === "object";
11333
- const uid = React25__namespace.default.useId();
12223
+ const uid = React37__namespace.default.useId();
11334
12224
  const gridId = responsive ? `g${uid.replace(/[^a-zA-Z0-9]/g, "")}` : null;
11335
12225
  let css = "";
11336
12226
  if (responsive) {
@@ -11344,12 +12234,14 @@ function Grid({
11344
12234
  }
11345
12235
  const __twcStyles = useScopedStyles(gridId ? `twc-grid-${gridId}` : "twc-grid", css);
11346
12236
  const templateColumns = minChildWidth ? `repeat(auto-fill, minmax(min(${len(minChildWidth)}, 100%), 1fr))` : responsive ? `repeat(var(--twc-grid-cols, ${columns.base ?? 1}), minmax(0, 1fr))` : `repeat(${columns || 1}, minmax(0, 1fr))`;
11347
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref7(rest.href);
12237
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref8(rest.href);
11348
12238
  return /* @__PURE__ */ jsxRuntime.jsxs(
11349
12239
  Tag2,
11350
12240
  {
12241
+ ref,
11351
12242
  className: `twc-grid ${className}`.trim(),
11352
12243
  "data-twc-grid-id": gridId || void 0,
12244
+ "data-twc-sx": sxAttr,
11353
12245
  style: {
11354
12246
  display: "grid",
11355
12247
  gridTemplateColumns: templateColumns,
@@ -11359,27 +12251,30 @@ function Grid({
11359
12251
  justifyItems: justify,
11360
12252
  alignContent,
11361
12253
  justifyContent,
11362
- ...style
12254
+ ...style,
12255
+ ...flatStyle
11363
12256
  },
11364
12257
  ...rest,
11365
12258
  children: [
11366
12259
  responsive ? __twcStyles : null,
12260
+ styleNode,
11367
12261
  children
11368
12262
  ]
11369
12263
  }
11370
12264
  );
11371
- }
12265
+ });
12266
+ Grid.displayName = "Grid";
11372
12267
  function space2(v) {
11373
12268
  if (v == null) return void 0;
11374
12269
  if (typeof v === "number") return `var(--space-${String(v).replace(".", "-")})`;
11375
12270
  return v;
11376
12271
  }
11377
- function safeHref8(url) {
12272
+ function safeHref9(url) {
11378
12273
  if (url == null) return void 0;
11379
12274
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
11380
12275
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
11381
12276
  }
11382
- function Stack({
12277
+ var Stack = React37__namespace.default.forwardRef(function Stack2({
11383
12278
  as: Tag2 = "div",
11384
12279
  direction = "column",
11385
12280
  gap = 4,
@@ -11395,17 +12290,21 @@ function Stack({
11395
12290
  pb,
11396
12291
  pl,
11397
12292
  divider,
12293
+ sx,
11398
12294
  className = "",
11399
12295
  style,
11400
12296
  children,
11401
12297
  ...rest
11402
- }) {
11403
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref8(rest.href);
11404
- const kids = divider != null ? React25__namespace.default.Children.toArray(children).flatMap((child, i, arr) => i < arr.length - 1 ? [child, /* @__PURE__ */ jsxRuntime.jsx(React25__namespace.default.Fragment, { children: divider }, `twc-stack-div-${i}`)] : [child]) : children;
11405
- return /* @__PURE__ */ jsxRuntime.jsx(
12298
+ }, ref) {
12299
+ const { flatStyle, styleNode, sxAttr } = useSx(sx);
12300
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref9(rest.href);
12301
+ const kids = divider != null ? React37__namespace.default.Children.toArray(children).flatMap((child, i, arr) => i < arr.length - 1 ? [child, /* @__PURE__ */ jsxRuntime.jsx(React37__namespace.default.Fragment, { children: divider }, `twc-stack-div-${i}`)] : [child]) : children;
12302
+ return /* @__PURE__ */ jsxRuntime.jsxs(
11406
12303
  Tag2,
11407
12304
  {
12305
+ ref,
11408
12306
  className: `twc-stack ${className}`.trim(),
12307
+ "data-twc-sx": sxAttr,
11409
12308
  style: {
11410
12309
  display: inline ? "inline-flex" : "flex",
11411
12310
  flexDirection: direction,
@@ -11418,13 +12317,18 @@ function Stack({
11418
12317
  paddingBottom: space2(pb ?? py ?? p),
11419
12318
  paddingLeft: space2(pl ?? px ?? p),
11420
12319
  minWidth: 0,
11421
- ...style
12320
+ ...style,
12321
+ ...flatStyle
11422
12322
  },
11423
12323
  ...rest,
11424
- children: kids
12324
+ children: [
12325
+ styleNode,
12326
+ kids
12327
+ ]
11425
12328
  }
11426
12329
  );
11427
- }
12330
+ });
12331
+ Stack.displayName = "Stack";
11428
12332
  var CODE_CSS = `
11429
12333
  .twc-code {
11430
12334
  font-family: var(--font-mono); font-size: 0.875em;
@@ -11448,7 +12352,7 @@ var CODE_CSS = `
11448
12352
  .twc-code__copy:focus-visible { outline: none; box-shadow: var(--ring); }
11449
12353
  .twc-code__copy svg { width: 15px; height: 15px; display: block; }
11450
12354
  `;
11451
- function safeHref9(url) {
12355
+ function safeHref10(url) {
11452
12356
  if (url == null) return void 0;
11453
12357
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
11454
12358
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -11465,11 +12369,11 @@ function Code({
11465
12369
  }) {
11466
12370
  const __twcStyles = useScopedStyles("twc-code-styles", CODE_CSS);
11467
12371
  const Tag2 = as ?? (block ? "pre" : "code");
11468
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref9(rest.href);
11469
- const rootRef = React25__namespace.default.useRef(null);
11470
- const [copied, setCopied] = React25__namespace.default.useState(false);
11471
- const timerRef = React25__namespace.default.useRef(null);
11472
- React25__namespace.default.useEffect(() => () => clearTimeout(timerRef.current), []);
12372
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref10(rest.href);
12373
+ const rootRef = React37__namespace.default.useRef(null);
12374
+ const [copied, setCopied] = React37__namespace.default.useState(false);
12375
+ const timerRef = React37__namespace.default.useRef(null);
12376
+ React37__namespace.default.useEffect(() => () => clearTimeout(timerRef.current), []);
11473
12377
  const doCopy = () => {
11474
12378
  if (typeof navigator === "undefined" || !navigator.clipboard) return;
11475
12379
  const text = typeof children === "string" ? children : rootRef.current?.textContent ?? "";
@@ -11490,12 +12394,12 @@ function Code({
11490
12394
  ] });
11491
12395
  }
11492
12396
  var LEVEL_SIZE = { 1: "4xl", 2: "2xl", 3: "xl", 4: "lg", 5: "base", 6: "sm" };
11493
- function safeHref10(url) {
12397
+ function safeHref11(url) {
11494
12398
  if (url == null) return void 0;
11495
12399
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
11496
12400
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
11497
12401
  }
11498
- function Heading({
12402
+ var Heading = React37__namespace.default.forwardRef(function Heading2({
11499
12403
  as,
11500
12404
  level = 2,
11501
12405
  size,
@@ -11503,18 +12407,22 @@ function Heading({
11503
12407
  align,
11504
12408
  truncate,
11505
12409
  lineClamp,
12410
+ sx,
11506
12411
  className = "",
11507
12412
  style,
11508
12413
  children,
11509
12414
  ...rest
11510
- }) {
12415
+ }, ref) {
12416
+ const { flatStyle, styleNode, sxAttr } = useSx(sx);
11511
12417
  const Tag2 = as || `h${level}`;
11512
12418
  const sz = size || (display ? "display" : LEVEL_SIZE[level]) || "2xl";
11513
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref10(rest.href);
11514
- return /* @__PURE__ */ jsxRuntime.jsx(
12419
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref11(rest.href);
12420
+ return /* @__PURE__ */ jsxRuntime.jsxs(
11515
12421
  Tag2,
11516
12422
  {
12423
+ ref,
11517
12424
  className: `twc-heading ${className}`.trim(),
12425
+ "data-twc-sx": sxAttr,
11518
12426
  style: {
11519
12427
  margin: 0,
11520
12428
  fontFamily: "var(--font-sans)",
@@ -11525,13 +12433,18 @@ function Heading({
11525
12433
  fontSize: `var(--text-${sz})`,
11526
12434
  textAlign: align,
11527
12435
  ...lineClamp != null ? { display: "-webkit-box", WebkitBoxOrient: "vertical", WebkitLineClamp: lineClamp, overflow: "hidden" } : truncate ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 } : null,
11528
- ...style
12436
+ ...style,
12437
+ ...flatStyle
11529
12438
  },
11530
12439
  ...rest,
11531
- children
12440
+ children: [
12441
+ styleNode,
12442
+ children
12443
+ ]
11532
12444
  }
11533
12445
  );
11534
- }
12446
+ });
12447
+ Heading.displayName = "Heading";
11535
12448
  var TONE = {
11536
12449
  default: "--color-text",
11537
12450
  muted: "--color-text-muted",
@@ -11547,12 +12460,12 @@ var TONE = {
11547
12460
  // Adopt the surrounding color (e.g. inside a solid Button/Badge/Alert or a link).
11548
12461
  inherit: "inherit"
11549
12462
  };
11550
- function safeHref11(url) {
12463
+ function safeHref12(url) {
11551
12464
  if (url == null) return void 0;
11552
12465
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
11553
12466
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
11554
12467
  }
11555
- function Text({
12468
+ var Text = React37__namespace.default.forwardRef(function Text2({
11556
12469
  as: Tag2 = "p",
11557
12470
  size = "base",
11558
12471
  tone = "default",
@@ -11560,17 +12473,21 @@ function Text({
11560
12473
  align,
11561
12474
  truncate,
11562
12475
  lineClamp,
12476
+ sx,
11563
12477
  className = "",
11564
12478
  style,
11565
12479
  children,
11566
12480
  ...rest
11567
- }) {
11568
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref11(rest.href);
12481
+ }, ref) {
12482
+ const { flatStyle, styleNode, sxAttr } = useSx(sx);
12483
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref12(rest.href);
11569
12484
  const toneToken = TONE[tone] || TONE.default;
11570
- return /* @__PURE__ */ jsxRuntime.jsx(
12485
+ return /* @__PURE__ */ jsxRuntime.jsxs(
11571
12486
  Tag2,
11572
12487
  {
12488
+ ref,
11573
12489
  className: `twc-text ${className}`.trim(),
12490
+ "data-twc-sx": sxAttr,
11574
12491
  style: {
11575
12492
  margin: 0,
11576
12493
  fontFamily: "var(--font-sans)",
@@ -11580,53 +12497,58 @@ function Text({
11580
12497
  fontWeight: weight ? `var(--font-${weight})` : void 0,
11581
12498
  textAlign: align,
11582
12499
  ...lineClamp != null ? { display: "-webkit-box", WebkitBoxOrient: "vertical", WebkitLineClamp: lineClamp, overflow: "hidden" } : truncate ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 } : null,
11583
- ...style
12500
+ ...style,
12501
+ ...flatStyle
11584
12502
  },
11585
12503
  ...rest,
11586
- children
12504
+ children: [
12505
+ styleNode,
12506
+ children
12507
+ ]
11587
12508
  }
11588
12509
  );
11589
- }
12510
+ });
12511
+ Text.displayName = "Text";
11590
12512
  var canUseDOM2 = typeof window !== "undefined" && typeof document !== "undefined";
11591
- var useIsomorphicLayoutEffect = canUseDOM2 ? React25__namespace.default.useLayoutEffect : React25__namespace.default.useEffect;
12513
+ var useIsomorphicLayoutEffect = canUseDOM2 ? React37__namespace.default.useLayoutEffect : React37__namespace.default.useEffect;
11592
12514
  function useMounted() {
11593
- const [mounted, setMounted] = React25__namespace.default.useState(false);
11594
- React25__namespace.default.useEffect(() => {
12515
+ const [mounted, setMounted] = React37__namespace.default.useState(false);
12516
+ React37__namespace.default.useEffect(() => {
11595
12517
  setMounted(true);
11596
12518
  }, []);
11597
12519
  return mounted;
11598
12520
  }
11599
12521
  function usePrevious(value) {
11600
- const ref = React25__namespace.default.useRef(void 0);
11601
- React25__namespace.default.useEffect(() => {
12522
+ const ref = React37__namespace.default.useRef(void 0);
12523
+ React37__namespace.default.useEffect(() => {
11602
12524
  ref.current = value;
11603
12525
  }, [value]);
11604
12526
  return ref.current;
11605
12527
  }
11606
12528
  function useToggle(initial = false) {
11607
- const [on, setOn] = React25__namespace.default.useState(initial);
11608
- const toggle = React25__namespace.default.useCallback((next) => {
12529
+ const [on, setOn] = React37__namespace.default.useState(initial);
12530
+ const toggle = React37__namespace.default.useCallback((next) => {
11609
12531
  setOn((prev) => typeof next === "boolean" ? next : !prev);
11610
12532
  }, []);
11611
12533
  return [on, toggle, setOn];
11612
12534
  }
11613
12535
  function useDisclosure(initial = false) {
11614
- const [open, setOpen] = React25__namespace.default.useState(initial);
11615
- const onOpen = React25__namespace.default.useCallback(() => setOpen(true), []);
11616
- const onClose = React25__namespace.default.useCallback(() => setOpen(false), []);
11617
- const onToggle = React25__namespace.default.useCallback(() => setOpen((p) => !p), []);
12536
+ const [open, setOpen] = React37__namespace.default.useState(initial);
12537
+ const onOpen = React37__namespace.default.useCallback(() => setOpen(true), []);
12538
+ const onClose = React37__namespace.default.useCallback(() => setOpen(false), []);
12539
+ const onToggle = React37__namespace.default.useCallback(() => setOpen((p) => !p), []);
11618
12540
  return { open, onOpen, onClose, onToggle, setOpen };
11619
12541
  }
11620
12542
  function useControllableState({ value, defaultValue, onChange } = {}) {
11621
12543
  const isControlled = value !== void 0;
11622
- const [uncontrolled, setUncontrolled] = React25__namespace.default.useState(defaultValue);
12544
+ const [uncontrolled, setUncontrolled] = React37__namespace.default.useState(defaultValue);
11623
12545
  const current = isControlled ? value : uncontrolled;
11624
- const ref = React25__namespace.default.useRef({ current, isControlled, onChange });
12546
+ const ref = React37__namespace.default.useRef({ current, isControlled, onChange });
11625
12547
  useIsomorphicLayoutEffect(() => {
11626
12548
  ref.current = { current, isControlled, onChange };
11627
12549
  });
11628
- const wasControlled = React25__namespace.default.useRef(isControlled);
11629
- React25__namespace.default.useEffect(() => {
12550
+ const wasControlled = React37__namespace.default.useRef(isControlled);
12551
+ React37__namespace.default.useEffect(() => {
11630
12552
  if (wasControlled.current !== isControlled) {
11631
12553
  warnOnce(
11632
12554
  "useControllableState:switch",
@@ -11635,7 +12557,7 @@ function useControllableState({ value, defaultValue, onChange } = {}) {
11635
12557
  wasControlled.current = isControlled;
11636
12558
  }
11637
12559
  });
11638
- const setValue = React25__namespace.default.useCallback((next) => {
12560
+ const setValue = React37__namespace.default.useCallback((next) => {
11639
12561
  const { current: cur, isControlled: ctrl, onChange: cb } = ref.current;
11640
12562
  const resolved = typeof next === "function" ? next(cur) : next;
11641
12563
  if (resolved === cur) return;
@@ -11646,7 +12568,7 @@ function useControllableState({ value, defaultValue, onChange } = {}) {
11646
12568
  }
11647
12569
  function useMediaQuery(query, { defaultValue = false, initializeWithValue = false } = {}) {
11648
12570
  const get = () => canUseDOM2 ? window.matchMedia(query).matches : defaultValue;
11649
- const [matches3, setMatches] = React25__namespace.default.useState(initializeWithValue ? get : defaultValue);
12571
+ const [matches3, setMatches] = React37__namespace.default.useState(initializeWithValue ? get : defaultValue);
11650
12572
  useIsomorphicLayoutEffect(() => {
11651
12573
  if (!canUseDOM2) return void 0;
11652
12574
  const mql = window.matchMedia(query);
@@ -11662,7 +12584,7 @@ function usePrefersReducedMotion() {
11662
12584
  }
11663
12585
  function useColorScheme({ storageKey = "twico-theme", attribute = "class", element, disableTransitionsOnChange = true } = {}) {
11664
12586
  const getTarget = () => element || (canUseDOM2 ? document.documentElement : null);
11665
- const firstApply = React25__namespace.default.useRef(true);
12587
+ const firstApply = React37__namespace.default.useRef(true);
11666
12588
  const read = () => {
11667
12589
  if (!canUseDOM2) return "light";
11668
12590
  try {
@@ -11672,8 +12594,8 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
11672
12594
  }
11673
12595
  return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
11674
12596
  };
11675
- const [theme, setThemeState] = React25__namespace.default.useState(read);
11676
- const apply = React25__namespace.default.useCallback(
12597
+ const [theme, setThemeState] = React37__namespace.default.useState(read);
12598
+ const apply = React37__namespace.default.useCallback(
11677
12599
  (t) => {
11678
12600
  const target = getTarget();
11679
12601
  if (!target) return;
@@ -11699,11 +12621,11 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
11699
12621
  useIsomorphicLayoutEffect(() => {
11700
12622
  apply(theme);
11701
12623
  }, [theme, apply]);
11702
- const themeRef = React25__namespace.default.useRef(theme);
12624
+ const themeRef = React37__namespace.default.useRef(theme);
11703
12625
  useIsomorphicLayoutEffect(() => {
11704
12626
  themeRef.current = theme;
11705
12627
  }, [theme]);
11706
- const setTheme = React25__namespace.default.useCallback(
12628
+ const setTheme = React37__namespace.default.useCallback(
11707
12629
  (t) => {
11708
12630
  setThemeState(t);
11709
12631
  try {
@@ -11714,10 +12636,10 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
11714
12636
  },
11715
12637
  [storageKey]
11716
12638
  );
11717
- const toggle = React25__namespace.default.useCallback(() => {
12639
+ const toggle = React37__namespace.default.useCallback(() => {
11718
12640
  setTheme(themeRef.current === "dark" ? "light" : "dark");
11719
12641
  }, [setTheme]);
11720
- React25__namespace.default.useEffect(() => {
12642
+ React37__namespace.default.useEffect(() => {
11721
12643
  if (!canUseDOM2) return void 0;
11722
12644
  const sync = () => setThemeState(read());
11723
12645
  const onStorage = (e) => {
@@ -11733,14 +12655,14 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
11733
12655
  return { theme, setTheme, toggle, isDark: theme === "dark" };
11734
12656
  }
11735
12657
  function useEventListener(eventName, handler, element, options) {
11736
- const saved = React25__namespace.default.useRef(handler);
12658
+ const saved = React37__namespace.default.useRef(handler);
11737
12659
  useIsomorphicLayoutEffect(() => {
11738
12660
  saved.current = handler;
11739
12661
  }, [handler]);
11740
12662
  const capture = typeof options === "boolean" ? options : options && options.capture;
11741
12663
  const passive = typeof options === "object" && options ? options.passive : void 0;
11742
12664
  const once = typeof options === "object" && options ? options.once : void 0;
11743
- React25__namespace.default.useEffect(() => {
12665
+ React37__namespace.default.useEffect(() => {
11744
12666
  const target = element && element.current || element || (canUseDOM2 ? window : null);
11745
12667
  if (!target || !target.addEventListener) return void 0;
11746
12668
  const opts = typeof options === "boolean" ? options : { capture, passive, once };
@@ -11750,11 +12672,11 @@ function useEventListener(eventName, handler, element, options) {
11750
12672
  }, [eventName, element, capture, passive, once]);
11751
12673
  }
11752
12674
  function useClickOutside(ref, handler, events = ["mousedown", "touchstart"]) {
11753
- const saved = React25__namespace.default.useRef(handler);
12675
+ const saved = React37__namespace.default.useRef(handler);
11754
12676
  useIsomorphicLayoutEffect(() => {
11755
12677
  saved.current = handler;
11756
12678
  }, [handler]);
11757
- React25__namespace.default.useEffect(() => {
12679
+ React37__namespace.default.useEffect(() => {
11758
12680
  if (!canUseDOM2) return void 0;
11759
12681
  const listener = (e) => {
11760
12682
  const el = ref && ref.current;
@@ -11789,8 +12711,8 @@ function useLocalStorage(key, initialValue) {
11789
12711
  return initialValue;
11790
12712
  }
11791
12713
  };
11792
- const [stored, setStored] = React25__namespace.default.useState(read);
11793
- const setValue = React25__namespace.default.useCallback(
12714
+ const [stored, setStored] = React37__namespace.default.useState(read);
12715
+ const setValue = React37__namespace.default.useCallback(
11794
12716
  (value) => {
11795
12717
  setStored((prev) => {
11796
12718
  const next = typeof value === "function" ? value(prev) : value;
@@ -11806,8 +12728,8 @@ function useLocalStorage(key, initialValue) {
11806
12728
  return [stored, setValue];
11807
12729
  }
11808
12730
  function useCopyToClipboard(timeout = 1500) {
11809
- const [copied, setCopied] = React25__namespace.default.useState(false);
11810
- const copy = React25__namespace.default.useCallback(async (text) => {
12731
+ const [copied, setCopied] = React37__namespace.default.useState(false);
12732
+ const copy = React37__namespace.default.useCallback(async (text) => {
11811
12733
  if (!canUseDOM2 || !navigator.clipboard) {
11812
12734
  setCopied(false);
11813
12735
  return false;
@@ -11821,7 +12743,7 @@ function useCopyToClipboard(timeout = 1500) {
11821
12743
  return false;
11822
12744
  }
11823
12745
  }, []);
11824
- React25__namespace.default.useEffect(() => {
12746
+ React37__namespace.default.useEffect(() => {
11825
12747
  if (!copied) return void 0;
11826
12748
  const t = setTimeout(() => setCopied(false), timeout);
11827
12749
  return () => clearTimeout(t);
@@ -11829,23 +12751,23 @@ function useCopyToClipboard(timeout = 1500) {
11829
12751
  return { copied, copy };
11830
12752
  }
11831
12753
  function useDebouncedValue(value, delay = 200) {
11832
- const [debounced, setDebounced] = React25__namespace.default.useState(value);
11833
- React25__namespace.default.useEffect(() => {
12754
+ const [debounced, setDebounced] = React37__namespace.default.useState(value);
12755
+ React37__namespace.default.useEffect(() => {
11834
12756
  const t = setTimeout(() => setDebounced(value), delay);
11835
12757
  return () => clearTimeout(t);
11836
12758
  }, [value, delay]);
11837
12759
  return debounced;
11838
12760
  }
11839
12761
  function useDebouncedCallback(callback, delay = 200) {
11840
- const saved = React25__namespace.default.useRef(callback);
11841
- const timer = React25__namespace.default.useRef(null);
12762
+ const saved = React37__namespace.default.useRef(callback);
12763
+ const timer = React37__namespace.default.useRef(null);
11842
12764
  useIsomorphicLayoutEffect(() => {
11843
12765
  saved.current = callback;
11844
12766
  }, [callback]);
11845
- React25__namespace.default.useEffect(() => () => {
12767
+ React37__namespace.default.useEffect(() => () => {
11846
12768
  if (timer.current) clearTimeout(timer.current);
11847
12769
  }, []);
11848
- return React25__namespace.default.useCallback(
12770
+ return React37__namespace.default.useCallback(
11849
12771
  (...args) => {
11850
12772
  if (timer.current) clearTimeout(timer.current);
11851
12773
  timer.current = setTimeout(() => saved.current(...args), delay);
@@ -11854,33 +12776,33 @@ function useDebouncedCallback(callback, delay = 200) {
11854
12776
  );
11855
12777
  }
11856
12778
  function useInterval(callback, delay) {
11857
- const saved = React25__namespace.default.useRef(callback);
12779
+ const saved = React37__namespace.default.useRef(callback);
11858
12780
  useIsomorphicLayoutEffect(() => {
11859
12781
  saved.current = callback;
11860
12782
  }, [callback]);
11861
- React25__namespace.default.useEffect(() => {
12783
+ React37__namespace.default.useEffect(() => {
11862
12784
  if (delay == null) return void 0;
11863
12785
  const id = setInterval(() => saved.current(), delay);
11864
12786
  return () => clearInterval(id);
11865
12787
  }, [delay]);
11866
12788
  }
11867
12789
  function useTimeout(callback, delay) {
11868
- const saved = React25__namespace.default.useRef(callback);
12790
+ const saved = React37__namespace.default.useRef(callback);
11869
12791
  useIsomorphicLayoutEffect(() => {
11870
12792
  saved.current = callback;
11871
12793
  }, [callback]);
11872
- React25__namespace.default.useEffect(() => {
12794
+ React37__namespace.default.useEffect(() => {
11873
12795
  if (delay == null) return void 0;
11874
12796
  const id = setTimeout(() => saved.current(), delay);
11875
12797
  return () => clearTimeout(id);
11876
12798
  }, [delay]);
11877
12799
  }
11878
12800
  function useWindowSize() {
11879
- const [size, setSize] = React25__namespace.default.useState(() => ({
12801
+ const [size, setSize] = React37__namespace.default.useState(() => ({
11880
12802
  width: canUseDOM2 ? window.innerWidth : 0,
11881
12803
  height: canUseDOM2 ? window.innerHeight : 0
11882
12804
  }));
11883
- React25__namespace.default.useEffect(() => {
12805
+ React37__namespace.default.useEffect(() => {
11884
12806
  if (!canUseDOM2) return void 0;
11885
12807
  const onResize = () => setSize({ width: window.innerWidth, height: window.innerHeight });
11886
12808
  onResize();
@@ -11890,8 +12812,8 @@ function useWindowSize() {
11890
12812
  return size;
11891
12813
  }
11892
12814
  function useHover(ref) {
11893
- const [hovered, setHovered] = React25__namespace.default.useState(false);
11894
- React25__namespace.default.useEffect(() => {
12815
+ const [hovered, setHovered] = React37__namespace.default.useState(false);
12816
+ React37__namespace.default.useEffect(() => {
11895
12817
  const el = ref && ref.current;
11896
12818
  if (!el) return void 0;
11897
12819
  const on = () => setHovered(true);
@@ -11907,8 +12829,8 @@ function useHover(ref) {
11907
12829
  }
11908
12830
  function useIntersectionObserver(ref, options = {}) {
11909
12831
  const { root = null, rootMargin = "0px", threshold = 0 } = options;
11910
- const [entry, setEntry] = React25__namespace.default.useState(null);
11911
- React25__namespace.default.useEffect(() => {
12832
+ const [entry, setEntry] = React37__namespace.default.useState(null);
12833
+ React37__namespace.default.useEffect(() => {
11912
12834
  const el = ref && ref.current;
11913
12835
  if (!canUseDOM2 || !el || typeof IntersectionObserver === "undefined") return void 0;
11914
12836
  const obs = new IntersectionObserver(([e]) => setEntry(e), { root, rootMargin, threshold });
@@ -11918,7 +12840,7 @@ function useIntersectionObserver(ref, options = {}) {
11918
12840
  return entry;
11919
12841
  }
11920
12842
  function useId(prefix = "twc") {
11921
- const raw = React25__namespace.default.useId();
12843
+ const raw = React37__namespace.default.useId();
11922
12844
  return prefix ? `${prefix}-${raw.replace(/:/g, "")}` : raw;
11923
12845
  }
11924
12846
  var useFocusTrap2 = useFocusTrap;
@@ -11927,6 +12849,7 @@ var useScrollLock2 = useScrollLock;
11927
12849
 
11928
12850
  exports.Accordion = Accordion;
11929
12851
  exports.Alert = Alert;
12852
+ exports.Anchor = Anchor;
11930
12853
  exports.AppShell = AppShell;
11931
12854
  exports.Avatar = Avatar;
11932
12855
  exports.AvatarMenu = AvatarMenu;
@@ -11940,6 +12863,7 @@ exports.Chart = Chart;
11940
12863
  exports.Checkbox = Checkbox;
11941
12864
  exports.Code = Code;
11942
12865
  exports.ColorPicker = ColorPicker;
12866
+ exports.ColorSchemeScript = ColorSchemeScript;
11943
12867
  exports.Combobox = Combobox;
11944
12868
  exports.CommandPalette = CommandPalette;
11945
12869
  exports.Container = Container;
@@ -11954,17 +12878,23 @@ exports.Drawer = Drawer;
11954
12878
  exports.EmptyState = EmptyState;
11955
12879
  exports.Field = Field;
11956
12880
  exports.FileUpload = FileUpload;
12881
+ exports.Form = Form;
11957
12882
  exports.Grid = Grid;
11958
12883
  exports.Heading = Heading;
11959
12884
  exports.IconButton = IconButton;
12885
+ exports.Image = Image;
11960
12886
  exports.Input = Input;
11961
12887
  exports.Kanban = Kanban;
12888
+ exports.Kbd = Kbd;
12889
+ exports.Label = Label;
11962
12890
  exports.List = List;
11963
12891
  exports.Menu = Menu;
11964
12892
  exports.MultiSelect = MultiSelect;
11965
12893
  exports.Navbar = Navbar;
11966
12894
  exports.Pagination = Pagination;
11967
12895
  exports.Popover = Popover;
12896
+ exports.Portal = Portal;
12897
+ exports.Pre = Pre;
11968
12898
  exports.Progress = Progress;
11969
12899
  exports.Radio = Radio;
11970
12900
  exports.RadioGroup = RadioGroup;
@@ -11983,12 +12913,17 @@ exports.Tabs = Tabs;
11983
12913
  exports.Tag = Tag;
11984
12914
  exports.Text = Text;
11985
12915
  exports.Textarea = Textarea;
12916
+ exports.ThemeProvider = ThemeProvider;
11986
12917
  exports.Timeline = Timeline;
11987
12918
  exports.Toast = Toast;
11988
12919
  exports.ToastProvider = ToastProvider;
11989
12920
  exports.ToastViewport = ToastViewport;
11990
12921
  exports.Tooltip = Tooltip;
11991
12922
  exports.TreeView = TreeView;
12923
+ exports.TwicoProvider = TwicoProvider;
12924
+ exports.VisuallyHidden = VisuallyHidden;
12925
+ exports.createTheme = createTheme;
12926
+ exports.getColorSchemeScript = getColorSchemeScript;
11992
12927
  exports.runDatatableQuery = runDatatableQuery;
11993
12928
  exports.useClickOutside = useClickOutside;
11994
12929
  exports.useColorScheme = useColorScheme;