@reopt-ai/opt-ui-primitives 1.5.1 → 1.5.2
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 +1080 -589
- package/dist/index.d.cts +137 -21
- package/dist/index.d.ts +137 -21
- package/dist/index.js +1080 -591
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -176,6 +176,32 @@ function removeGlobalListeners() {
|
|
|
176
176
|
document.removeEventListener("touchstart", handlePointerDown, true);
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Subscribe to the shared modality tracking and read it on demand.
|
|
181
|
+
*
|
|
182
|
+
* Returns a stable predicate answering "should this focus show as visible?".
|
|
183
|
+
* Widgets that must react ONLY to keyboard focus (a tooltip must not pop open
|
|
184
|
+
* because the user clicked its trigger) gate their focus handler on it — the
|
|
185
|
+
* `visibleOnly` behavior.
|
|
186
|
+
*
|
|
187
|
+
* The browser's own `:focus-visible` is the authority whenever the element and
|
|
188
|
+
* the engine support it: it knows about text inputs (which show a ring even
|
|
189
|
+
* after a click), programmatic focus, and platform conventions the modality
|
|
190
|
+
* heuristic cannot infer. The document-level heuristic is the fallback for
|
|
191
|
+
* engines and test environments where matching `:focus-visible` throws.
|
|
192
|
+
*/
|
|
193
|
+
function useKeyboardModality() {
|
|
194
|
+
(0, react.useEffect)(() => {
|
|
195
|
+
addGlobalListeners();
|
|
196
|
+
return removeGlobalListeners;
|
|
197
|
+
}, []);
|
|
198
|
+
return (0, react.useCallback)((element) => {
|
|
199
|
+
if (element) try {
|
|
200
|
+
if (element.matches(":focus-visible")) return true;
|
|
201
|
+
} catch (_unused) {}
|
|
202
|
+
return hadKeyboardEvent;
|
|
203
|
+
}, []);
|
|
204
|
+
}
|
|
179
205
|
/** Returns `focusVisibleProps` to spread on a focusable element. */
|
|
180
206
|
function useFocusVisible() {
|
|
181
207
|
(0, react.useEffect)(() => {
|
|
@@ -192,6 +218,89 @@ function useFocusVisible() {
|
|
|
192
218
|
} };
|
|
193
219
|
}
|
|
194
220
|
//#endregion
|
|
221
|
+
//#region src/hooks/use-item-registry.ts
|
|
222
|
+
const DOCUMENT_POSITION_FOLLOWING = 4;
|
|
223
|
+
function resolveElement(entry) {
|
|
224
|
+
if (entry.element) return entry.element;
|
|
225
|
+
if (typeof document === "undefined") return null;
|
|
226
|
+
return document.getElementById(entry.id);
|
|
227
|
+
}
|
|
228
|
+
/** Insert `entry` at its document position instead of appending it. */
|
|
229
|
+
function insertByDomOrder(list, entry) {
|
|
230
|
+
const element = resolveElement(entry);
|
|
231
|
+
const lastElement = list.length > 0 ? resolveElement(list[list.length - 1]) : null;
|
|
232
|
+
if (!element || !lastElement || lastElement.compareDocumentPosition(element) & DOCUMENT_POSITION_FOLLOWING) {
|
|
233
|
+
list.push(entry);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
for (let i = 0; i < list.length; i += 1) {
|
|
237
|
+
const other = resolveElement(list[i]);
|
|
238
|
+
if (other && element.compareDocumentPosition(other) & DOCUMENT_POSITION_FOLLOWING) {
|
|
239
|
+
list.splice(i, 0, entry);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
list.push(entry);
|
|
244
|
+
}
|
|
245
|
+
/** Id of the first item that is not disabled. */
|
|
246
|
+
function firstEnabledId(items) {
|
|
247
|
+
var _items$find$id, _items$find;
|
|
248
|
+
return (_items$find$id = (_items$find = items.find((item) => !item.disabled)) === null || _items$find === void 0 ? void 0 : _items$find.id) !== null && _items$find$id !== void 0 ? _items$find$id : null;
|
|
249
|
+
}
|
|
250
|
+
/** Id of the last item that is not disabled. */
|
|
251
|
+
function lastEnabledId(items) {
|
|
252
|
+
for (let i = items.length - 1; i >= 0; i -= 1) if (!items[i].disabled) return items[i].id;
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Id `delta` enabled items away from `activeId` (disabled skipped).
|
|
257
|
+
*
|
|
258
|
+
* Clamps at the ends by default — the listbox/menu behavior. Pass
|
|
259
|
+
* `{ wrap: true }` for the WAI-ARIA tabs behavior, where the arrow keys cycle.
|
|
260
|
+
* With no active item, a forward move lands on the first enabled item and a
|
|
261
|
+
* backward move on the last.
|
|
262
|
+
*/
|
|
263
|
+
function moveActiveId(items, activeId, delta, options) {
|
|
264
|
+
const enabled = items.filter((item) => !item.disabled);
|
|
265
|
+
if (enabled.length === 0) return null;
|
|
266
|
+
const index = enabled.findIndex((item) => item.id === activeId);
|
|
267
|
+
if (index < 0) {
|
|
268
|
+
if (options === null || options === void 0 ? void 0 : options.wrap) return enabled[0].id;
|
|
269
|
+
return delta > 0 ? enabled[0].id : enabled[enabled.length - 1].id;
|
|
270
|
+
}
|
|
271
|
+
const count = enabled.length;
|
|
272
|
+
return enabled[(options === null || options === void 0 ? void 0 : options.wrap) ? ((index + delta) % count + count) % count : Math.min(count - 1, Math.max(0, index + delta))].id;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Id of the enabled item nearest to `index`: forward first (the item that took
|
|
276
|
+
* the removed slot), then backward. `null` when the list has none left.
|
|
277
|
+
*
|
|
278
|
+
* This is what keeps the navigation POSITION when the active item is removed.
|
|
279
|
+
*/
|
|
280
|
+
function nearestEnabledId(items, index) {
|
|
281
|
+
for (let i = Math.max(0, index); i < items.length; i += 1) if (!items[i].disabled) return items[i].id;
|
|
282
|
+
for (let i = Math.min(index, items.length) - 1; i >= 0; i -= 1) if (!items[i].disabled) return items[i].id;
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
/** Creates a document-ordered item registry. Stable across renders. */
|
|
286
|
+
function useItemRegistry() {
|
|
287
|
+
const items = (0, react.useRef)([]);
|
|
288
|
+
return {
|
|
289
|
+
items,
|
|
290
|
+
registerItem: (0, react.useCallback)((entry) => {
|
|
291
|
+
const list = items.current;
|
|
292
|
+
const existing = list.findIndex((item) => item.id === entry.id);
|
|
293
|
+
if (existing >= 0) list.splice(existing, 1);
|
|
294
|
+
insertByDomOrder(list, entry);
|
|
295
|
+
}, []),
|
|
296
|
+
unregisterItem: (0, react.useCallback)((id) => {
|
|
297
|
+
const index = items.current.findIndex((item) => item.id === id);
|
|
298
|
+
if (index >= 0) items.current.splice(index, 1);
|
|
299
|
+
return index;
|
|
300
|
+
}, [])
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
//#endregion
|
|
195
304
|
//#region src/hooks/use-roving-tabindex.ts
|
|
196
305
|
/**
|
|
197
306
|
* Implements roving tabindex pattern for keyboard navigation.
|
|
@@ -203,7 +312,7 @@ function useFocusVisible() {
|
|
|
203
312
|
*/
|
|
204
313
|
function useRovingTabindex(options = {}) {
|
|
205
314
|
const { orientation = "horizontal", loop = false, rtl = false, columns } = options;
|
|
206
|
-
const itemsRef
|
|
315
|
+
const { items: itemsRef, registerItem: registerEntry, unregisterItem: removeItem } = useItemRegistry();
|
|
207
316
|
const [activeId, setActiveId] = (0, react.useState)(null);
|
|
208
317
|
const containerRef = (0, react.useRef)(null);
|
|
209
318
|
const seededRef = (0, react.useRef)(false);
|
|
@@ -211,14 +320,8 @@ function useRovingTabindex(options = {}) {
|
|
|
211
320
|
return itemsRef.current.filter((item) => !item.disabled);
|
|
212
321
|
}, []);
|
|
213
322
|
const register = (0, react.useCallback)((id, element, disabled) => {
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
if (existing >= 0) itemsRef.current[existing] = {
|
|
217
|
-
id,
|
|
218
|
-
element,
|
|
219
|
-
disabled
|
|
220
|
-
};
|
|
221
|
-
else itemsRef.current.push({
|
|
323
|
+
const activeBecameDisabled = itemsRef.current.findIndex((item) => item.id === id) >= 0 && id === activeId && !!disabled;
|
|
324
|
+
registerEntry({
|
|
222
325
|
id,
|
|
223
326
|
element,
|
|
224
327
|
disabled
|
|
@@ -227,21 +330,28 @@ function useRovingTabindex(options = {}) {
|
|
|
227
330
|
seededRef.current = true;
|
|
228
331
|
setActiveId(id);
|
|
229
332
|
} else if (activeBecameDisabled) {
|
|
230
|
-
|
|
231
|
-
const next = (_itemsRef$current$fin = (_itemsRef$current$fin2 = itemsRef.current.find((item) => !item.disabled)) === null || _itemsRef$current$fin2 === void 0 ? void 0 : _itemsRef$current$fin2.id) !== null && _itemsRef$current$fin !== void 0 ? _itemsRef$current$fin : null;
|
|
333
|
+
const next = firstEnabledId(itemsRef.current);
|
|
232
334
|
if (next === null) seededRef.current = false;
|
|
233
335
|
setActiveId(next);
|
|
234
336
|
}
|
|
235
|
-
}, [
|
|
337
|
+
}, [
|
|
338
|
+
activeId,
|
|
339
|
+
itemsRef,
|
|
340
|
+
registerEntry
|
|
341
|
+
]);
|
|
236
342
|
const unregister = (0, react.useCallback)((id) => {
|
|
237
|
-
|
|
343
|
+
const removedIndex = removeItem(id);
|
|
344
|
+
if (removedIndex < 0) return;
|
|
238
345
|
if (activeId === id) {
|
|
239
|
-
|
|
240
|
-
const next = (_getEnabledItems$0$id = (_getEnabledItems$ = getEnabledItems()[0]) === null || _getEnabledItems$ === void 0 ? void 0 : _getEnabledItems$.id) !== null && _getEnabledItems$0$id !== void 0 ? _getEnabledItems$0$id : null;
|
|
346
|
+
const next = nearestEnabledId(itemsRef.current, removedIndex);
|
|
241
347
|
if (next === null) seededRef.current = false;
|
|
242
348
|
setActiveId(next);
|
|
243
349
|
}
|
|
244
|
-
}, [
|
|
350
|
+
}, [
|
|
351
|
+
activeId,
|
|
352
|
+
itemsRef,
|
|
353
|
+
removeItem
|
|
354
|
+
]);
|
|
245
355
|
const moveTo = (0, react.useCallback)((id) => {
|
|
246
356
|
setActiveId(id);
|
|
247
357
|
const item = itemsRef.current.find((i) => i.id === id);
|
|
@@ -279,12 +389,12 @@ function useRovingTabindex(options = {}) {
|
|
|
279
389
|
moveByOffset(rtl ? 1 : -1);
|
|
280
390
|
} else if (e.key === "Home") {
|
|
281
391
|
e.preventDefault();
|
|
282
|
-
const
|
|
283
|
-
if (
|
|
392
|
+
const first = firstEnabledId(itemsRef.current);
|
|
393
|
+
if (first) moveTo(first);
|
|
284
394
|
} else if (e.key === "End") {
|
|
285
395
|
e.preventDefault();
|
|
286
|
-
const
|
|
287
|
-
if (
|
|
396
|
+
const last = lastEnabledId(itemsRef.current);
|
|
397
|
+
if (last) moveTo(last);
|
|
288
398
|
}
|
|
289
399
|
}, [
|
|
290
400
|
orientation,
|
|
@@ -441,6 +551,28 @@ function useFloating(options = {}) {
|
|
|
441
551
|
Object.assign(elements.floating.style, styles);
|
|
442
552
|
}
|
|
443
553
|
}));
|
|
554
|
+
m.push({
|
|
555
|
+
name: "optTransformOrigin",
|
|
556
|
+
fn(state) {
|
|
557
|
+
var _ref2, _middlewareData$shift, _middlewareData$shift2;
|
|
558
|
+
const { elements, middlewareData, placement: resolved, rects } = state;
|
|
559
|
+
const [resolvedSide, resolvedAlign] = resolved.split("-");
|
|
560
|
+
const isVertical = resolvedSide === "top" || resolvedSide === "bottom";
|
|
561
|
+
const so = sideOffsetRef.current;
|
|
562
|
+
const sideOffsetValue = (_ref2 = typeof so === "function" ? so({
|
|
563
|
+
rects,
|
|
564
|
+
placement: resolved
|
|
565
|
+
}) : so) !== null && _ref2 !== void 0 ? _ref2 : 0;
|
|
566
|
+
const shiftAmount = isVertical ? ((_middlewareData$shift = middlewareData.shift) === null || _middlewareData$shift === void 0 ? void 0 : _middlewareData$shift.x) || 0 : ((_middlewareData$shift2 = middlewareData.shift) === null || _middlewareData$shift2 === void 0 ? void 0 : _middlewareData$shift2.y) || 0;
|
|
567
|
+
let crossOrigin;
|
|
568
|
+
if (!resolvedAlign) crossOrigin = "50%";
|
|
569
|
+
else if (Math.abs(shiftAmount) <= 1) crossOrigin = resolvedAlign === "start" ? "0%" : "100%";
|
|
570
|
+
else crossOrigin = isVertical ? `${rects.reference.x + rects.reference.width / 2 - state.x}px` : `${rects.reference.y + rects.reference.height / 2 - state.y}px`;
|
|
571
|
+
const sideOrigin = resolvedSide === "top" || resolvedSide === "left" ? `calc(100% + ${sideOffsetValue}px)` : `${-sideOffsetValue}px`;
|
|
572
|
+
elements.floating.style.setProperty("--opt-transform-origin", isVertical ? `${crossOrigin} ${sideOrigin}` : `${sideOrigin} ${crossOrigin}`);
|
|
573
|
+
return {};
|
|
574
|
+
}
|
|
575
|
+
});
|
|
444
576
|
m.push((0, _floating_ui_react.hide)({ padding: overflowPadding }));
|
|
445
577
|
return m;
|
|
446
578
|
}, [
|
|
@@ -495,7 +627,8 @@ function useFloating(options = {}) {
|
|
|
495
627
|
ref: floating.refs.setFloating,
|
|
496
628
|
style: _objectSpread2(_objectSpread2({
|
|
497
629
|
"--opt-available-width": "100vw",
|
|
498
|
-
"--opt-available-height": "100vh"
|
|
630
|
+
"--opt-available-height": "100vh",
|
|
631
|
+
"--opt-transform-origin": "center"
|
|
499
632
|
}, floating.floatingStyles), isPositioned ? null : { opacity: 0 })
|
|
500
633
|
}),
|
|
501
634
|
/**
|
|
@@ -565,6 +698,137 @@ function useScrollActiveDescendantIntoView(activeId) {
|
|
|
565
698
|
}, [activeId]);
|
|
566
699
|
}
|
|
567
700
|
//#endregion
|
|
701
|
+
//#region src/hooks/use-hidden-until-found.ts
|
|
702
|
+
/**
|
|
703
|
+
* Keeps collapsed content reachable by browser find-in-page.
|
|
704
|
+
*
|
|
705
|
+
* The content stays MOUNTED and toggles `hidden="until-found"` instead of
|
|
706
|
+
* unmounting, so Chromium can match text inside it; when it does, the
|
|
707
|
+
* `beforematch` event fires and `onReveal` opens the owning disclosure so the
|
|
708
|
+
* component state stays consistent with what the browser just revealed.
|
|
709
|
+
*
|
|
710
|
+
* React coerces the `hidden` prop to a boolean attribute, so the "until-found"
|
|
711
|
+
* string has to be written imperatively — hence the ref rather than a prop.
|
|
712
|
+
*
|
|
713
|
+
* Progressive enhancement: browsers without `hidden="until-found"` treat it as
|
|
714
|
+
* plain `hidden`, which is the correct fallback.
|
|
715
|
+
*/
|
|
716
|
+
function useHiddenUntilFound(ref, { enabled, open, onReveal }) {
|
|
717
|
+
(0, react.useEffect)(() => {
|
|
718
|
+
const el = ref.current;
|
|
719
|
+
if (!el || !enabled) return;
|
|
720
|
+
const handleBeforeMatch = () => onReveal();
|
|
721
|
+
el.addEventListener("beforematch", handleBeforeMatch);
|
|
722
|
+
return () => el.removeEventListener("beforematch", handleBeforeMatch);
|
|
723
|
+
}, [
|
|
724
|
+
ref,
|
|
725
|
+
enabled,
|
|
726
|
+
onReveal
|
|
727
|
+
]);
|
|
728
|
+
(0, react.useEffect)(() => {
|
|
729
|
+
const el = ref.current;
|
|
730
|
+
if (!el || !enabled) return;
|
|
731
|
+
if (open) el.removeAttribute("hidden");
|
|
732
|
+
else el.setAttribute("hidden", "until-found");
|
|
733
|
+
}, [
|
|
734
|
+
ref,
|
|
735
|
+
enabled,
|
|
736
|
+
open
|
|
737
|
+
]);
|
|
738
|
+
}
|
|
739
|
+
//#endregion
|
|
740
|
+
//#region src/internal/merge-props.ts
|
|
741
|
+
const EVENT_HANDLER = /^on[A-Z]/;
|
|
742
|
+
function isSyntheticEvent(value) {
|
|
743
|
+
return typeof value === "object" && value !== null && "nativeEvent" in value;
|
|
744
|
+
}
|
|
745
|
+
function makePreventable(event) {
|
|
746
|
+
if (typeof event.preventOptHandler === "function") return;
|
|
747
|
+
event.optHandlerPrevented = false;
|
|
748
|
+
event.preventOptHandler = () => {
|
|
749
|
+
event.optHandlerPrevented = true;
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
function chainHandlers(a, b) {
|
|
753
|
+
return (...args) => {
|
|
754
|
+
const event = args[0];
|
|
755
|
+
if (isSyntheticEvent(event)) {
|
|
756
|
+
makePreventable(event);
|
|
757
|
+
a(...args);
|
|
758
|
+
if (event.optHandlerPrevented) return void 0;
|
|
759
|
+
return b(...args);
|
|
760
|
+
}
|
|
761
|
+
a(...args);
|
|
762
|
+
return b(...args);
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
/** Merge prop objects left→right with handler/className/style composition. */
|
|
766
|
+
function mergeProps(...parts) {
|
|
767
|
+
const result = {};
|
|
768
|
+
for (const part of parts) {
|
|
769
|
+
if (!part) continue;
|
|
770
|
+
for (const key in part) {
|
|
771
|
+
if (!Object.prototype.hasOwnProperty.call(part, key)) continue;
|
|
772
|
+
const value = part[key];
|
|
773
|
+
const existing = result[key];
|
|
774
|
+
if (EVENT_HANDLER.test(key)) {
|
|
775
|
+
if (typeof value === "function" && typeof existing === "function") result[key] = chainHandlers(existing, value);
|
|
776
|
+
else if (value === void 0 && typeof existing === "function") continue;
|
|
777
|
+
else result[key] = value;
|
|
778
|
+
} else if (key === "className") result[key] = [existing, value].filter(Boolean).join(" ") || void 0;
|
|
779
|
+
else if (key === "style" && existing && typeof existing === "object" && value && typeof value === "object") result[key] = _objectSpread2(_objectSpread2({}, existing), value);
|
|
780
|
+
else result[key] = value;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
return result;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Merge multiple refs (callback or object) into one callback ref.
|
|
787
|
+
*
|
|
788
|
+
* Returns a React 19 ref CLEANUP function, so every merged ref is detached at
|
|
789
|
+
* exactly the right time: callback refs that themselves return a cleanup have
|
|
790
|
+
* it invoked (previously the returned cleanup was dropped on the floor, leaking
|
|
791
|
+
* whatever it was meant to release), and the rest are detached by being called
|
|
792
|
+
* with `null` / having their `.current` reset. Cleanups run in reverse
|
|
793
|
+
* attachment order, mirroring React's own teardown order.
|
|
794
|
+
*/
|
|
795
|
+
function mergeRefs(...refs) {
|
|
796
|
+
return (value) => {
|
|
797
|
+
const cleanups = [];
|
|
798
|
+
for (const ref of refs) if (typeof ref === "function") {
|
|
799
|
+
const cleanup = ref(value);
|
|
800
|
+
cleanups.push(typeof cleanup === "function" ? cleanup : () => ref(null));
|
|
801
|
+
} else if (ref != null) {
|
|
802
|
+
const objectRef = ref;
|
|
803
|
+
objectRef.current = value;
|
|
804
|
+
cleanups.push(() => {
|
|
805
|
+
objectRef.current = null;
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
return () => {
|
|
809
|
+
for (let i = cleanups.length - 1; i >= 0; i -= 1) cleanups[i]();
|
|
810
|
+
};
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
//#endregion
|
|
814
|
+
//#region src/hooks/use-merged-ref.ts
|
|
815
|
+
/**
|
|
816
|
+
* A STABLE merged ref callback.
|
|
817
|
+
*
|
|
818
|
+
* `mergeRefs` returns a fresh function on every call, and React re-attaches a
|
|
819
|
+
* callback ref whenever its identity changes: it detaches first (nulling every
|
|
820
|
+
* ref in the chain), then attaches again. Building the merged ref inline during
|
|
821
|
+
* render therefore made every render null out the element the animation and
|
|
822
|
+
* measurement code reads — which is how the collapsible content on the explore
|
|
823
|
+
* detail pages stopped opening.
|
|
824
|
+
*
|
|
825
|
+
* Memoizing on the ref identities keeps the callback stable across renders, so
|
|
826
|
+
* the refs are attached exactly once.
|
|
827
|
+
*/
|
|
828
|
+
function useMergedRef(...refs) {
|
|
829
|
+
return (0, react.useMemo)(() => mergeRefs(...refs), refs);
|
|
830
|
+
}
|
|
831
|
+
//#endregion
|
|
568
832
|
//#region \0@oxc-project+runtime@0.146.0/helpers/esm/objectWithoutPropertiesLoose.js
|
|
569
833
|
function _objectWithoutPropertiesLoose(r, e) {
|
|
570
834
|
if (null == r) return {};
|
|
@@ -639,24 +903,14 @@ function DisclosureContent(_ref2) {
|
|
|
639
903
|
const { open, setOpen, contentId, triggerId, animated } = useDisclosureContext();
|
|
640
904
|
const { ref, mounted, dataAttributes } = useEnterLeave(open, { animated: animated && !hiddenUntilFound });
|
|
641
905
|
const innerRef = (0, react.useRef)(null);
|
|
642
|
-
(
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
const onBeforeMatch = () => setOpen(true);
|
|
649
|
-
el.addEventListener("beforematch", onBeforeMatch);
|
|
650
|
-
return () => el.removeEventListener("beforematch", onBeforeMatch);
|
|
651
|
-
}, [hiddenUntilFound, setOpen]);
|
|
652
|
-
(0, react.useEffect)(() => {
|
|
653
|
-
const el = innerRef.current;
|
|
654
|
-
if (!el || !hiddenUntilFound) return;
|
|
655
|
-
if (open) el.removeAttribute("hidden");
|
|
656
|
-
else el.setAttribute("hidden", "until-found");
|
|
657
|
-
}, [open, hiddenUntilFound]);
|
|
906
|
+
const contentRef = useMergedRef(innerRef, ref);
|
|
907
|
+
useHiddenUntilFound(innerRef, {
|
|
908
|
+
enabled: hiddenUntilFound,
|
|
909
|
+
open,
|
|
910
|
+
onReveal: (0, react.useCallback)(() => setOpen(true), [setOpen])
|
|
911
|
+
});
|
|
658
912
|
if (hiddenUntilFound) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", _objectSpread2({
|
|
659
|
-
ref:
|
|
913
|
+
ref: contentRef,
|
|
660
914
|
id: contentId,
|
|
661
915
|
role: "region",
|
|
662
916
|
"aria-labelledby": triggerId,
|
|
@@ -665,7 +919,7 @@ function DisclosureContent(_ref2) {
|
|
|
665
919
|
}, props));
|
|
666
920
|
if (!mounted) return null;
|
|
667
921
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", _objectSpread2(_objectSpread2({
|
|
668
|
-
ref:
|
|
922
|
+
ref: contentRef,
|
|
669
923
|
id: contentId,
|
|
670
924
|
role: "region",
|
|
671
925
|
"aria-labelledby": triggerId,
|
|
@@ -811,12 +1065,7 @@ const DialogPanel = (0, react.forwardRef)((_ref2, forwardedRef) => {
|
|
|
811
1065
|
lastFocusedRef.current = null;
|
|
812
1066
|
}
|
|
813
1067
|
}, [mounted]);
|
|
814
|
-
const mergedRef = (0, react.
|
|
815
|
-
dialogRef.current = node;
|
|
816
|
-
enterLeaveRef.current = node;
|
|
817
|
-
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
818
|
-
else if (forwardedRef) forwardedRef.current = node;
|
|
819
|
-
}, [
|
|
1068
|
+
const mergedRef = (0, react.useMemo)(() => mergeRefs(dialogRef, enterLeaveRef, forwardedRef), [
|
|
820
1069
|
dialogRef,
|
|
821
1070
|
enterLeaveRef,
|
|
822
1071
|
forwardedRef
|
|
@@ -833,7 +1082,8 @@ const DialogPanel = (0, react.forwardRef)((_ref2, forwardedRef) => {
|
|
|
833
1082
|
}, [
|
|
834
1083
|
dialogRef,
|
|
835
1084
|
setOpen,
|
|
836
|
-
dismissOnEscape
|
|
1085
|
+
dismissOnEscape,
|
|
1086
|
+
mounted
|
|
837
1087
|
]);
|
|
838
1088
|
const handleClick = (0, react.useCallback)((e) => {
|
|
839
1089
|
if (dismissOnBackdrop && e.target === e.currentTarget) setOpen(false);
|
|
@@ -898,13 +1148,9 @@ const _excluded2$12 = [
|
|
|
898
1148
|
"onClick"
|
|
899
1149
|
];
|
|
900
1150
|
const _excluded3$9 = ["tabId"];
|
|
1151
|
+
/** WAI-ARIA tabs wrap at both ends, unlike a listbox/menu (which clamps). */
|
|
901
1152
|
function nextEnabledTabId(tabs, currentId, delta) {
|
|
902
|
-
|
|
903
|
-
if (enabled.length === 0) return null;
|
|
904
|
-
const idx = enabled.findIndex((t) => t.id === currentId);
|
|
905
|
-
if (idx < 0) return enabled[0].id;
|
|
906
|
-
const n = enabled.length;
|
|
907
|
-
return enabled[((idx + delta) % n + n) % n].id;
|
|
1153
|
+
return moveActiveId(tabs, currentId, delta, { wrap: true });
|
|
908
1154
|
}
|
|
909
1155
|
const TabsContext = (0, react.createContext)(null);
|
|
910
1156
|
function useTabsContext() {
|
|
@@ -916,37 +1162,54 @@ function useTabsContext() {
|
|
|
916
1162
|
function TabsRoot({ children, selectedId: controlledId, defaultSelectedId = "", onSelectedIdChange, setSelectedId: setSelectedIdDeprecated, orientation = "horizontal" }) {
|
|
917
1163
|
const [selectedId, setSelectedId] = useControllableState(defaultSelectedId, controlledId, onSelectedIdChange !== null && onSelectedIdChange !== void 0 ? onSelectedIdChange : setSelectedIdDeprecated);
|
|
918
1164
|
const baseId = useId();
|
|
919
|
-
const tabs = (
|
|
920
|
-
const
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
}, []);
|
|
1165
|
+
const { items: tabs, registerItem, unregisterItem } = useItemRegistry();
|
|
1166
|
+
const selectedIdRef = (0, react.useRef)(selectedId);
|
|
1167
|
+
selectedIdRef.current = selectedId;
|
|
1168
|
+
const isControlled = controlledId !== void 0;
|
|
1169
|
+
const isControlledRef = (0, react.useRef)(isControlled);
|
|
1170
|
+
isControlledRef.current = isControlled;
|
|
1171
|
+
const setSelectedIdRef = (0, react.useRef)(setSelectedId);
|
|
1172
|
+
setSelectedIdRef.current = setSelectedId;
|
|
1173
|
+
const registerTab = (0, react.useCallback)((id, disabled) => registerItem({
|
|
1174
|
+
id,
|
|
1175
|
+
disabled
|
|
1176
|
+
}), [registerItem]);
|
|
931
1177
|
const unregisterTab = (0, react.useCallback)((id) => {
|
|
932
|
-
|
|
933
|
-
|
|
1178
|
+
const removedIndex = unregisterItem(id);
|
|
1179
|
+
if (selectedIdRef.current !== id) return;
|
|
1180
|
+
if (isControlledRef.current) return;
|
|
1181
|
+
const next = nearestEnabledId(tabs.current, removedIndex);
|
|
1182
|
+
if (next) setSelectedIdRef.current(next);
|
|
1183
|
+
}, [tabs, unregisterItem]);
|
|
934
1184
|
(0, react.useLayoutEffect)(() => {
|
|
935
1185
|
if (!selectedId) {
|
|
936
|
-
const first = tabs.current
|
|
937
|
-
if (first) setSelectedId(first
|
|
1186
|
+
const first = firstEnabledId(tabs.current);
|
|
1187
|
+
if (first) setSelectedId(first);
|
|
938
1188
|
}
|
|
939
|
-
}, [
|
|
1189
|
+
}, [
|
|
1190
|
+
selectedId,
|
|
1191
|
+
setSelectedId,
|
|
1192
|
+
tabs
|
|
1193
|
+
]);
|
|
1194
|
+
const contextValue = (0, react.useMemo)(() => ({
|
|
1195
|
+
selectedId,
|
|
1196
|
+
setSelectedId,
|
|
1197
|
+
baseId,
|
|
1198
|
+
orientation,
|
|
1199
|
+
registerTab,
|
|
1200
|
+
unregisterTab,
|
|
1201
|
+
tabs
|
|
1202
|
+
}), [
|
|
1203
|
+
selectedId,
|
|
1204
|
+
setSelectedId,
|
|
1205
|
+
baseId,
|
|
1206
|
+
orientation,
|
|
1207
|
+
registerTab,
|
|
1208
|
+
unregisterTab,
|
|
1209
|
+
tabs
|
|
1210
|
+
]);
|
|
940
1211
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabsContext.Provider, {
|
|
941
|
-
value:
|
|
942
|
-
selectedId,
|
|
943
|
-
setSelectedId,
|
|
944
|
-
baseId,
|
|
945
|
-
orientation,
|
|
946
|
-
registerTab,
|
|
947
|
-
unregisterTab,
|
|
948
|
-
tabs
|
|
949
|
-
},
|
|
1212
|
+
value: contextValue,
|
|
950
1213
|
children
|
|
951
1214
|
});
|
|
952
1215
|
}
|
|
@@ -1108,39 +1371,6 @@ const Radio = (0, react.forwardRef)((_ref2, ref) => {
|
|
|
1108
1371
|
});
|
|
1109
1372
|
Radio.displayName = "Radio";
|
|
1110
1373
|
//#endregion
|
|
1111
|
-
//#region src/internal/merge-props.ts
|
|
1112
|
-
const EVENT_HANDLER = /^on[A-Z]/;
|
|
1113
|
-
/** Merge prop objects left→right with handler/className/style composition. */
|
|
1114
|
-
function mergeProps(...parts) {
|
|
1115
|
-
const result = {};
|
|
1116
|
-
for (const part of parts) {
|
|
1117
|
-
if (!part) continue;
|
|
1118
|
-
for (const key in part) {
|
|
1119
|
-
if (!Object.prototype.hasOwnProperty.call(part, key)) continue;
|
|
1120
|
-
const value = part[key];
|
|
1121
|
-
const existing = result[key];
|
|
1122
|
-
if (EVENT_HANDLER.test(key) && typeof value === "function" && typeof existing === "function") {
|
|
1123
|
-
const a = existing;
|
|
1124
|
-
const b = value;
|
|
1125
|
-
result[key] = (...args) => {
|
|
1126
|
-
a(...args);
|
|
1127
|
-
return b(...args);
|
|
1128
|
-
};
|
|
1129
|
-
} else if (key === "className") result[key] = [existing, value].filter(Boolean).join(" ") || void 0;
|
|
1130
|
-
else if (key === "style" && existing && typeof existing === "object" && value && typeof value === "object") result[key] = _objectSpread2(_objectSpread2({}, existing), value);
|
|
1131
|
-
else result[key] = value;
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
return result;
|
|
1135
|
-
}
|
|
1136
|
-
/** Merge multiple refs (callback or object) into one callback ref. */
|
|
1137
|
-
function mergeRefs(...refs) {
|
|
1138
|
-
return (value) => {
|
|
1139
|
-
for (const ref of refs) if (typeof ref === "function") ref(value);
|
|
1140
|
-
else if (ref != null) ref.current = value;
|
|
1141
|
-
};
|
|
1142
|
-
}
|
|
1143
|
-
//#endregion
|
|
1144
1374
|
//#region src/internal/overlay-portal.tsx
|
|
1145
1375
|
/**
|
|
1146
1376
|
* Conditionally portals overlay content. When `portal` is false, children render
|
|
@@ -1166,6 +1396,32 @@ function OverlayPortal({ portal, portalRoot, children }) {
|
|
|
1166
1396
|
});
|
|
1167
1397
|
}
|
|
1168
1398
|
//#endregion
|
|
1399
|
+
//#region src/internal/render-element.tsx
|
|
1400
|
+
/**
|
|
1401
|
+
* Renders one part of a primitive: merges prop objects, merges refs, and
|
|
1402
|
+
* honors a `render` prop.
|
|
1403
|
+
*
|
|
1404
|
+
* A plain function, not a hook, so parts can call it after an early return
|
|
1405
|
+
* (`if (!mounted) return null`) — which most overlay panels do.
|
|
1406
|
+
*
|
|
1407
|
+
* Every part used to hand-roll this — an inline `ref={(node) => {...}}` that
|
|
1408
|
+
* poked one ref object and then type-checked a floating-ui callback ref, plus
|
|
1409
|
+
* an effect copying an element into the enter/leave ref. Eight copies of the
|
|
1410
|
+
* same wiring meant a fix (React 19 ref cleanup, say) had to be applied eight
|
|
1411
|
+
* times, and only `Composite` ever supported `render`. Routing parts through
|
|
1412
|
+
* here fixes all of them at once and makes `render` universal.
|
|
1413
|
+
*/
|
|
1414
|
+
function renderElement(tag, { render, refs, props }) {
|
|
1415
|
+
const mergedProps = mergeProps(...props !== null && props !== void 0 ? props : []);
|
|
1416
|
+
const mergedRef = mergeRefs(...refs !== null && refs !== void 0 ? refs : []);
|
|
1417
|
+
if (typeof render === "function") return render(_objectSpread2(_objectSpread2({}, mergedProps), {}, { ref: mergedRef }));
|
|
1418
|
+
if (render && (0, react.isValidElement)(render)) {
|
|
1419
|
+
const renderProps = render.props;
|
|
1420
|
+
return (0, react.cloneElement)(render, _objectSpread2(_objectSpread2({}, mergeProps(renderProps, mergedProps)), {}, { ref: mergeRefs(renderProps.ref, mergedRef) }));
|
|
1421
|
+
}
|
|
1422
|
+
return (0, react.createElement)(tag, _objectSpread2(_objectSpread2({}, mergedProps), {}, { ref: mergedRef }));
|
|
1423
|
+
}
|
|
1424
|
+
//#endregion
|
|
1169
1425
|
//#region src/primitives/tooltip.tsx
|
|
1170
1426
|
const _excluded$15 = [
|
|
1171
1427
|
"children",
|
|
@@ -1176,7 +1432,8 @@ const _excluded2$10 = ["ref", "aria-describedby"];
|
|
|
1176
1432
|
const _excluded3$8 = [
|
|
1177
1433
|
"children",
|
|
1178
1434
|
"onMouseEnter",
|
|
1179
|
-
"onMouseLeave"
|
|
1435
|
+
"onMouseLeave",
|
|
1436
|
+
"render"
|
|
1180
1437
|
];
|
|
1181
1438
|
function mergeAriaDescribedBy(...values) {
|
|
1182
1439
|
const ids = values.flatMap((value) => typeof value === "string" ? value.trim().split(/\s+/) : []);
|
|
@@ -1186,53 +1443,98 @@ function mergeAriaDescribedBy(...values) {
|
|
|
1186
1443
|
const TooltipContext = (0, react.createContext)(null);
|
|
1187
1444
|
function useTooltipContext() {
|
|
1188
1445
|
const ctx = (0, react.useContext)(TooltipContext);
|
|
1189
|
-
if (!ctx) throw new Error("Tooltip components must be used within
|
|
1446
|
+
if (!ctx) throw new Error("Tooltip components must be used within TooltipRoot");
|
|
1190
1447
|
return ctx;
|
|
1191
1448
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1449
|
+
const TooltipGroupContext = (0, react.createContext)(null);
|
|
1450
|
+
/**
|
|
1451
|
+
* Groups sibling tooltips so moving between them does not re-pay the show
|
|
1452
|
+
* delay — the APG/desktop convention for toolbars and icon rows, where waiting
|
|
1453
|
+
* 700ms per button makes the row feel broken.
|
|
1454
|
+
*
|
|
1455
|
+
* Optional: a `TooltipProvider` outside any group keeps its own delay.
|
|
1456
|
+
*/
|
|
1457
|
+
function TooltipGroup({ children, skipDelay = 300 }) {
|
|
1458
|
+
const warmUntilRef = (0, react.useRef)(0);
|
|
1459
|
+
const cooldownRef = (0, react.useRef)(void 0);
|
|
1460
|
+
const value = (0, react.useMemo)(() => ({
|
|
1461
|
+
isWarm: () => skipDelay > 0 && Date.now() < warmUntilRef.current,
|
|
1462
|
+
onOpen: () => {
|
|
1463
|
+
clearTimeout(cooldownRef.current);
|
|
1464
|
+
warmUntilRef.current = 0;
|
|
1465
|
+
},
|
|
1466
|
+
onClose: () => {
|
|
1467
|
+
if (skipDelay <= 0) return;
|
|
1468
|
+
warmUntilRef.current = Date.now() + skipDelay;
|
|
1469
|
+
clearTimeout(cooldownRef.current);
|
|
1470
|
+
cooldownRef.current = setTimeout(() => {
|
|
1471
|
+
warmUntilRef.current = 0;
|
|
1472
|
+
}, skipDelay);
|
|
1473
|
+
}
|
|
1474
|
+
}), [skipDelay]);
|
|
1475
|
+
(0, react.useEffect)(() => () => clearTimeout(cooldownRef.current), []);
|
|
1476
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipGroupContext.Provider, {
|
|
1477
|
+
value,
|
|
1478
|
+
children
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
/**
|
|
1482
|
+
* Owns ONE tooltip: its open state, delays, placement and portal.
|
|
1483
|
+
*
|
|
1484
|
+
* Wrap several of these in a {@link TooltipGroup} to share a skip-delay window.
|
|
1485
|
+
*/
|
|
1486
|
+
function TooltipRoot({ children, timeout, showTimeout = 700, hideTimeout = 300, placement = "top", animated = true, portal = false, portalRoot = null }) {
|
|
1194
1487
|
const [open, setOpen] = (0, react.useState)(false);
|
|
1195
1488
|
const tooltipId = useId();
|
|
1196
1489
|
const showDelay = timeout !== null && timeout !== void 0 ? timeout : showTimeout;
|
|
1197
1490
|
const showTimerRef = (0, react.useRef)(void 0);
|
|
1198
1491
|
const hideTimerRef = (0, react.useRef)(void 0);
|
|
1492
|
+
const group = (0, react.useContext)(TooltipGroupContext);
|
|
1493
|
+
const isKeyboardModality = useKeyboardModality();
|
|
1494
|
+
const clearTimers = (0, react.useCallback)(() => {
|
|
1495
|
+
clearTimeout(showTimerRef.current);
|
|
1496
|
+
clearTimeout(hideTimerRef.current);
|
|
1497
|
+
}, []);
|
|
1199
1498
|
const { getReferenceProps: getFloatRefProps, getFloatingProps } = useFloating({
|
|
1200
1499
|
placement,
|
|
1201
1500
|
gutter: 8,
|
|
1202
|
-
open
|
|
1501
|
+
open,
|
|
1502
|
+
onOpenChange: (0, react.useCallback)((next) => {
|
|
1503
|
+
if (next) return;
|
|
1504
|
+
clearTimers();
|
|
1505
|
+
setOpen(false);
|
|
1506
|
+
}, [clearTimers]),
|
|
1507
|
+
dismiss: {
|
|
1508
|
+
escapeKey: true,
|
|
1509
|
+
outsidePress: false
|
|
1510
|
+
}
|
|
1203
1511
|
});
|
|
1204
1512
|
const show = (0, react.useCallback)(() => {
|
|
1205
1513
|
clearTimeout(hideTimerRef.current);
|
|
1206
|
-
|
|
1207
|
-
|
|
1514
|
+
const delay = (group === null || group === void 0 ? void 0 : group.isWarm()) ? 0 : showDelay;
|
|
1515
|
+
showTimerRef.current = setTimeout(() => {
|
|
1516
|
+
group === null || group === void 0 || group.onOpen();
|
|
1517
|
+
setOpen(true);
|
|
1518
|
+
}, delay);
|
|
1519
|
+
}, [showDelay, group]);
|
|
1208
1520
|
const hide = (0, react.useCallback)(() => {
|
|
1209
1521
|
clearTimeout(showTimerRef.current);
|
|
1210
|
-
hideTimerRef.current = setTimeout(() =>
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
(0, react.useEffect)(() => {
|
|
1219
|
-
if (!open) return;
|
|
1220
|
-
const handler = (e) => {
|
|
1221
|
-
if (e.key === "Escape") {
|
|
1222
|
-
clearTimeout(showTimerRef.current);
|
|
1223
|
-
clearTimeout(hideTimerRef.current);
|
|
1224
|
-
setOpen(false);
|
|
1225
|
-
}
|
|
1226
|
-
};
|
|
1227
|
-
document.addEventListener("keydown", handler);
|
|
1228
|
-
return () => document.removeEventListener("keydown", handler);
|
|
1229
|
-
}, [open]);
|
|
1522
|
+
hideTimerRef.current = setTimeout(() => {
|
|
1523
|
+
setOpen((wasOpen) => {
|
|
1524
|
+
if (wasOpen) group === null || group === void 0 || group.onClose();
|
|
1525
|
+
return false;
|
|
1526
|
+
});
|
|
1527
|
+
}, hideTimeout);
|
|
1528
|
+
}, [hideTimeout, group]);
|
|
1529
|
+
(0, react.useEffect)(() => clearTimers, [clearTimers]);
|
|
1230
1530
|
const getReferenceProps = (0, react.useCallback)(() => {
|
|
1231
1531
|
return _objectSpread2(_objectSpread2({}, getFloatRefProps()), {}, {
|
|
1232
1532
|
"aria-describedby": open ? tooltipId : void 0,
|
|
1233
1533
|
onMouseEnter: show,
|
|
1234
1534
|
onMouseLeave: hide,
|
|
1235
|
-
onFocus:
|
|
1535
|
+
onFocus: (event) => {
|
|
1536
|
+
if (isKeyboardModality(event.currentTarget)) show();
|
|
1537
|
+
},
|
|
1236
1538
|
onBlur: hide
|
|
1237
1539
|
});
|
|
1238
1540
|
}, [
|
|
@@ -1240,24 +1542,46 @@ function TooltipProvider({ children, timeout, showTimeout = 700, hideTimeout = 3
|
|
|
1240
1542
|
open,
|
|
1241
1543
|
tooltipId,
|
|
1242
1544
|
show,
|
|
1243
|
-
hide
|
|
1545
|
+
hide,
|
|
1546
|
+
isKeyboardModality
|
|
1547
|
+
]);
|
|
1548
|
+
const contextValue = (0, react.useMemo)(() => ({
|
|
1549
|
+
open,
|
|
1550
|
+
setOpen,
|
|
1551
|
+
tooltipId,
|
|
1552
|
+
show,
|
|
1553
|
+
hide,
|
|
1554
|
+
animated,
|
|
1555
|
+
portal,
|
|
1556
|
+
portalRoot,
|
|
1557
|
+
getReferenceProps,
|
|
1558
|
+
getFloatingProps
|
|
1559
|
+
}), [
|
|
1560
|
+
open,
|
|
1561
|
+
setOpen,
|
|
1562
|
+
tooltipId,
|
|
1563
|
+
show,
|
|
1564
|
+
hide,
|
|
1565
|
+
animated,
|
|
1566
|
+
portal,
|
|
1567
|
+
portalRoot,
|
|
1568
|
+
getReferenceProps,
|
|
1569
|
+
getFloatingProps
|
|
1244
1570
|
]);
|
|
1245
1571
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipContext.Provider, {
|
|
1246
|
-
value:
|
|
1247
|
-
open,
|
|
1248
|
-
setOpen,
|
|
1249
|
-
tooltipId,
|
|
1250
|
-
show,
|
|
1251
|
-
hide,
|
|
1252
|
-
animated,
|
|
1253
|
-
portal,
|
|
1254
|
-
portalRoot,
|
|
1255
|
-
getReferenceProps,
|
|
1256
|
-
getFloatingProps
|
|
1257
|
-
},
|
|
1572
|
+
value: contextValue,
|
|
1258
1573
|
children
|
|
1259
1574
|
});
|
|
1260
1575
|
}
|
|
1576
|
+
/**
|
|
1577
|
+
* A single tooltip.
|
|
1578
|
+
*
|
|
1579
|
+
* @deprecated Renamed to {@link TooltipRoot}. Despite the name this component
|
|
1580
|
+
* never provided anything to a subtree of tooltips — it IS one tooltip. The
|
|
1581
|
+
* delay-sharing provider is {@link TooltipGroup}. Kept as an alias for
|
|
1582
|
+
* back-compat; scheduled for removal in the next major.
|
|
1583
|
+
*/
|
|
1584
|
+
const TooltipProvider = TooltipRoot;
|
|
1261
1585
|
const TooltipAnchor = (0, react.forwardRef)((_ref, ref) => {
|
|
1262
1586
|
let { children, render, "aria-describedby": ariaDescribedBy } = _ref, props = _objectWithoutProperties(_ref, _excluded$15);
|
|
1263
1587
|
const { getReferenceProps } = useTooltipContext();
|
|
@@ -1280,28 +1604,32 @@ const TooltipAnchor = (0, react.forwardRef)((_ref, ref) => {
|
|
|
1280
1604
|
TooltipAnchor.displayName = "TooltipAnchor";
|
|
1281
1605
|
/** Renders the `Tooltip` component. */
|
|
1282
1606
|
function Tooltip(_ref3) {
|
|
1283
|
-
let { children, onMouseEnter, onMouseLeave } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$8);
|
|
1607
|
+
let { children, onMouseEnter, onMouseLeave, render } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$8);
|
|
1284
1608
|
const { open, tooltipId, show, hide, animated, portal, portalRoot, getFloatingProps } = useTooltipContext();
|
|
1285
1609
|
const { mounted, dataAttributes, ref } = useEnterLeave(open, { animated });
|
|
1286
1610
|
const floatingProps = getFloatingProps();
|
|
1611
|
+
const panelRef = useMergedRef(ref, floatingProps.ref);
|
|
1287
1612
|
if (!mounted) return null;
|
|
1288
|
-
const node =
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1613
|
+
const node = renderElement("div", {
|
|
1614
|
+
render,
|
|
1615
|
+
refs: [panelRef],
|
|
1616
|
+
props: [
|
|
1617
|
+
{
|
|
1618
|
+
id: tooltipId,
|
|
1619
|
+
role: "tooltip",
|
|
1620
|
+
style: floatingProps.style,
|
|
1621
|
+
onMouseEnter: show,
|
|
1622
|
+
onMouseLeave: hide
|
|
1623
|
+
},
|
|
1624
|
+
dataAttributes,
|
|
1625
|
+
{
|
|
1626
|
+
onMouseEnter,
|
|
1627
|
+
onMouseLeave
|
|
1628
|
+
},
|
|
1629
|
+
props,
|
|
1630
|
+
{ children }
|
|
1631
|
+
]
|
|
1632
|
+
});
|
|
1305
1633
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OverlayPortal, {
|
|
1306
1634
|
portal,
|
|
1307
1635
|
portalRoot,
|
|
@@ -1311,7 +1639,7 @@ function Tooltip(_ref3) {
|
|
|
1311
1639
|
//#endregion
|
|
1312
1640
|
//#region src/primitives/popover.tsx
|
|
1313
1641
|
const _excluded$14 = ["onClick"];
|
|
1314
|
-
const _excluded2$9 = ["children"];
|
|
1642
|
+
const _excluded2$9 = ["children", "render"];
|
|
1315
1643
|
const _excluded3$7 = ["onClick"];
|
|
1316
1644
|
const PopoverContext = (0, react.createContext)(null);
|
|
1317
1645
|
function usePopoverContext() {
|
|
@@ -1330,20 +1658,33 @@ function PopoverRoot({ children, open: controlledOpen, defaultOpen = false, onOp
|
|
|
1330
1658
|
onOpenChange: setOpen,
|
|
1331
1659
|
dismiss: true
|
|
1332
1660
|
});
|
|
1661
|
+
const contextValue = (0, react.useMemo)(() => ({
|
|
1662
|
+
open,
|
|
1663
|
+
setOpen,
|
|
1664
|
+
popoverId,
|
|
1665
|
+
manageFocus,
|
|
1666
|
+
animated,
|
|
1667
|
+
portal,
|
|
1668
|
+
portalRoot,
|
|
1669
|
+
getReferenceProps,
|
|
1670
|
+
getFloatingProps,
|
|
1671
|
+
getPositionerStateProps,
|
|
1672
|
+
context
|
|
1673
|
+
}), [
|
|
1674
|
+
open,
|
|
1675
|
+
setOpen,
|
|
1676
|
+
popoverId,
|
|
1677
|
+
manageFocus,
|
|
1678
|
+
animated,
|
|
1679
|
+
portal,
|
|
1680
|
+
portalRoot,
|
|
1681
|
+
getReferenceProps,
|
|
1682
|
+
getFloatingProps,
|
|
1683
|
+
getPositionerStateProps,
|
|
1684
|
+
context
|
|
1685
|
+
]);
|
|
1333
1686
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PopoverContext.Provider, {
|
|
1334
|
-
value:
|
|
1335
|
-
open,
|
|
1336
|
-
setOpen,
|
|
1337
|
-
popoverId,
|
|
1338
|
-
manageFocus,
|
|
1339
|
-
animated,
|
|
1340
|
-
portal,
|
|
1341
|
-
portalRoot,
|
|
1342
|
-
getReferenceProps,
|
|
1343
|
-
getFloatingProps,
|
|
1344
|
-
getPositionerStateProps,
|
|
1345
|
-
context
|
|
1346
|
-
},
|
|
1687
|
+
value: contextValue,
|
|
1347
1688
|
children
|
|
1348
1689
|
});
|
|
1349
1690
|
}
|
|
@@ -1375,21 +1716,28 @@ const PopoverTrigger = (0, react.forwardRef)((_ref, ref) => {
|
|
|
1375
1716
|
PopoverTrigger.displayName = "PopoverTrigger";
|
|
1376
1717
|
/** Renders the `PopoverContent` component. */
|
|
1377
1718
|
function PopoverContent(_ref2) {
|
|
1378
|
-
let { children } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$9);
|
|
1719
|
+
let { children, render } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$9);
|
|
1379
1720
|
const { open, popoverId, manageFocus, animated, portal, portalRoot, getFloatingProps, getPositionerStateProps, context } = usePopoverContext();
|
|
1380
1721
|
const { ref, mounted, dataAttributes } = useEnterLeave(open, { animated });
|
|
1381
1722
|
const floatingProps = getFloatingProps();
|
|
1723
|
+
const panelRef = useMergedRef(ref, floatingProps.ref);
|
|
1382
1724
|
if (!mounted) return null;
|
|
1383
|
-
const node =
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1725
|
+
const node = renderElement("div", {
|
|
1726
|
+
render,
|
|
1727
|
+
refs: [panelRef],
|
|
1728
|
+
props: [
|
|
1729
|
+
{
|
|
1730
|
+
id: popoverId,
|
|
1731
|
+
"data-popover-id": popoverId,
|
|
1732
|
+
tabIndex: -1,
|
|
1733
|
+
style: floatingProps.style
|
|
1734
|
+
},
|
|
1735
|
+
getPositionerStateProps(open),
|
|
1736
|
+
dataAttributes,
|
|
1737
|
+
props,
|
|
1738
|
+
{ children }
|
|
1739
|
+
]
|
|
1740
|
+
});
|
|
1393
1741
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OverlayPortal, {
|
|
1394
1742
|
portal,
|
|
1395
1743
|
portalRoot,
|
|
@@ -1416,144 +1764,245 @@ const PopoverClose = (0, react.forwardRef)((_ref3, ref) => {
|
|
|
1416
1764
|
});
|
|
1417
1765
|
PopoverClose.displayName = "PopoverClose";
|
|
1418
1766
|
//#endregion
|
|
1767
|
+
//#region src/internal/create-store.ts
|
|
1768
|
+
/** Creates a {@link Store} seeded with `initial`. */
|
|
1769
|
+
function createStore(initial) {
|
|
1770
|
+
let state = initial;
|
|
1771
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
1772
|
+
return {
|
|
1773
|
+
getState: () => state,
|
|
1774
|
+
setState: (partial) => {
|
|
1775
|
+
let changed = false;
|
|
1776
|
+
for (const key in partial) if (!Object.is(state[key], partial[key])) {
|
|
1777
|
+
changed = true;
|
|
1778
|
+
break;
|
|
1779
|
+
}
|
|
1780
|
+
if (!changed) return;
|
|
1781
|
+
state = _objectSpread2(_objectSpread2({}, state), partial);
|
|
1782
|
+
for (const listener of listeners) listener();
|
|
1783
|
+
},
|
|
1784
|
+
subscribe: (listener) => {
|
|
1785
|
+
listeners.add(listener);
|
|
1786
|
+
return () => {
|
|
1787
|
+
listeners.delete(listener);
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
/**
|
|
1793
|
+
* Subscribe to a slice of a {@link Store}.
|
|
1794
|
+
*
|
|
1795
|
+
* The selector MUST return a stable value (primitive, or a referentially stable
|
|
1796
|
+
* object) — `useSyncExternalStore` re-renders in a loop otherwise.
|
|
1797
|
+
*/
|
|
1798
|
+
function useStoreSelector(store, selector) {
|
|
1799
|
+
return (0, react.useSyncExternalStore)(store.subscribe, () => selector(store.getState()), () => selector(store.getState()));
|
|
1800
|
+
}
|
|
1801
|
+
//#endregion
|
|
1419
1802
|
//#region src/primitives/select.tsx
|
|
1420
1803
|
const _excluded$13 = [
|
|
1421
1804
|
"onClick",
|
|
1422
1805
|
"onKeyDown",
|
|
1423
1806
|
"children"
|
|
1424
1807
|
];
|
|
1425
|
-
const _excluded2$8 = ["children"];
|
|
1808
|
+
const _excluded2$8 = ["children", "render"];
|
|
1426
1809
|
const _excluded3$6 = [
|
|
1427
1810
|
"value",
|
|
1428
1811
|
"disabled",
|
|
1429
1812
|
"onClick",
|
|
1430
1813
|
"children"
|
|
1431
1814
|
];
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1815
|
+
/** Normalize the raw value (single `string` or multiple `string[]`). */
|
|
1816
|
+
function toValues(value) {
|
|
1817
|
+
if (Array.isArray(value)) return value;
|
|
1818
|
+
return value === "" ? [] : [value];
|
|
1819
|
+
}
|
|
1820
|
+
const SelectStoreContext = (0, react.createContext)(null);
|
|
1821
|
+
function useSelectStoreContext() {
|
|
1822
|
+
const ctx = (0, react.useContext)(SelectStoreContext);
|
|
1823
|
+
if (!ctx) throw new Error("Select components must be used within SelectRoot");
|
|
1824
|
+
return ctx;
|
|
1435
1825
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
if (idx < 0) return delta > 0 ? enabled[0].id : enabled[enabled.length - 1].id;
|
|
1441
|
-
return enabled[Math.min(enabled.length - 1, Math.max(0, idx + delta))].id;
|
|
1826
|
+
/** Subscribe to a slice of select state; re-renders only when it changes. */
|
|
1827
|
+
function useSelectSelector(selector) {
|
|
1828
|
+
const { store } = useSelectStoreContext();
|
|
1829
|
+
return useStoreSelector(store, selector);
|
|
1442
1830
|
}
|
|
1443
|
-
const
|
|
1444
|
-
function
|
|
1445
|
-
const ctx = (0, react.useContext)(
|
|
1831
|
+
const SelectFloatingContext = (0, react.createContext)(null);
|
|
1832
|
+
function useSelectFloating() {
|
|
1833
|
+
const ctx = (0, react.useContext)(SelectFloatingContext);
|
|
1446
1834
|
if (!ctx) throw new Error("Select components must be used within SelectRoot");
|
|
1447
1835
|
return ctx;
|
|
1448
1836
|
}
|
|
1449
1837
|
/** Renders the `SelectRoot` component. */
|
|
1450
|
-
function SelectRoot({ children, value: controlledValue, defaultValue, onValueChange, setValue: setValueDeprecated, multiple = false, name, open: controlledOpen, onOpenChange, setOpen: setOpenDeprecated, animated = true, portal = false, portalRoot = null }) {
|
|
1838
|
+
function SelectRoot({ children, value: controlledValue, defaultValue, onValueChange, setValue: setValueDeprecated, multiple = false, readOnly = false, name, open: controlledOpen, onOpenChange, setOpen: setOpenDeprecated, animated = true, portal = false, portalRoot = null }) {
|
|
1451
1839
|
var _selectedValues$;
|
|
1452
|
-
const [value, setValue] = useControllableState(defaultValue !== null && defaultValue !== void 0 ? defaultValue : multiple ? [] : "", controlledValue, onValueChange !== null && onValueChange !== void 0 ? onValueChange : setValueDeprecated);
|
|
1453
|
-
const [open, setOpenState] = (0, react.useState)(controlledOpen !== null && controlledOpen !== void 0 ? controlledOpen : false);
|
|
1454
|
-
const onOpenChangeCb = onOpenChange !== null && onOpenChange !== void 0 ? onOpenChange : setOpenDeprecated;
|
|
1455
|
-
const [activeId, setActiveId] = (0, react.useState)(null);
|
|
1456
1840
|
const selectId = useId();
|
|
1457
1841
|
const listboxId = `${selectId}-listbox`;
|
|
1458
|
-
const items = (
|
|
1459
|
-
(0, react.
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
}
|
|
1467
|
-
const
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
if (multiple) {
|
|
1471
|
-
const arr = Array.isArray(value) ? value : value ? [value] : [];
|
|
1472
|
-
setValue(arr.includes(v) ? arr.filter((x) => x !== v) : [...arr, v]);
|
|
1473
|
-
} else {
|
|
1474
|
-
setValue(v);
|
|
1475
|
-
setOpen(false);
|
|
1476
|
-
}
|
|
1477
|
-
}, [
|
|
1842
|
+
const { items, registerItem, unregisterItem: removeItem } = useItemRegistry();
|
|
1843
|
+
const [store] = (0, react.useState)(() => {
|
|
1844
|
+
var _ref;
|
|
1845
|
+
return createStore({
|
|
1846
|
+
value: (_ref = controlledValue !== null && controlledValue !== void 0 ? controlledValue : defaultValue) !== null && _ref !== void 0 ? _ref : multiple ? [] : "",
|
|
1847
|
+
activeId: null,
|
|
1848
|
+
open: controlledOpen !== null && controlledOpen !== void 0 ? controlledOpen : false
|
|
1849
|
+
});
|
|
1850
|
+
});
|
|
1851
|
+
const propsRef = (0, react.useRef)({
|
|
1852
|
+
controlledValue,
|
|
1853
|
+
controlledOpen,
|
|
1478
1854
|
multiple,
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1855
|
+
readOnly,
|
|
1856
|
+
onValueChange: onValueChange !== null && onValueChange !== void 0 ? onValueChange : setValueDeprecated,
|
|
1857
|
+
onOpenChange: onOpenChange !== null && onOpenChange !== void 0 ? onOpenChange : setOpenDeprecated
|
|
1858
|
+
});
|
|
1859
|
+
propsRef.current = {
|
|
1860
|
+
controlledValue,
|
|
1861
|
+
controlledOpen,
|
|
1862
|
+
multiple,
|
|
1863
|
+
readOnly,
|
|
1864
|
+
onValueChange: onValueChange !== null && onValueChange !== void 0 ? onValueChange : setValueDeprecated,
|
|
1865
|
+
onOpenChange: onOpenChange !== null && onOpenChange !== void 0 ? onOpenChange : setOpenDeprecated
|
|
1866
|
+
};
|
|
1867
|
+
(0, react.useLayoutEffect)(() => {
|
|
1868
|
+
if (controlledValue !== void 0) store.setState({ value: controlledValue });
|
|
1869
|
+
}, [controlledValue, store]);
|
|
1870
|
+
(0, react.useLayoutEffect)(() => {
|
|
1871
|
+
if (controlledOpen !== void 0) store.setState({ open: controlledOpen });
|
|
1872
|
+
}, [controlledOpen, store]);
|
|
1873
|
+
const actions = (0, react.useMemo)(() => {
|
|
1874
|
+
const setValue = (v) => {
|
|
1875
|
+
var _p$onValueChange;
|
|
1876
|
+
const p = propsRef.current;
|
|
1877
|
+
if (p.controlledValue === void 0) store.setState({ value: v });
|
|
1878
|
+
(_p$onValueChange = p.onValueChange) === null || _p$onValueChange === void 0 || _p$onValueChange.call(p, v);
|
|
1879
|
+
};
|
|
1880
|
+
const setOpen = (v) => {
|
|
1881
|
+
var _p$onOpenChange;
|
|
1882
|
+
const p = propsRef.current;
|
|
1883
|
+
if (p.controlledOpen === void 0) store.setState({ open: v });
|
|
1884
|
+
(_p$onOpenChange = p.onOpenChange) === null || _p$onOpenChange === void 0 || _p$onOpenChange.call(p, v);
|
|
1885
|
+
if (!v) store.setState({ activeId: null });
|
|
1886
|
+
};
|
|
1887
|
+
return {
|
|
1888
|
+
setValue,
|
|
1889
|
+
setOpen,
|
|
1890
|
+
setActiveId: (updater) => {
|
|
1891
|
+
const cur = store.getState().activeId;
|
|
1892
|
+
const next = typeof updater === "function" ? updater(cur) : updater;
|
|
1893
|
+
store.setState({ activeId: next });
|
|
1894
|
+
},
|
|
1895
|
+
selectValue: (v) => {
|
|
1896
|
+
const p = propsRef.current;
|
|
1897
|
+
if (p.readOnly) return;
|
|
1898
|
+
if (p.multiple) {
|
|
1899
|
+
const arr = toValues(store.getState().value);
|
|
1900
|
+
setValue(arr.includes(v) ? arr.filter((x) => x !== v) : [...arr, v]);
|
|
1901
|
+
} else {
|
|
1902
|
+
setValue(v);
|
|
1903
|
+
setOpen(false);
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
};
|
|
1907
|
+
}, [store]);
|
|
1489
1908
|
const unregisterItem = (0, react.useCallback)((id) => {
|
|
1490
|
-
|
|
1491
|
-
|
|
1909
|
+
const removedIndex = removeItem(id);
|
|
1910
|
+
if (store.getState().activeId !== id) return;
|
|
1911
|
+
store.setState({ activeId: nearestEnabledId(items.current, removedIndex) });
|
|
1912
|
+
}, [
|
|
1913
|
+
items,
|
|
1914
|
+
removeItem,
|
|
1915
|
+
store
|
|
1916
|
+
]);
|
|
1917
|
+
const open = useStoreSelector(store, (state) => state.open);
|
|
1918
|
+
const value = useStoreSelector(store, (state) => state.value);
|
|
1919
|
+
const selectedValues = (0, react.useMemo)(() => toValues(value), [value]);
|
|
1492
1920
|
const { getReferenceProps, getFloatingProps } = useFloating({
|
|
1493
1921
|
placement: "bottom-start",
|
|
1494
1922
|
gutter: 4,
|
|
1495
1923
|
sameWidth: true,
|
|
1496
1924
|
open,
|
|
1497
|
-
onOpenChange: setOpen,
|
|
1925
|
+
onOpenChange: actions.setOpen,
|
|
1498
1926
|
dismiss: {
|
|
1499
1927
|
outsidePress: true,
|
|
1500
1928
|
escapeKey: false
|
|
1501
1929
|
}
|
|
1502
1930
|
});
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1931
|
+
const storeContext = (0, react.useMemo)(() => ({
|
|
1932
|
+
store,
|
|
1933
|
+
actions,
|
|
1934
|
+
multiple,
|
|
1935
|
+
readOnly,
|
|
1936
|
+
selectId,
|
|
1937
|
+
listboxId,
|
|
1938
|
+
items,
|
|
1939
|
+
registerItem,
|
|
1940
|
+
unregisterItem
|
|
1941
|
+
}), [
|
|
1942
|
+
store,
|
|
1943
|
+
actions,
|
|
1944
|
+
multiple,
|
|
1945
|
+
readOnly,
|
|
1946
|
+
selectId,
|
|
1947
|
+
listboxId,
|
|
1948
|
+
registerItem,
|
|
1949
|
+
unregisterItem
|
|
1950
|
+
]);
|
|
1951
|
+
const floatingContext = (0, react.useMemo)(() => ({
|
|
1952
|
+
getReferenceProps,
|
|
1953
|
+
getFloatingProps,
|
|
1954
|
+
animated,
|
|
1955
|
+
portal,
|
|
1956
|
+
portalRoot
|
|
1957
|
+
}), [
|
|
1958
|
+
getReferenceProps,
|
|
1959
|
+
getFloatingProps,
|
|
1960
|
+
animated,
|
|
1961
|
+
portal,
|
|
1962
|
+
portalRoot
|
|
1963
|
+
]);
|
|
1964
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SelectStoreContext.Provider, {
|
|
1965
|
+
value: storeContext,
|
|
1966
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(SelectFloatingContext.Provider, {
|
|
1967
|
+
value: floatingContext,
|
|
1968
|
+
children: [children, name && (multiple ? selectedValues.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1969
|
+
type: "hidden",
|
|
1970
|
+
name,
|
|
1971
|
+
value: v
|
|
1972
|
+
}, v)) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1973
|
+
type: "hidden",
|
|
1974
|
+
name,
|
|
1975
|
+
value: (_selectedValues$ = selectedValues[0]) !== null && _selectedValues$ !== void 0 ? _selectedValues$ : ""
|
|
1976
|
+
}))]
|
|
1977
|
+
})
|
|
1534
1978
|
});
|
|
1535
1979
|
}
|
|
1536
1980
|
/** Renders the `SelectLabel` component. */
|
|
1537
1981
|
function SelectLabel(props) {
|
|
1538
|
-
const { selectId } =
|
|
1982
|
+
const { selectId } = useSelectStoreContext();
|
|
1539
1983
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", _objectSpread2({ htmlFor: selectId }, props));
|
|
1540
1984
|
}
|
|
1541
|
-
const SelectTrigger = (0, react.forwardRef)((
|
|
1985
|
+
const SelectTrigger = (0, react.forwardRef)((_ref2, ref) => {
|
|
1542
1986
|
var _selectedValues$2;
|
|
1543
|
-
let { onClick, onKeyDown, children } =
|
|
1544
|
-
const {
|
|
1987
|
+
let { onClick, onKeyDown, children } = _ref2, props = _objectWithoutProperties(_ref2, _excluded$13);
|
|
1988
|
+
const { actions, multiple, readOnly, selectId, listboxId, items, store } = useSelectStoreContext();
|
|
1989
|
+
const { getReferenceProps } = useSelectFloating();
|
|
1990
|
+
const open = useSelectSelector((state) => state.open);
|
|
1991
|
+
const activeId = useSelectSelector((state) => state.activeId);
|
|
1992
|
+
const value = useSelectSelector((state) => state.value);
|
|
1993
|
+
const selectedValues = (0, react.useMemo)(() => toValues(value), [value]);
|
|
1545
1994
|
const refProps = getReferenceProps();
|
|
1546
1995
|
const typeahead = (0, react.useRef)({
|
|
1547
1996
|
buffer: "",
|
|
1548
1997
|
timer: 0
|
|
1549
1998
|
});
|
|
1550
1999
|
const selectActive = (0, react.useCallback)(() => {
|
|
1551
|
-
const item = items.current.find((i) => i.id === activeId);
|
|
1552
|
-
if (item && !item.disabled) selectValue(item.value);
|
|
2000
|
+
const item = items.current.find((i) => i.id === store.getState().activeId);
|
|
2001
|
+
if (item && !item.disabled) actions.selectValue(item.value);
|
|
1553
2002
|
}, [
|
|
1554
2003
|
items,
|
|
1555
|
-
|
|
1556
|
-
|
|
2004
|
+
store,
|
|
2005
|
+
actions
|
|
1557
2006
|
]);
|
|
1558
2007
|
const runTypeahead = (0, react.useCallback)((char) => {
|
|
1559
2008
|
const t = typeahead.current;
|
|
@@ -1566,52 +2015,51 @@ const SelectTrigger = (0, react.forwardRef)((_ref, ref) => {
|
|
|
1566
2015
|
var _document$getElementB;
|
|
1567
2016
|
return (_document$getElementB = document.getElementById(i.id)) === null || _document$getElementB === void 0 || (_document$getElementB = _document$getElementB.textContent) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.trim().toLowerCase().startsWith(t.buffer);
|
|
1568
2017
|
});
|
|
1569
|
-
if (match) setActiveId(match.id);
|
|
1570
|
-
}, [items,
|
|
2018
|
+
if (match) actions.setActiveId(match.id);
|
|
2019
|
+
}, [items, actions]);
|
|
1571
2020
|
const handleClick = (0, react.useCallback)((e) => {
|
|
1572
|
-
setOpen(!open);
|
|
2021
|
+
actions.setOpen(!open);
|
|
1573
2022
|
onClick === null || onClick === void 0 || onClick(e);
|
|
1574
2023
|
}, [
|
|
1575
2024
|
open,
|
|
1576
|
-
|
|
2025
|
+
actions,
|
|
1577
2026
|
onClick
|
|
1578
2027
|
]);
|
|
1579
2028
|
const handleKeyDown = (0, react.useCallback)((e) => {
|
|
2029
|
+
const currentActiveId = store.getState().activeId;
|
|
1580
2030
|
switch (e.key) {
|
|
1581
2031
|
case "ArrowDown":
|
|
1582
2032
|
e.preventDefault();
|
|
1583
|
-
if (!open) setOpen(true);
|
|
1584
|
-
else setActiveId(moveActiveId
|
|
2033
|
+
if (!open) actions.setOpen(true);
|
|
2034
|
+
else actions.setActiveId(moveActiveId(items.current, currentActiveId, 1));
|
|
1585
2035
|
break;
|
|
1586
2036
|
case "ArrowUp":
|
|
1587
2037
|
e.preventDefault();
|
|
1588
|
-
if (!open) setOpen(true);
|
|
1589
|
-
else setActiveId(moveActiveId
|
|
2038
|
+
if (!open) actions.setOpen(true);
|
|
2039
|
+
else actions.setActiveId(moveActiveId(items.current, currentActiveId, -1));
|
|
1590
2040
|
break;
|
|
1591
2041
|
case "Home":
|
|
1592
2042
|
if (open) {
|
|
1593
2043
|
e.preventDefault();
|
|
1594
|
-
setActiveId(firstEnabledId
|
|
2044
|
+
actions.setActiveId(firstEnabledId(items.current));
|
|
1595
2045
|
}
|
|
1596
2046
|
break;
|
|
1597
2047
|
case "End":
|
|
1598
2048
|
if (open) {
|
|
1599
|
-
var _enabled$id, _enabled;
|
|
1600
2049
|
e.preventDefault();
|
|
1601
|
-
|
|
1602
|
-
setActiveId((_enabled$id = (_enabled = enabled[enabled.length - 1]) === null || _enabled === void 0 ? void 0 : _enabled.id) !== null && _enabled$id !== void 0 ? _enabled$id : null);
|
|
2050
|
+
actions.setActiveId(lastEnabledId(items.current));
|
|
1603
2051
|
}
|
|
1604
2052
|
break;
|
|
1605
2053
|
case "Enter":
|
|
1606
2054
|
case " ":
|
|
1607
2055
|
e.preventDefault();
|
|
1608
2056
|
if (open) selectActive();
|
|
1609
|
-
else setOpen(true);
|
|
2057
|
+
else actions.setOpen(true);
|
|
1610
2058
|
break;
|
|
1611
2059
|
case "Escape":
|
|
1612
2060
|
if (open) {
|
|
1613
2061
|
e.preventDefault();
|
|
1614
|
-
setOpen(false);
|
|
2062
|
+
actions.setOpen(false);
|
|
1615
2063
|
}
|
|
1616
2064
|
break;
|
|
1617
2065
|
default: if (open && e.key.length === 1 && e.key !== " " && !e.metaKey && !e.ctrlKey && !e.altKey && !e.nativeEvent.isComposing) runTypeahead(e.key);
|
|
@@ -1620,9 +2068,8 @@ const SelectTrigger = (0, react.forwardRef)((_ref, ref) => {
|
|
|
1620
2068
|
}, [
|
|
1621
2069
|
open,
|
|
1622
2070
|
items,
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
setOpen,
|
|
2071
|
+
store,
|
|
2072
|
+
actions,
|
|
1626
2073
|
selectActive,
|
|
1627
2074
|
runTypeahead,
|
|
1628
2075
|
onKeyDown
|
|
@@ -1640,6 +2087,8 @@ const SelectTrigger = (0, react.forwardRef)((_ref, ref) => {
|
|
|
1640
2087
|
"aria-haspopup": "listbox",
|
|
1641
2088
|
"aria-controls": open ? listboxId : void 0,
|
|
1642
2089
|
"aria-activedescendant": open ? activeId !== null && activeId !== void 0 ? activeId : void 0 : void 0,
|
|
2090
|
+
"aria-readonly": readOnly || void 0,
|
|
2091
|
+
"data-readonly": readOnly ? "" : void 0,
|
|
1643
2092
|
"data-select-trigger": selectId,
|
|
1644
2093
|
onClick: handleClick,
|
|
1645
2094
|
onKeyDown: handleKeyDown
|
|
@@ -1647,38 +2096,50 @@ const SelectTrigger = (0, react.forwardRef)((_ref, ref) => {
|
|
|
1647
2096
|
});
|
|
1648
2097
|
SelectTrigger.displayName = "SelectTrigger";
|
|
1649
2098
|
/** Renders the `SelectPopover` component. */
|
|
1650
|
-
function SelectPopover(
|
|
1651
|
-
let { children } =
|
|
1652
|
-
const {
|
|
2099
|
+
function SelectPopover(_ref3) {
|
|
2100
|
+
let { children, render } = _ref3, props = _objectWithoutProperties(_ref3, _excluded2$8);
|
|
2101
|
+
const { actions, multiple, readOnly, selectId, listboxId, items, store } = useSelectStoreContext();
|
|
2102
|
+
const { getFloatingProps, animated, portal, portalRoot } = useSelectFloating();
|
|
2103
|
+
const open = useSelectSelector((state) => state.open);
|
|
2104
|
+
const activeId = useSelectSelector((state) => state.activeId);
|
|
1653
2105
|
const { ref, mounted, dataAttributes } = useEnterLeave(open, { animated });
|
|
1654
2106
|
const floatingProps = getFloatingProps();
|
|
2107
|
+
const panelRef = useMergedRef(ref, floatingProps.ref);
|
|
1655
2108
|
(0, react.useLayoutEffect)(() => {
|
|
1656
|
-
if (mounted)
|
|
2109
|
+
if (!mounted) return;
|
|
2110
|
+
actions.setActiveId((prev) => {
|
|
1657
2111
|
var _selected$id;
|
|
1658
2112
|
if (prev) return prev;
|
|
2113
|
+
const selectedValues = toValues(store.getState().value);
|
|
1659
2114
|
const selected = items.current.find((i) => selectedValues.includes(i.value));
|
|
1660
|
-
return (_selected$id = selected === null || selected === void 0 ? void 0 : selected.id) !== null && _selected$id !== void 0 ? _selected$id : firstEnabledId
|
|
2115
|
+
return (_selected$id = selected === null || selected === void 0 ? void 0 : selected.id) !== null && _selected$id !== void 0 ? _selected$id : firstEnabledId(items.current);
|
|
1661
2116
|
});
|
|
1662
2117
|
}, [
|
|
1663
2118
|
mounted,
|
|
1664
2119
|
items,
|
|
1665
|
-
|
|
1666
|
-
|
|
2120
|
+
store,
|
|
2121
|
+
actions
|
|
1667
2122
|
]);
|
|
1668
2123
|
useScrollActiveDescendantIntoView(activeId);
|
|
1669
2124
|
if (!mounted) return null;
|
|
1670
|
-
const node =
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
2125
|
+
const node = renderElement("div", {
|
|
2126
|
+
render,
|
|
2127
|
+
refs: [panelRef],
|
|
2128
|
+
props: [
|
|
2129
|
+
{
|
|
2130
|
+
id: listboxId,
|
|
2131
|
+
role: "listbox",
|
|
2132
|
+
"aria-multiselectable": multiple || void 0,
|
|
2133
|
+
"aria-readonly": readOnly || void 0,
|
|
2134
|
+
"aria-activedescendant": activeId !== null && activeId !== void 0 ? activeId : void 0,
|
|
2135
|
+
"data-select-id": selectId,
|
|
2136
|
+
style: floatingProps.style
|
|
2137
|
+
},
|
|
2138
|
+
dataAttributes,
|
|
2139
|
+
props,
|
|
2140
|
+
{ children }
|
|
2141
|
+
]
|
|
2142
|
+
});
|
|
1682
2143
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OverlayPortal, {
|
|
1683
2144
|
portal,
|
|
1684
2145
|
portalRoot,
|
|
@@ -1686,12 +2147,12 @@ function SelectPopover(_ref2) {
|
|
|
1686
2147
|
});
|
|
1687
2148
|
}
|
|
1688
2149
|
/** Renders the `SelectItem` component. */
|
|
1689
|
-
function SelectItem(
|
|
1690
|
-
let { value: itemValue, disabled, onClick, children } =
|
|
1691
|
-
const {
|
|
2150
|
+
function SelectItem(_ref4) {
|
|
2151
|
+
let { value: itemValue, disabled, onClick, children } = _ref4, props = _objectWithoutProperties(_ref4, _excluded3$6);
|
|
2152
|
+
const { actions, registerItem, unregisterItem } = useSelectStoreContext();
|
|
1692
2153
|
const itemId = useId();
|
|
1693
|
-
const isSelected =
|
|
1694
|
-
const isActive = activeId === itemId;
|
|
2154
|
+
const isSelected = useSelectSelector((state) => toValues(state.value).includes(itemValue));
|
|
2155
|
+
const isActive = useSelectSelector((state) => state.activeId === itemId);
|
|
1695
2156
|
(0, react.useLayoutEffect)(() => {
|
|
1696
2157
|
registerItem({
|
|
1697
2158
|
id: itemId,
|
|
@@ -1707,12 +2168,12 @@ function SelectItem(_ref3) {
|
|
|
1707
2168
|
unregisterItem
|
|
1708
2169
|
]);
|
|
1709
2170
|
const handleClick = (0, react.useCallback)((e) => {
|
|
1710
|
-
if (!disabled) selectValue(itemValue);
|
|
2171
|
+
if (!disabled) actions.selectValue(itemValue);
|
|
1711
2172
|
onClick === null || onClick === void 0 || onClick(e);
|
|
1712
2173
|
}, [
|
|
1713
2174
|
disabled,
|
|
1714
2175
|
itemValue,
|
|
1715
|
-
|
|
2176
|
+
actions,
|
|
1716
2177
|
onClick
|
|
1717
2178
|
]);
|
|
1718
2179
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", _objectSpread2(_objectSpread2({
|
|
@@ -1724,14 +2185,14 @@ function SelectItem(_ref3) {
|
|
|
1724
2185
|
"data-disabled": disabled ? "" : void 0,
|
|
1725
2186
|
onClick: handleClick,
|
|
1726
2187
|
onMouseEnter: () => {
|
|
1727
|
-
if (!disabled) setActiveId(itemId);
|
|
2188
|
+
if (!disabled) actions.setActiveId(itemId);
|
|
1728
2189
|
}
|
|
1729
2190
|
}, props), {}, { children: children !== null && children !== void 0 ? children : itemValue }));
|
|
1730
2191
|
}
|
|
1731
2192
|
//#endregion
|
|
1732
2193
|
//#region src/primitives/combobox.tsx
|
|
1733
2194
|
const _excluded$12 = ["onKeyDown"];
|
|
1734
|
-
const _excluded2$7 = ["children"];
|
|
2195
|
+
const _excluded2$7 = ["children", "render"];
|
|
1735
2196
|
const _excluded3$5 = [
|
|
1736
2197
|
"value",
|
|
1737
2198
|
"disabled",
|
|
@@ -1739,36 +2200,6 @@ const _excluded3$5 = [
|
|
|
1739
2200
|
"children"
|
|
1740
2201
|
];
|
|
1741
2202
|
const _excluded4$3 = ["children"];
|
|
1742
|
-
function firstEnabledId$3(items) {
|
|
1743
|
-
var _items$find$id, _items$find;
|
|
1744
|
-
return (_items$find$id = (_items$find = items.find((i) => !i.disabled)) === null || _items$find === void 0 ? void 0 : _items$find.id) !== null && _items$find$id !== void 0 ? _items$find$id : null;
|
|
1745
|
-
}
|
|
1746
|
-
function moveActiveId$3(items, activeId, delta) {
|
|
1747
|
-
const enabled = items.filter((i) => !i.disabled);
|
|
1748
|
-
if (enabled.length === 0) return null;
|
|
1749
|
-
const idx = enabled.findIndex((i) => i.id === activeId);
|
|
1750
|
-
if (idx < 0) return delta > 0 ? enabled[0].id : enabled[enabled.length - 1].id;
|
|
1751
|
-
return enabled[Math.min(enabled.length - 1, Math.max(0, idx + delta))].id;
|
|
1752
|
-
}
|
|
1753
|
-
function createComboboxStore(initial) {
|
|
1754
|
-
let state = initial;
|
|
1755
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
1756
|
-
return {
|
|
1757
|
-
getState: () => state,
|
|
1758
|
-
setState: (partial) => {
|
|
1759
|
-
const next = _objectSpread2(_objectSpread2({}, state), partial);
|
|
1760
|
-
if (next.value === state.value && next.searchValue === state.searchValue && next.activeId === state.activeId && next.open === state.open) return;
|
|
1761
|
-
state = next;
|
|
1762
|
-
listeners.forEach((l) => l());
|
|
1763
|
-
},
|
|
1764
|
-
subscribe: (listener) => {
|
|
1765
|
-
listeners.add(listener);
|
|
1766
|
-
return () => {
|
|
1767
|
-
listeners.delete(listener);
|
|
1768
|
-
};
|
|
1769
|
-
}
|
|
1770
|
-
};
|
|
1771
|
-
}
|
|
1772
2203
|
const ComboboxStoreContext = (0, react.createContext)(null);
|
|
1773
2204
|
function useComboboxStoreContext() {
|
|
1774
2205
|
const ctx = (0, react.useContext)(ComboboxStoreContext);
|
|
@@ -1778,7 +2209,7 @@ function useComboboxStoreContext() {
|
|
|
1778
2209
|
/** Subscribe to a slice of combobox state; re-renders only when it changes. */
|
|
1779
2210
|
function useComboboxSelector(selector) {
|
|
1780
2211
|
const { store } = useComboboxStoreContext();
|
|
1781
|
-
return (
|
|
2212
|
+
return useStoreSelector(store, selector);
|
|
1782
2213
|
}
|
|
1783
2214
|
const ComboboxFloatingContext = (0, react.createContext)(null);
|
|
1784
2215
|
function useComboboxFloating() {
|
|
@@ -1787,11 +2218,11 @@ function useComboboxFloating() {
|
|
|
1787
2218
|
return ctx;
|
|
1788
2219
|
}
|
|
1789
2220
|
/** Renders the `ComboboxRoot` component. */
|
|
1790
|
-
function ComboboxRoot({ children, value: controlledValue, defaultValue = "", onValueChange, setValue: setValueDeprecated, open: controlledOpen, onOpenChange, setOpen: setOpenDeprecated, animated = true, portal = false, portalRoot = null }) {
|
|
2221
|
+
function ComboboxRoot({ children, value: controlledValue, defaultValue = "", onValueChange, setValue: setValueDeprecated, readOnly = false, open: controlledOpen, onOpenChange, setOpen: setOpenDeprecated, animated = true, portal = false, portalRoot = null }) {
|
|
1791
2222
|
const comboboxId = useId();
|
|
1792
2223
|
const listboxId = `${comboboxId}-listbox`;
|
|
1793
|
-
const items = (
|
|
1794
|
-
const [store] = (0, react.useState)(() =>
|
|
2224
|
+
const { items, registerItem, unregisterItem: removeItem } = useItemRegistry();
|
|
2225
|
+
const [store] = (0, react.useState)(() => createStore({
|
|
1795
2226
|
value: controlledValue !== null && controlledValue !== void 0 ? controlledValue : defaultValue,
|
|
1796
2227
|
searchValue: "",
|
|
1797
2228
|
activeId: null,
|
|
@@ -1809,10 +2240,10 @@ function ComboboxRoot({ children, value: controlledValue, defaultValue = "", onV
|
|
|
1809
2240
|
onValueChange: onValueChange !== null && onValueChange !== void 0 ? onValueChange : setValueDeprecated,
|
|
1810
2241
|
onOpenChange: onOpenChange !== null && onOpenChange !== void 0 ? onOpenChange : setOpenDeprecated
|
|
1811
2242
|
};
|
|
1812
|
-
(0, react.
|
|
2243
|
+
(0, react.useLayoutEffect)(() => {
|
|
1813
2244
|
if (controlledValue !== void 0) store.setState({ value: controlledValue });
|
|
1814
2245
|
}, [controlledValue, store]);
|
|
1815
|
-
(0, react.
|
|
2246
|
+
(0, react.useLayoutEffect)(() => {
|
|
1816
2247
|
if (controlledOpen !== void 0) store.setState({ open: controlledOpen });
|
|
1817
2248
|
}, [controlledOpen, store]);
|
|
1818
2249
|
const actions = (0, react.useMemo)(() => ({
|
|
@@ -1836,21 +2267,21 @@ function ComboboxRoot({ children, value: controlledValue, defaultValue = "", onV
|
|
|
1836
2267
|
store.setState({ activeId: next });
|
|
1837
2268
|
}
|
|
1838
2269
|
}), [store]);
|
|
1839
|
-
const registerItem = (0, react.useCallback)((entry) => {
|
|
1840
|
-
const list = items.current;
|
|
1841
|
-
const existing = list.findIndex((i) => i.id === entry.id);
|
|
1842
|
-
if (existing >= 0) list[existing] = entry;
|
|
1843
|
-
else list.push(entry);
|
|
1844
|
-
}, []);
|
|
1845
2270
|
const unregisterItem = (0, react.useCallback)((id) => {
|
|
1846
|
-
|
|
1847
|
-
|
|
2271
|
+
const removedIndex = removeItem(id);
|
|
2272
|
+
if (store.getState().activeId !== id) return;
|
|
2273
|
+
store.setState({ activeId: nearestEnabledId(items.current, removedIndex) });
|
|
2274
|
+
}, [
|
|
2275
|
+
items,
|
|
2276
|
+
removeItem,
|
|
2277
|
+
store
|
|
2278
|
+
]);
|
|
1848
2279
|
const { getReferenceProps, getFloatingProps } = useFloating({
|
|
1849
2280
|
placement: "bottom-start",
|
|
1850
2281
|
gutter: 4,
|
|
1851
2282
|
sameWidth: true,
|
|
1852
2283
|
lazyFlip: true,
|
|
1853
|
-
open: (
|
|
2284
|
+
open: useStoreSelector(store, (state) => state.open),
|
|
1854
2285
|
onOpenChange: actions.setOpen,
|
|
1855
2286
|
dismiss: {
|
|
1856
2287
|
outsidePress: true,
|
|
@@ -1860,6 +2291,7 @@ function ComboboxRoot({ children, value: controlledValue, defaultValue = "", onV
|
|
|
1860
2291
|
const storeContext = (0, react.useMemo)(() => ({
|
|
1861
2292
|
store,
|
|
1862
2293
|
actions,
|
|
2294
|
+
readOnly,
|
|
1863
2295
|
comboboxId,
|
|
1864
2296
|
listboxId,
|
|
1865
2297
|
items,
|
|
@@ -1868,6 +2300,7 @@ function ComboboxRoot({ children, value: controlledValue, defaultValue = "", onV
|
|
|
1868
2300
|
}), [
|
|
1869
2301
|
store,
|
|
1870
2302
|
actions,
|
|
2303
|
+
readOnly,
|
|
1871
2304
|
comboboxId,
|
|
1872
2305
|
listboxId,
|
|
1873
2306
|
registerItem,
|
|
@@ -1896,7 +2329,7 @@ function ComboboxRoot({ children, value: controlledValue, defaultValue = "", onV
|
|
|
1896
2329
|
}
|
|
1897
2330
|
const ComboboxInput = (0, react.forwardRef)((_ref, ref) => {
|
|
1898
2331
|
let { onKeyDown } = _ref, props = _objectWithoutProperties(_ref, _excluded$12);
|
|
1899
|
-
const { actions, comboboxId, listboxId, items } = useComboboxStoreContext();
|
|
2332
|
+
const { actions, readOnly, comboboxId, listboxId, items } = useComboboxStoreContext();
|
|
1900
2333
|
const { getReferenceProps } = useComboboxFloating();
|
|
1901
2334
|
const open = useComboboxSelector((s) => s.open);
|
|
1902
2335
|
const searchValue = useComboboxSelector((s) => s.searchValue);
|
|
@@ -1909,6 +2342,7 @@ const ComboboxInput = (0, react.forwardRef)((_ref, ref) => {
|
|
|
1909
2342
|
actions.setActiveId(null);
|
|
1910
2343
|
}, [actions, open]);
|
|
1911
2344
|
const selectActive = (0, react.useCallback)(() => {
|
|
2345
|
+
if (readOnly) return;
|
|
1912
2346
|
const item = items.current.find((i) => i.id === activeId);
|
|
1913
2347
|
if (item && !item.disabled) {
|
|
1914
2348
|
actions.setValue(item.value);
|
|
@@ -1918,7 +2352,8 @@ const ComboboxInput = (0, react.forwardRef)((_ref, ref) => {
|
|
|
1918
2352
|
}, [
|
|
1919
2353
|
items,
|
|
1920
2354
|
activeId,
|
|
1921
|
-
actions
|
|
2355
|
+
actions,
|
|
2356
|
+
readOnly
|
|
1922
2357
|
]);
|
|
1923
2358
|
const handleKeyDown = (0, react.useCallback)((e) => {
|
|
1924
2359
|
if (e.nativeEvent.isComposing) {
|
|
@@ -1929,12 +2364,12 @@ const ComboboxInput = (0, react.forwardRef)((_ref, ref) => {
|
|
|
1929
2364
|
case "ArrowDown":
|
|
1930
2365
|
e.preventDefault();
|
|
1931
2366
|
if (!open) actions.setOpen(true);
|
|
1932
|
-
actions.setActiveId(moveActiveId
|
|
2367
|
+
actions.setActiveId(moveActiveId(items.current, activeId, 1));
|
|
1933
2368
|
break;
|
|
1934
2369
|
case "ArrowUp":
|
|
1935
2370
|
e.preventDefault();
|
|
1936
2371
|
if (!open) actions.setOpen(true);
|
|
1937
|
-
actions.setActiveId(moveActiveId
|
|
2372
|
+
actions.setActiveId(moveActiveId(items.current, activeId, -1));
|
|
1938
2373
|
break;
|
|
1939
2374
|
case "Enter":
|
|
1940
2375
|
if (open && activeId) {
|
|
@@ -1969,6 +2404,9 @@ const ComboboxInput = (0, react.forwardRef)((_ref, ref) => {
|
|
|
1969
2404
|
"aria-autocomplete": "list",
|
|
1970
2405
|
"aria-controls": open ? listboxId : void 0,
|
|
1971
2406
|
"aria-activedescendant": open ? activeId !== null && activeId !== void 0 ? activeId : void 0 : void 0,
|
|
2407
|
+
"aria-readonly": readOnly || void 0,
|
|
2408
|
+
readOnly,
|
|
2409
|
+
"data-readonly": readOnly ? "" : void 0,
|
|
1972
2410
|
"data-combobox-input": comboboxId,
|
|
1973
2411
|
value: searchValue,
|
|
1974
2412
|
onChange: handleChange,
|
|
@@ -1978,29 +2416,35 @@ const ComboboxInput = (0, react.forwardRef)((_ref, ref) => {
|
|
|
1978
2416
|
ComboboxInput.displayName = "ComboboxInput";
|
|
1979
2417
|
/** Renders the `ComboboxPopover` component. */
|
|
1980
2418
|
function ComboboxPopover(_ref2) {
|
|
1981
|
-
let { children } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$7);
|
|
2419
|
+
let { children, render } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$7);
|
|
1982
2420
|
const { actions, comboboxId, listboxId, items } = useComboboxStoreContext();
|
|
1983
2421
|
const { getFloatingProps, animated, portal, portalRoot } = useComboboxFloating();
|
|
1984
2422
|
const { ref, mounted, dataAttributes } = useEnterLeave(useComboboxSelector((s) => s.open), { animated });
|
|
1985
2423
|
const floatingProps = getFloatingProps();
|
|
2424
|
+
const panelRef = useMergedRef(ref, floatingProps.ref);
|
|
1986
2425
|
(0, react.useLayoutEffect)(() => {
|
|
1987
|
-
if (mounted) actions.setActiveId((prev) => prev !== null && prev !== void 0 ? prev : firstEnabledId
|
|
2426
|
+
if (mounted) actions.setActiveId((prev) => prev !== null && prev !== void 0 ? prev : firstEnabledId(items.current));
|
|
1988
2427
|
}, [
|
|
1989
2428
|
mounted,
|
|
1990
2429
|
items,
|
|
1991
2430
|
actions
|
|
1992
2431
|
]);
|
|
1993
2432
|
if (!mounted) return null;
|
|
1994
|
-
const node =
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2433
|
+
const node = renderElement("div", {
|
|
2434
|
+
render,
|
|
2435
|
+
refs: [panelRef],
|
|
2436
|
+
props: [
|
|
2437
|
+
{
|
|
2438
|
+
id: listboxId,
|
|
2439
|
+
role: "listbox",
|
|
2440
|
+
"data-combobox-id": comboboxId,
|
|
2441
|
+
style: floatingProps.style
|
|
2442
|
+
},
|
|
2443
|
+
dataAttributes,
|
|
2444
|
+
props,
|
|
2445
|
+
{ children }
|
|
2446
|
+
]
|
|
2447
|
+
});
|
|
2004
2448
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OverlayPortal, {
|
|
2005
2449
|
portal,
|
|
2006
2450
|
portalRoot,
|
|
@@ -2010,7 +2454,7 @@ function ComboboxPopover(_ref2) {
|
|
|
2010
2454
|
/** Renders the `ComboboxItem` component. */
|
|
2011
2455
|
function ComboboxItem(_ref3) {
|
|
2012
2456
|
let { value: itemValue, disabled, onClick, children } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$5);
|
|
2013
|
-
const { actions, registerItem, unregisterItem } = useComboboxStoreContext();
|
|
2457
|
+
const { actions, readOnly, registerItem, unregisterItem } = useComboboxStoreContext();
|
|
2014
2458
|
const itemId = useId();
|
|
2015
2459
|
const isSelected = useComboboxSelector((s) => s.value === itemValue);
|
|
2016
2460
|
const isActive = useComboboxSelector((s) => s.activeId === itemId);
|
|
@@ -2029,7 +2473,7 @@ function ComboboxItem(_ref3) {
|
|
|
2029
2473
|
unregisterItem
|
|
2030
2474
|
]);
|
|
2031
2475
|
const handleClick = (0, react.useCallback)((e) => {
|
|
2032
|
-
if (!disabled) {
|
|
2476
|
+
if (!disabled && !readOnly) {
|
|
2033
2477
|
actions.setValue(itemValue);
|
|
2034
2478
|
actions.setSearchValue(itemValue);
|
|
2035
2479
|
actions.setOpen(false);
|
|
@@ -2037,6 +2481,7 @@ function ComboboxItem(_ref3) {
|
|
|
2037
2481
|
onClick === null || onClick === void 0 || onClick(e);
|
|
2038
2482
|
}, [
|
|
2039
2483
|
disabled,
|
|
2484
|
+
readOnly,
|
|
2040
2485
|
itemValue,
|
|
2041
2486
|
actions,
|
|
2042
2487
|
onClick
|
|
@@ -2308,10 +2753,18 @@ function CommandGroup(_ref5) {
|
|
|
2308
2753
|
children
|
|
2309
2754
|
})] }));
|
|
2310
2755
|
}
|
|
2311
|
-
/**
|
|
2756
|
+
/**
|
|
2757
|
+
* Renders the `CommandSeparator` component.
|
|
2758
|
+
*
|
|
2759
|
+
* Rendered with `role="presentation"`: the separator is a child of
|
|
2760
|
+
* `CommandList` (`role="listbox"`), whose only permitted children are `option`
|
|
2761
|
+
* and `group`. A real `role="separator"` there fails
|
|
2762
|
+
* `aria-required-children` and corrupts the option count announced by screen
|
|
2763
|
+
* readers. (Menu separators keep `role="separator"` — `menu` permits it.)
|
|
2764
|
+
*/
|
|
2312
2765
|
function CommandSeparator(props) {
|
|
2313
2766
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", _objectSpread2({
|
|
2314
|
-
role: "
|
|
2767
|
+
role: "presentation",
|
|
2315
2768
|
"data-slot": "command-separator"
|
|
2316
2769
|
}, props));
|
|
2317
2770
|
}
|
|
@@ -2394,7 +2847,11 @@ const _excluded2$5 = [
|
|
|
2394
2847
|
"onKeyDown",
|
|
2395
2848
|
"role"
|
|
2396
2849
|
];
|
|
2397
|
-
const _excluded3$3 = [
|
|
2850
|
+
const _excluded3$3 = [
|
|
2851
|
+
"children",
|
|
2852
|
+
"onKeyDown",
|
|
2853
|
+
"render"
|
|
2854
|
+
];
|
|
2398
2855
|
const _excluded4$1 = [
|
|
2399
2856
|
"disabled",
|
|
2400
2857
|
"hideOnClick",
|
|
@@ -2415,19 +2872,6 @@ const _excluded6$1 = [
|
|
|
2415
2872
|
"onClick",
|
|
2416
2873
|
"children"
|
|
2417
2874
|
];
|
|
2418
|
-
/** First enabled item id, or null. */
|
|
2419
|
-
function firstEnabledId$2(items) {
|
|
2420
|
-
var _items$find$id, _items$find;
|
|
2421
|
-
return (_items$find$id = (_items$find = items.find((i) => !i.disabled)) === null || _items$find === void 0 ? void 0 : _items$find.id) !== null && _items$find$id !== void 0 ? _items$find$id : null;
|
|
2422
|
-
}
|
|
2423
|
-
/** Move the active id by `delta` over the enabled items (clamped, no wrap). */
|
|
2424
|
-
function moveActiveId$2(items, activeId, delta) {
|
|
2425
|
-
const enabled = items.filter((i) => !i.disabled);
|
|
2426
|
-
if (enabled.length === 0) return null;
|
|
2427
|
-
const idx = enabled.findIndex((i) => i.id === activeId);
|
|
2428
|
-
if (idx < 0) return delta > 0 ? enabled[0].id : enabled[enabled.length - 1].id;
|
|
2429
|
-
return enabled[Math.min(enabled.length - 1, Math.max(0, idx + delta))].id;
|
|
2430
|
-
}
|
|
2431
2875
|
const MenuContext = (0, react.createContext)(null);
|
|
2432
2876
|
function useMenuContext() {
|
|
2433
2877
|
const ctx = (0, react.useContext)(MenuContext);
|
|
@@ -2478,20 +2922,19 @@ function MenubarContainer(_ref) {
|
|
|
2478
2922
|
}
|
|
2479
2923
|
/** Renders the `MenuRoot` component. */
|
|
2480
2924
|
function MenuRoot({ children, open: controlledOpen, onOpenChange, setOpen: setOpenDeprecated, animated = true, portal = false, portalRoot = null }) {
|
|
2481
|
-
const [open, setOpenState] = (
|
|
2925
|
+
const [open, setOpenState] = useControllableState(false, controlledOpen, onOpenChange !== null && onOpenChange !== void 0 ? onOpenChange : setOpenDeprecated);
|
|
2482
2926
|
const [activeId, setActiveId] = (0, react.useState)(null);
|
|
2483
2927
|
const menuId = useId();
|
|
2484
2928
|
const triggerId = `${menuId}-trigger`;
|
|
2485
|
-
const items
|
|
2486
|
-
const
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
}, [
|
|
2929
|
+
const { items, registerItem: registerItemEntry, unregisterItem: removeItem } = useItemRegistry();
|
|
2930
|
+
const registerItem = (0, react.useCallback)((id, disabled) => registerItemEntry({
|
|
2931
|
+
id,
|
|
2932
|
+
disabled
|
|
2933
|
+
}), [registerItemEntry]);
|
|
2490
2934
|
const setOpen = (0, react.useCallback)((v) => {
|
|
2491
|
-
|
|
2492
|
-
onOpenChangeCb === null || onOpenChangeCb === void 0 || onOpenChangeCb(v);
|
|
2935
|
+
setOpenState(v);
|
|
2493
2936
|
if (!v) setActiveId(null);
|
|
2494
|
-
}, [
|
|
2937
|
+
}, [setOpenState]);
|
|
2495
2938
|
const focusTrigger = (0, react.useCallback)(() => {
|
|
2496
2939
|
var _document$getElementB;
|
|
2497
2940
|
(_document$getElementB = document.getElementById(triggerId)) === null || _document$getElementB === void 0 || _document$getElementB.focus();
|
|
@@ -2506,39 +2949,45 @@ function MenuRoot({ children, open: controlledOpen, onOpenChange, setOpen: setOp
|
|
|
2506
2949
|
escapeKey: false
|
|
2507
2950
|
}
|
|
2508
2951
|
});
|
|
2509
|
-
const registerItem = (0, react.useCallback)((id, disabled) => {
|
|
2510
|
-
const list = items.current;
|
|
2511
|
-
const existing = list.findIndex((i) => i.id === id);
|
|
2512
|
-
if (existing >= 0) list[existing] = {
|
|
2513
|
-
id,
|
|
2514
|
-
disabled
|
|
2515
|
-
};
|
|
2516
|
-
else list.push({
|
|
2517
|
-
id,
|
|
2518
|
-
disabled
|
|
2519
|
-
});
|
|
2520
|
-
}, []);
|
|
2521
2952
|
const unregisterItem = (0, react.useCallback)((id) => {
|
|
2522
|
-
|
|
2523
|
-
|
|
2953
|
+
const removedIndex = removeItem(id);
|
|
2954
|
+
setActiveId((prev) => prev === id ? nearestEnabledId(items.current, removedIndex) : prev);
|
|
2955
|
+
}, [items, removeItem]);
|
|
2956
|
+
const contextValue = (0, react.useMemo)(() => ({
|
|
2957
|
+
open,
|
|
2958
|
+
setOpen,
|
|
2959
|
+
menuId,
|
|
2960
|
+
triggerId,
|
|
2961
|
+
getReferenceProps,
|
|
2962
|
+
getFloatingProps,
|
|
2963
|
+
activeId,
|
|
2964
|
+
setActiveId,
|
|
2965
|
+
items,
|
|
2966
|
+
registerItem,
|
|
2967
|
+
unregisterItem,
|
|
2968
|
+
focusTrigger,
|
|
2969
|
+
animated,
|
|
2970
|
+
portal,
|
|
2971
|
+
portalRoot
|
|
2972
|
+
}), [
|
|
2973
|
+
open,
|
|
2974
|
+
setOpen,
|
|
2975
|
+
menuId,
|
|
2976
|
+
triggerId,
|
|
2977
|
+
getReferenceProps,
|
|
2978
|
+
getFloatingProps,
|
|
2979
|
+
activeId,
|
|
2980
|
+
setActiveId,
|
|
2981
|
+
items,
|
|
2982
|
+
registerItem,
|
|
2983
|
+
unregisterItem,
|
|
2984
|
+
focusTrigger,
|
|
2985
|
+
animated,
|
|
2986
|
+
portal,
|
|
2987
|
+
portalRoot
|
|
2988
|
+
]);
|
|
2524
2989
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuContext.Provider, {
|
|
2525
|
-
value:
|
|
2526
|
-
open,
|
|
2527
|
-
setOpen,
|
|
2528
|
-
menuId,
|
|
2529
|
-
triggerId,
|
|
2530
|
-
getReferenceProps,
|
|
2531
|
-
getFloatingProps,
|
|
2532
|
-
activeId,
|
|
2533
|
-
setActiveId,
|
|
2534
|
-
items,
|
|
2535
|
-
registerItem,
|
|
2536
|
-
unregisterItem,
|
|
2537
|
-
focusTrigger,
|
|
2538
|
-
animated,
|
|
2539
|
-
portal,
|
|
2540
|
-
portalRoot
|
|
2541
|
-
},
|
|
2990
|
+
value: contextValue,
|
|
2542
2991
|
children
|
|
2543
2992
|
});
|
|
2544
2993
|
}
|
|
@@ -2582,11 +3031,12 @@ const MenuTrigger = (0, react.forwardRef)((_ref2, ref) => {
|
|
|
2582
3031
|
MenuTrigger.displayName = "MenuTrigger";
|
|
2583
3032
|
/** Renders the `MenuPopover` component. */
|
|
2584
3033
|
function MenuPopover(_ref3) {
|
|
2585
|
-
let { children, onKeyDown } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$3);
|
|
3034
|
+
let { children, onKeyDown, render } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$3);
|
|
2586
3035
|
const { open, setOpen, menuId, triggerId, getFloatingProps, items, activeId, setActiveId, focusTrigger, animated, portal, portalRoot } = useMenuContext();
|
|
2587
3036
|
const { ref, mounted, dataAttributes } = useEnterLeave(open, { animated });
|
|
2588
3037
|
const floatingProps = getFloatingProps();
|
|
2589
3038
|
const menuRef = (0, react.useRef)(null);
|
|
3039
|
+
const panelRef = useMergedRef(menuRef, ref, floatingProps.ref);
|
|
2590
3040
|
const typeahead = (0, react.useRef)({
|
|
2591
3041
|
buffer: "",
|
|
2592
3042
|
timer: 0
|
|
@@ -2612,23 +3062,20 @@ function MenuPopover(_ref3) {
|
|
|
2612
3062
|
switch (e.key) {
|
|
2613
3063
|
case "ArrowDown":
|
|
2614
3064
|
e.preventDefault();
|
|
2615
|
-
setActiveId(moveActiveId
|
|
3065
|
+
setActiveId(moveActiveId(items.current, activeId, 1));
|
|
2616
3066
|
break;
|
|
2617
3067
|
case "ArrowUp":
|
|
2618
3068
|
e.preventDefault();
|
|
2619
|
-
setActiveId(moveActiveId
|
|
3069
|
+
setActiveId(moveActiveId(items.current, activeId, -1));
|
|
2620
3070
|
break;
|
|
2621
3071
|
case "Home":
|
|
2622
3072
|
e.preventDefault();
|
|
2623
|
-
setActiveId(firstEnabledId
|
|
3073
|
+
setActiveId(firstEnabledId(items.current));
|
|
2624
3074
|
break;
|
|
2625
|
-
case "End":
|
|
2626
|
-
var _enabled$id, _enabled;
|
|
3075
|
+
case "End":
|
|
2627
3076
|
e.preventDefault();
|
|
2628
|
-
|
|
2629
|
-
setActiveId((_enabled$id = (_enabled = enabled[enabled.length - 1]) === null || _enabled === void 0 ? void 0 : _enabled.id) !== null && _enabled$id !== void 0 ? _enabled$id : null);
|
|
3077
|
+
setActiveId(lastEnabledId(items.current));
|
|
2630
3078
|
break;
|
|
2631
|
-
}
|
|
2632
3079
|
case "Enter":
|
|
2633
3080
|
case " ":
|
|
2634
3081
|
e.preventDefault();
|
|
@@ -2659,7 +3106,7 @@ function MenuPopover(_ref3) {
|
|
|
2659
3106
|
if (mounted) {
|
|
2660
3107
|
var _menuRef$current;
|
|
2661
3108
|
(_menuRef$current = menuRef.current) === null || _menuRef$current === void 0 || _menuRef$current.focus();
|
|
2662
|
-
setActiveId((prev) => prev !== null && prev !== void 0 ? prev : firstEnabledId
|
|
3109
|
+
setActiveId((prev) => prev !== null && prev !== void 0 ? prev : firstEnabledId(items.current));
|
|
2663
3110
|
}
|
|
2664
3111
|
}, [
|
|
2665
3112
|
mounted,
|
|
@@ -2668,21 +3115,25 @@ function MenuPopover(_ref3) {
|
|
|
2668
3115
|
]);
|
|
2669
3116
|
useScrollActiveDescendantIntoView(activeId);
|
|
2670
3117
|
if (!mounted) return null;
|
|
2671
|
-
const node =
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
3118
|
+
const node = renderElement("div", {
|
|
3119
|
+
render,
|
|
3120
|
+
refs: [panelRef],
|
|
3121
|
+
props: [
|
|
3122
|
+
{
|
|
3123
|
+
id: menuId,
|
|
3124
|
+
role: "menu",
|
|
3125
|
+
"aria-labelledby": triggerId,
|
|
3126
|
+
"aria-activedescendant": activeId !== null && activeId !== void 0 ? activeId : void 0,
|
|
3127
|
+
"data-menu-id": menuId,
|
|
3128
|
+
style: floatingProps.style,
|
|
3129
|
+
tabIndex: -1,
|
|
3130
|
+
onKeyDown: handleKeyDown
|
|
3131
|
+
},
|
|
3132
|
+
dataAttributes,
|
|
3133
|
+
props,
|
|
3134
|
+
{ children }
|
|
3135
|
+
]
|
|
3136
|
+
});
|
|
2686
3137
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OverlayPortal, {
|
|
2687
3138
|
portal,
|
|
2688
3139
|
portalRoot,
|
|
@@ -2801,17 +3252,6 @@ function MenuButtonArrow(props) {
|
|
|
2801
3252
|
//#region src/primitives/toolbar.tsx
|
|
2802
3253
|
const _excluded$9 = ["onKeyDown"];
|
|
2803
3254
|
const _excluded2$4 = ["disabled", "onFocus"];
|
|
2804
|
-
function firstEnabledId$1(items) {
|
|
2805
|
-
var _items$find$id, _items$find;
|
|
2806
|
-
return (_items$find$id = (_items$find = items.find((i) => !i.disabled)) === null || _items$find === void 0 ? void 0 : _items$find.id) !== null && _items$find$id !== void 0 ? _items$find$id : null;
|
|
2807
|
-
}
|
|
2808
|
-
function moveActiveId$1(items, activeId, delta) {
|
|
2809
|
-
const enabled = items.filter((i) => !i.disabled);
|
|
2810
|
-
if (enabled.length === 0) return null;
|
|
2811
|
-
const idx = enabled.findIndex((i) => i.id === activeId);
|
|
2812
|
-
if (idx < 0) return delta > 0 ? enabled[0].id : enabled[enabled.length - 1].id;
|
|
2813
|
-
return enabled[Math.min(enabled.length - 1, Math.max(0, idx + delta))].id;
|
|
2814
|
-
}
|
|
2815
3255
|
const ToolbarContext = (0, react.createContext)(null);
|
|
2816
3256
|
function useToolbarContext() {
|
|
2817
3257
|
const ctx = (0, react.useContext)(ToolbarContext);
|
|
@@ -2821,29 +3261,31 @@ function useToolbarContext() {
|
|
|
2821
3261
|
/** Renders the `ToolbarRoot` component. */
|
|
2822
3262
|
function ToolbarRoot({ children, orientation = "horizontal" }) {
|
|
2823
3263
|
const [activeId, setActiveId] = (0, react.useState)(null);
|
|
2824
|
-
const items = (
|
|
2825
|
-
const registerItem = (0, react.useCallback)((entry) => {
|
|
2826
|
-
const list = items.current;
|
|
2827
|
-
const existing = list.findIndex((i) => i.id === entry.id);
|
|
2828
|
-
if (existing >= 0) list[existing] = entry;
|
|
2829
|
-
else list.push(entry);
|
|
2830
|
-
}, []);
|
|
3264
|
+
const { items, registerItem, unregisterItem: removeItem } = useItemRegistry();
|
|
2831
3265
|
const unregisterItem = (0, react.useCallback)((id) => {
|
|
2832
|
-
|
|
2833
|
-
setActiveId((prev) => prev === id ?
|
|
2834
|
-
}, []);
|
|
3266
|
+
const removedIndex = removeItem(id);
|
|
3267
|
+
setActiveId((prev) => prev === id ? nearestEnabledId(items.current, removedIndex) : prev);
|
|
3268
|
+
}, [items, removeItem]);
|
|
2835
3269
|
(0, react.useLayoutEffect)(() => {
|
|
2836
|
-
setActiveId((prev) => prev !== null && prev !== void 0 ? prev : firstEnabledId
|
|
3270
|
+
setActiveId((prev) => prev !== null && prev !== void 0 ? prev : firstEnabledId(items.current));
|
|
2837
3271
|
}, [activeId]);
|
|
3272
|
+
const contextValue = (0, react.useMemo)(() => ({
|
|
3273
|
+
orientation,
|
|
3274
|
+
activeId,
|
|
3275
|
+
setActiveId,
|
|
3276
|
+
registerItem,
|
|
3277
|
+
unregisterItem,
|
|
3278
|
+
items
|
|
3279
|
+
}), [
|
|
3280
|
+
orientation,
|
|
3281
|
+
activeId,
|
|
3282
|
+
setActiveId,
|
|
3283
|
+
registerItem,
|
|
3284
|
+
unregisterItem,
|
|
3285
|
+
items
|
|
3286
|
+
]);
|
|
2838
3287
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarContext.Provider, {
|
|
2839
|
-
value:
|
|
2840
|
-
orientation,
|
|
2841
|
-
activeId,
|
|
2842
|
-
setActiveId,
|
|
2843
|
-
registerItem,
|
|
2844
|
-
unregisterItem,
|
|
2845
|
-
items
|
|
2846
|
-
},
|
|
3288
|
+
value: contextValue,
|
|
2847
3289
|
children
|
|
2848
3290
|
});
|
|
2849
3291
|
}
|
|
@@ -2862,18 +3304,16 @@ function ToolbarContainer(_ref) {
|
|
|
2862
3304
|
let nextId;
|
|
2863
3305
|
if (e.key === nextKey) {
|
|
2864
3306
|
e.preventDefault();
|
|
2865
|
-
nextId = moveActiveId
|
|
3307
|
+
nextId = moveActiveId(items.current, activeId, 1);
|
|
2866
3308
|
} else if (e.key === prevKey) {
|
|
2867
3309
|
e.preventDefault();
|
|
2868
|
-
nextId = moveActiveId
|
|
3310
|
+
nextId = moveActiveId(items.current, activeId, -1);
|
|
2869
3311
|
} else if (e.key === "Home") {
|
|
2870
3312
|
e.preventDefault();
|
|
2871
|
-
nextId = firstEnabledId
|
|
3313
|
+
nextId = firstEnabledId(items.current);
|
|
2872
3314
|
} else if (e.key === "End") {
|
|
2873
|
-
var _enabled$id, _enabled;
|
|
2874
3315
|
e.preventDefault();
|
|
2875
|
-
|
|
2876
|
-
nextId = (_enabled$id = (_enabled = enabled[enabled.length - 1]) === null || _enabled === void 0 ? void 0 : _enabled.id) !== null && _enabled$id !== void 0 ? _enabled$id : null;
|
|
3316
|
+
nextId = lastEnabledId(items.current);
|
|
2877
3317
|
}
|
|
2878
3318
|
if (nextId) {
|
|
2879
3319
|
setActiveId(nextId);
|
|
@@ -2947,6 +3387,10 @@ const _excluded3$2 = [
|
|
|
2947
3387
|
/**
|
|
2948
3388
|
* From `start`, return the index of the first enabled item walking in `dir`
|
|
2949
3389
|
* (+1/-1). Honors `loop`. Returns -1 if none.
|
|
3390
|
+
*
|
|
3391
|
+
* Composite navigates by INDEX (grid rows/columns, wrap and loop modes), which
|
|
3392
|
+
* is why it keeps this directional scan instead of the registry's id-based
|
|
3393
|
+
* `moveActiveId`.
|
|
2950
3394
|
*/
|
|
2951
3395
|
function firstEnabledFrom(list, start, dir, loop) {
|
|
2952
3396
|
const n = list.length;
|
|
@@ -2969,7 +3413,7 @@ function useCompositeContext() {
|
|
|
2969
3413
|
/** Renders the `CompositeProvider` component. */
|
|
2970
3414
|
function CompositeProvider({ children, focusLoop = false, focusWrap = false, orientation = "both", activeId: controlledActiveId, onActiveIdChange, setActiveId: setActiveIdDeprecated }) {
|
|
2971
3415
|
const [internalActiveId, setInternalActiveId] = (0, react.useState)(null);
|
|
2972
|
-
const items
|
|
3416
|
+
const { items, registerItem: registerEntry, unregisterItem: removeItem } = useItemRegistry();
|
|
2973
3417
|
const onActiveIdChangeCb = onActiveIdChange !== null && onActiveIdChange !== void 0 ? onActiveIdChange : setActiveIdDeprecated;
|
|
2974
3418
|
const activeId = controlledActiveId !== void 0 ? controlledActiveId : internalActiveId;
|
|
2975
3419
|
const activeIdRef = (0, react.useRef)(activeId);
|
|
@@ -2981,16 +3425,8 @@ function CompositeProvider({ children, focusLoop = false, focusWrap = false, ori
|
|
|
2981
3425
|
}, [controlledActiveId, onActiveIdChangeCb]);
|
|
2982
3426
|
const registerItem = (0, react.useCallback)((id, element, row = 0, col = 0, disabled = false) => {
|
|
2983
3427
|
const list = items.current;
|
|
2984
|
-
const
|
|
2985
|
-
|
|
2986
|
-
if (existing >= 0) list[existing] = {
|
|
2987
|
-
id,
|
|
2988
|
-
element,
|
|
2989
|
-
row,
|
|
2990
|
-
col,
|
|
2991
|
-
disabled
|
|
2992
|
-
};
|
|
2993
|
-
else list.push({
|
|
3428
|
+
const activeBecameDisabled = list.findIndex((i) => i.id === id) >= 0 && id === activeIdRef.current && disabled;
|
|
3429
|
+
registerEntry({
|
|
2994
3430
|
id,
|
|
2995
3431
|
element,
|
|
2996
3432
|
row,
|
|
@@ -3011,29 +3447,48 @@ function CompositeProvider({ children, focusLoop = false, focusWrap = false, ori
|
|
|
3011
3447
|
setInternalActiveId(null);
|
|
3012
3448
|
} else setActiveId(nextId);
|
|
3013
3449
|
}
|
|
3014
|
-
}, [
|
|
3450
|
+
}, [
|
|
3451
|
+
controlledActiveId,
|
|
3452
|
+
setActiveId,
|
|
3453
|
+
items,
|
|
3454
|
+
registerEntry
|
|
3455
|
+
]);
|
|
3015
3456
|
const unregisterItem = (0, react.useCallback)((id) => {
|
|
3016
|
-
|
|
3457
|
+
const removedIndex = removeItem(id);
|
|
3458
|
+
if (removedIndex < 0) return;
|
|
3017
3459
|
if (controlledActiveId === void 0) setInternalActiveId((prev) => {
|
|
3018
3460
|
if (prev !== id) return prev;
|
|
3019
|
-
const
|
|
3020
|
-
const nextId = idx >= 0 ? items.current[idx].id : null;
|
|
3461
|
+
const nextId = nearestEnabledId(items.current, removedIndex);
|
|
3021
3462
|
activeIdRef.current = nextId;
|
|
3022
3463
|
if (nextId === null) seededRef.current = false;
|
|
3023
3464
|
return nextId;
|
|
3024
3465
|
});
|
|
3025
|
-
}, [
|
|
3466
|
+
}, [
|
|
3467
|
+
controlledActiveId,
|
|
3468
|
+
items,
|
|
3469
|
+
removeItem
|
|
3470
|
+
]);
|
|
3471
|
+
const contextValue = (0, react.useMemo)(() => ({
|
|
3472
|
+
activeId,
|
|
3473
|
+
setActiveId,
|
|
3474
|
+
registerItem,
|
|
3475
|
+
unregisterItem,
|
|
3476
|
+
items,
|
|
3477
|
+
focusLoop,
|
|
3478
|
+
focusWrap,
|
|
3479
|
+
orientation
|
|
3480
|
+
}), [
|
|
3481
|
+
activeId,
|
|
3482
|
+
setActiveId,
|
|
3483
|
+
registerItem,
|
|
3484
|
+
unregisterItem,
|
|
3485
|
+
items,
|
|
3486
|
+
focusLoop,
|
|
3487
|
+
focusWrap,
|
|
3488
|
+
orientation
|
|
3489
|
+
]);
|
|
3026
3490
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CompositeContext.Provider, {
|
|
3027
|
-
value:
|
|
3028
|
-
activeId,
|
|
3029
|
-
setActiveId,
|
|
3030
|
-
registerItem,
|
|
3031
|
-
unregisterItem,
|
|
3032
|
-
items,
|
|
3033
|
-
focusLoop,
|
|
3034
|
-
focusWrap,
|
|
3035
|
-
orientation
|
|
3036
|
-
},
|
|
3491
|
+
value: contextValue,
|
|
3037
3492
|
children
|
|
3038
3493
|
});
|
|
3039
3494
|
}
|
|
@@ -3200,17 +3655,6 @@ const _excluded2$2 = [
|
|
|
3200
3655
|
"onClick",
|
|
3201
3656
|
"onFocus"
|
|
3202
3657
|
];
|
|
3203
|
-
function firstEnabledId(items) {
|
|
3204
|
-
var _items$find$id, _items$find;
|
|
3205
|
-
return (_items$find$id = (_items$find = items.find((i) => !i.disabled)) === null || _items$find === void 0 ? void 0 : _items$find.id) !== null && _items$find$id !== void 0 ? _items$find$id : null;
|
|
3206
|
-
}
|
|
3207
|
-
function moveActiveId(items, activeId, delta) {
|
|
3208
|
-
const enabled = items.filter((i) => !i.disabled);
|
|
3209
|
-
if (enabled.length === 0) return null;
|
|
3210
|
-
const idx = enabled.findIndex((i) => i.id === activeId);
|
|
3211
|
-
if (idx < 0) return delta > 0 ? enabled[0].id : enabled[enabled.length - 1].id;
|
|
3212
|
-
return enabled[Math.min(enabled.length - 1, Math.max(0, idx + delta))].id;
|
|
3213
|
-
}
|
|
3214
3658
|
const ToggleGroupContext = (0, react.createContext)(null);
|
|
3215
3659
|
/**
|
|
3216
3660
|
* Groups related `Toggle`s with roving-tabindex keyboard navigation and shared
|
|
@@ -3238,17 +3682,11 @@ function ToggleGroup(_ref) {
|
|
|
3238
3682
|
setValue
|
|
3239
3683
|
]);
|
|
3240
3684
|
const [activeId, setActiveId] = (0, react.useState)(null);
|
|
3241
|
-
const items = (
|
|
3242
|
-
const registerItem = (0, react.useCallback)((entry) => {
|
|
3243
|
-
const list = items.current;
|
|
3244
|
-
const existing = list.findIndex((i) => i.id === entry.id);
|
|
3245
|
-
if (existing >= 0) list[existing] = entry;
|
|
3246
|
-
else list.push(entry);
|
|
3247
|
-
}, []);
|
|
3685
|
+
const { items, registerItem, unregisterItem: removeItem } = useItemRegistry();
|
|
3248
3686
|
const unregisterItem = (0, react.useCallback)((id) => {
|
|
3249
|
-
|
|
3250
|
-
setActiveId((prev) => prev === id ?
|
|
3251
|
-
}, []);
|
|
3687
|
+
const removedIndex = removeItem(id);
|
|
3688
|
+
setActiveId((prev) => prev === id ? nearestEnabledId(items.current, removedIndex) : prev);
|
|
3689
|
+
}, [items, removeItem]);
|
|
3252
3690
|
(0, react.useLayoutEffect)(() => {
|
|
3253
3691
|
setActiveId((prev) => prev !== null && prev !== void 0 ? prev : firstEnabledId(items.current));
|
|
3254
3692
|
}, [activeId]);
|
|
@@ -3271,10 +3709,8 @@ function ToggleGroup(_ref) {
|
|
|
3271
3709
|
e.preventDefault();
|
|
3272
3710
|
nextId = firstEnabledId(items.current);
|
|
3273
3711
|
} else if (e.key === "End") {
|
|
3274
|
-
var _enabled$id, _enabled;
|
|
3275
3712
|
e.preventDefault();
|
|
3276
|
-
|
|
3277
|
-
nextId = (_enabled$id = (_enabled = enabled[enabled.length - 1]) === null || _enabled === void 0 ? void 0 : _enabled.id) !== null && _enabled$id !== void 0 ? _enabled$id : null;
|
|
3713
|
+
nextId = lastEnabledId(items.current);
|
|
3278
3714
|
}
|
|
3279
3715
|
if (nextId) {
|
|
3280
3716
|
setActiveId(nextId);
|
|
@@ -3287,18 +3723,28 @@ function ToggleGroup(_ref) {
|
|
|
3287
3723
|
focusActive,
|
|
3288
3724
|
onKeyDown
|
|
3289
3725
|
]);
|
|
3726
|
+
const contextValue = (0, react.useMemo)(() => ({
|
|
3727
|
+
isPressed,
|
|
3728
|
+
toggle,
|
|
3729
|
+
disabled,
|
|
3730
|
+
orientation,
|
|
3731
|
+
activeId,
|
|
3732
|
+
setActiveId,
|
|
3733
|
+
registerItem,
|
|
3734
|
+
unregisterItem,
|
|
3735
|
+
items
|
|
3736
|
+
}), [
|
|
3737
|
+
isPressed,
|
|
3738
|
+
toggle,
|
|
3739
|
+
disabled,
|
|
3740
|
+
orientation,
|
|
3741
|
+
activeId,
|
|
3742
|
+
registerItem,
|
|
3743
|
+
unregisterItem,
|
|
3744
|
+
items
|
|
3745
|
+
]);
|
|
3290
3746
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleGroupContext.Provider, {
|
|
3291
|
-
value:
|
|
3292
|
-
isPressed,
|
|
3293
|
-
toggle,
|
|
3294
|
-
disabled,
|
|
3295
|
-
orientation,
|
|
3296
|
-
activeId,
|
|
3297
|
-
setActiveId,
|
|
3298
|
-
registerItem,
|
|
3299
|
-
unregisterItem,
|
|
3300
|
-
items
|
|
3301
|
-
},
|
|
3747
|
+
value: contextValue,
|
|
3302
3748
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", _objectSpread2({
|
|
3303
3749
|
role: "group",
|
|
3304
3750
|
onKeyDown: handleKeyDown
|
|
@@ -3318,17 +3764,19 @@ function Toggle(_ref2) {
|
|
|
3318
3764
|
const [standalonePressed, setStandalonePressed] = useControllableState(defaultPressed, pressedProp, onPressedChange);
|
|
3319
3765
|
const inGroup = group !== null;
|
|
3320
3766
|
const isDisabled = disabled || inGroup && group.disabled || false;
|
|
3767
|
+
const registerItem = group === null || group === void 0 ? void 0 : group.registerItem;
|
|
3768
|
+
const unregisterItem = group === null || group === void 0 ? void 0 : group.unregisterItem;
|
|
3321
3769
|
(0, react.useLayoutEffect)(() => {
|
|
3322
|
-
if (!
|
|
3323
|
-
|
|
3770
|
+
if (!registerItem || !unregisterItem) return void 0;
|
|
3771
|
+
registerItem({
|
|
3324
3772
|
id: itemId,
|
|
3325
3773
|
element: buttonRef.current,
|
|
3326
3774
|
disabled: isDisabled
|
|
3327
3775
|
});
|
|
3328
|
-
return () =>
|
|
3776
|
+
return () => unregisterItem(itemId);
|
|
3329
3777
|
}, [
|
|
3330
|
-
|
|
3331
|
-
|
|
3778
|
+
registerItem,
|
|
3779
|
+
unregisterItem,
|
|
3332
3780
|
itemId,
|
|
3333
3781
|
isDisabled
|
|
3334
3782
|
]);
|
|
@@ -3556,7 +4004,7 @@ const Meter = (0, react.forwardRef)(function Meter(_ref, ref) {
|
|
|
3556
4004
|
//#region src/primitives/accordion.tsx
|
|
3557
4005
|
const _excluded$1 = ["value", "disabled"];
|
|
3558
4006
|
const _excluded2$1 = ["onClick", "disabled"];
|
|
3559
|
-
const _excluded3$1 = ["style"];
|
|
4007
|
+
const _excluded3$1 = ["hiddenUntilFound", "style"];
|
|
3560
4008
|
const AccordionRootContext = (0, react.createContext)(null);
|
|
3561
4009
|
function useAccordionRoot() {
|
|
3562
4010
|
const ctx = (0, react.useContext)(AccordionRootContext);
|
|
@@ -3643,17 +4091,31 @@ function AccordionTrigger(_ref2) {
|
|
|
3643
4091
|
}
|
|
3644
4092
|
/** Renders the `AccordionContent` component. */
|
|
3645
4093
|
function AccordionContent(_ref3) {
|
|
3646
|
-
let { style } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$1);
|
|
4094
|
+
let { hiddenUntilFound = false, style } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$1);
|
|
3647
4095
|
const root = useAccordionRoot();
|
|
3648
4096
|
const item = useAccordionItem();
|
|
3649
|
-
const
|
|
4097
|
+
const expanded = root.isExpanded(item.value);
|
|
4098
|
+
const { ref, mounted, dataAttributes } = useEnterLeave(expanded, { animated: root.animated && !hiddenUntilFound });
|
|
3650
4099
|
const innerRef = (0, react.useRef)(null);
|
|
3651
|
-
(
|
|
3652
|
-
|
|
3653
|
-
|
|
4100
|
+
const contentRef = useMergedRef(innerRef, ref);
|
|
4101
|
+
useHiddenUntilFound(innerRef, {
|
|
4102
|
+
enabled: hiddenUntilFound,
|
|
4103
|
+
open: expanded,
|
|
4104
|
+
onReveal: (0, react.useCallback)(() => {
|
|
4105
|
+
if (!root.isExpanded(item.value)) root.toggle(item.value);
|
|
4106
|
+
}, [root, item.value])
|
|
4107
|
+
});
|
|
4108
|
+
if (hiddenUntilFound) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", _objectSpread2({
|
|
4109
|
+
ref: contentRef,
|
|
4110
|
+
id: item.contentId,
|
|
4111
|
+
role: "region",
|
|
4112
|
+
"aria-labelledby": item.triggerId,
|
|
4113
|
+
"data-state": expanded ? "open" : "closed",
|
|
4114
|
+
style
|
|
4115
|
+
}, props));
|
|
3654
4116
|
if (!mounted) return null;
|
|
3655
4117
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", _objectSpread2(_objectSpread2({
|
|
3656
|
-
ref:
|
|
4118
|
+
ref: contentRef,
|
|
3657
4119
|
id: item.contentId,
|
|
3658
4120
|
role: "region",
|
|
3659
4121
|
"aria-labelledby": item.triggerId,
|
|
@@ -4005,18 +4467,21 @@ const _excluded4 = [
|
|
|
4005
4467
|
"name",
|
|
4006
4468
|
"id",
|
|
4007
4469
|
"onChange",
|
|
4470
|
+
"onBlur",
|
|
4008
4471
|
"aria-describedby"
|
|
4009
4472
|
];
|
|
4010
4473
|
const _excluded5 = [
|
|
4011
4474
|
"name",
|
|
4012
4475
|
"id",
|
|
4013
4476
|
"onChange",
|
|
4477
|
+
"onBlur",
|
|
4014
4478
|
"aria-describedby"
|
|
4015
4479
|
];
|
|
4016
4480
|
const _excluded6 = [
|
|
4017
4481
|
"name",
|
|
4018
4482
|
"id",
|
|
4019
4483
|
"onChange",
|
|
4484
|
+
"onBlur",
|
|
4020
4485
|
"aria-describedby",
|
|
4021
4486
|
"children"
|
|
4022
4487
|
];
|
|
@@ -4127,7 +4592,7 @@ function FormLabel(_ref3) {
|
|
|
4127
4592
|
}
|
|
4128
4593
|
const FormInput = (0, react.forwardRef)((_ref4, ref) => {
|
|
4129
4594
|
var _useFieldValueMaybe;
|
|
4130
|
-
let { name, id, onChange, "aria-describedby": ariaDescribedBy } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4);
|
|
4595
|
+
let { name, id, onChange, onBlur, "aria-describedby": ariaDescribedBy } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4);
|
|
4131
4596
|
const form = useFormContext();
|
|
4132
4597
|
const field = useFormField();
|
|
4133
4598
|
const value = (_useFieldValueMaybe = useFieldValueMaybe(form, name)) !== null && _useFieldValueMaybe !== void 0 ? _useFieldValueMaybe : "";
|
|
@@ -4146,13 +4611,21 @@ const FormInput = (0, react.forwardRef)((_ref4, ref) => {
|
|
|
4146
4611
|
name,
|
|
4147
4612
|
onChange
|
|
4148
4613
|
]);
|
|
4614
|
+
const handleBlur = (0, react.useCallback)((e) => {
|
|
4615
|
+
form === null || form === void 0 || form.setFieldTouched(name, true);
|
|
4616
|
+
onBlur === null || onBlur === void 0 || onBlur(e);
|
|
4617
|
+
}, [
|
|
4618
|
+
form,
|
|
4619
|
+
name,
|
|
4620
|
+
onBlur
|
|
4621
|
+
]);
|
|
4149
4622
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", _objectSpread2({
|
|
4150
4623
|
ref: setRef,
|
|
4151
4624
|
id: id !== null && id !== void 0 ? id : field === null || field === void 0 ? void 0 : field.inputId,
|
|
4152
4625
|
name,
|
|
4153
4626
|
value,
|
|
4154
4627
|
onChange: handleChange,
|
|
4155
|
-
onBlur:
|
|
4628
|
+
onBlur: handleBlur,
|
|
4156
4629
|
"aria-invalid": hasError || void 0,
|
|
4157
4630
|
"aria-describedby": composeDescribedBy(field, hasError, ariaDescribedBy)
|
|
4158
4631
|
}, props));
|
|
@@ -4160,7 +4633,7 @@ const FormInput = (0, react.forwardRef)((_ref4, ref) => {
|
|
|
4160
4633
|
FormInput.displayName = "FormInput";
|
|
4161
4634
|
const FormTextarea = (0, react.forwardRef)((_ref5, ref) => {
|
|
4162
4635
|
var _useFieldValueMaybe2;
|
|
4163
|
-
let { name, id, onChange, "aria-describedby": ariaDescribedBy } = _ref5, props = _objectWithoutProperties(_ref5, _excluded5);
|
|
4636
|
+
let { name, id, onChange, onBlur, "aria-describedby": ariaDescribedBy } = _ref5, props = _objectWithoutProperties(_ref5, _excluded5);
|
|
4164
4637
|
const form = useFormContext();
|
|
4165
4638
|
const field = useFormField();
|
|
4166
4639
|
const value = (_useFieldValueMaybe2 = useFieldValueMaybe(form, name)) !== null && _useFieldValueMaybe2 !== void 0 ? _useFieldValueMaybe2 : "";
|
|
@@ -4176,13 +4649,21 @@ const FormTextarea = (0, react.forwardRef)((_ref5, ref) => {
|
|
|
4176
4649
|
name,
|
|
4177
4650
|
onChange
|
|
4178
4651
|
]);
|
|
4652
|
+
const handleBlur = (0, react.useCallback)((e) => {
|
|
4653
|
+
form === null || form === void 0 || form.setFieldTouched(name, true);
|
|
4654
|
+
onBlur === null || onBlur === void 0 || onBlur(e);
|
|
4655
|
+
}, [
|
|
4656
|
+
form,
|
|
4657
|
+
name,
|
|
4658
|
+
onBlur
|
|
4659
|
+
]);
|
|
4179
4660
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", _objectSpread2({
|
|
4180
4661
|
ref: setRef,
|
|
4181
4662
|
id: id !== null && id !== void 0 ? id : field === null || field === void 0 ? void 0 : field.inputId,
|
|
4182
4663
|
name,
|
|
4183
4664
|
value,
|
|
4184
4665
|
onChange: handleChange,
|
|
4185
|
-
onBlur:
|
|
4666
|
+
onBlur: handleBlur,
|
|
4186
4667
|
"aria-invalid": hasError || void 0,
|
|
4187
4668
|
"aria-describedby": composeDescribedBy(field, hasError, ariaDescribedBy)
|
|
4188
4669
|
}, props));
|
|
@@ -4190,7 +4671,7 @@ const FormTextarea = (0, react.forwardRef)((_ref5, ref) => {
|
|
|
4190
4671
|
FormTextarea.displayName = "FormTextarea";
|
|
4191
4672
|
const FormSelect = (0, react.forwardRef)((_ref6, ref) => {
|
|
4192
4673
|
var _useFieldValueMaybe3;
|
|
4193
|
-
let { name, id, onChange, "aria-describedby": ariaDescribedBy, children } = _ref6, props = _objectWithoutProperties(_ref6, _excluded6);
|
|
4674
|
+
let { name, id, onChange, onBlur, "aria-describedby": ariaDescribedBy, children } = _ref6, props = _objectWithoutProperties(_ref6, _excluded6);
|
|
4194
4675
|
const form = useFormContext();
|
|
4195
4676
|
const field = useFormField();
|
|
4196
4677
|
const value = (_useFieldValueMaybe3 = useFieldValueMaybe(form, name)) !== null && _useFieldValueMaybe3 !== void 0 ? _useFieldValueMaybe3 : "";
|
|
@@ -4206,13 +4687,21 @@ const FormSelect = (0, react.forwardRef)((_ref6, ref) => {
|
|
|
4206
4687
|
name,
|
|
4207
4688
|
onChange
|
|
4208
4689
|
]);
|
|
4690
|
+
const handleBlur = (0, react.useCallback)((e) => {
|
|
4691
|
+
form === null || form === void 0 || form.setFieldTouched(name, true);
|
|
4692
|
+
onBlur === null || onBlur === void 0 || onBlur(e);
|
|
4693
|
+
}, [
|
|
4694
|
+
form,
|
|
4695
|
+
name,
|
|
4696
|
+
onBlur
|
|
4697
|
+
]);
|
|
4209
4698
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", _objectSpread2(_objectSpread2({
|
|
4210
4699
|
ref: setRef,
|
|
4211
4700
|
id: id !== null && id !== void 0 ? id : field === null || field === void 0 ? void 0 : field.inputId,
|
|
4212
4701
|
name,
|
|
4213
4702
|
value,
|
|
4214
4703
|
onChange: handleChange,
|
|
4215
|
-
onBlur:
|
|
4704
|
+
onBlur: handleBlur,
|
|
4216
4705
|
"aria-invalid": hasError || void 0,
|
|
4217
4706
|
"aria-describedby": composeDescribedBy(field, hasError, ariaDescribedBy)
|
|
4218
4707
|
}, props), {}, { children }));
|
|
@@ -4510,7 +4999,9 @@ exports.ToolbarRoot = ToolbarRoot;
|
|
|
4510
4999
|
exports.ToolbarSeparator = ToolbarSeparator;
|
|
4511
5000
|
exports.Tooltip = Tooltip;
|
|
4512
5001
|
exports.TooltipAnchor = TooltipAnchor;
|
|
5002
|
+
exports.TooltipGroup = TooltipGroup;
|
|
4513
5003
|
exports.TooltipProvider = TooltipProvider;
|
|
5004
|
+
exports.TooltipRoot = TooltipRoot;
|
|
4514
5005
|
exports.useCommandState = useCommandState;
|
|
4515
5006
|
exports.useControllableState = useControllableState;
|
|
4516
5007
|
exports.useDialogClose = useDialogClose;
|