@marktiderman/genesis-ui 1.3.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AppShell-BJarYZzz.d.ts +198 -0
- package/dist/{chunk-NJMO3VPA.js → chunk-22XB3Q6H.js} +8 -8
- package/dist/chunk-22XB3Q6H.js.map +1 -0
- package/dist/{chunk-2MXMWBDV.js → chunk-27ELYTGE.js} +6 -6
- package/dist/chunk-27ELYTGE.js.map +1 -0
- package/dist/chunk-46TZGMFW.js +159 -0
- package/dist/chunk-46TZGMFW.js.map +1 -0
- package/dist/chunk-4CQHPWJD.js +117 -0
- package/dist/chunk-4CQHPWJD.js.map +1 -0
- package/dist/{chunk-ZDAT5JDH.js → chunk-65SPT7EA.js} +24 -6
- package/dist/chunk-65SPT7EA.js.map +1 -0
- package/dist/chunk-6KHY647C.js +67 -0
- package/dist/chunk-6KHY647C.js.map +1 -0
- package/dist/chunk-6M4NHHKG.js +51 -0
- package/dist/chunk-6M4NHHKG.js.map +1 -0
- package/dist/chunk-6Q6CLLJ4.js +9 -0
- package/dist/chunk-6Q6CLLJ4.js.map +1 -0
- package/dist/{chunk-UGHQFQOE.js → chunk-6TVMQH6M.js} +28 -28
- package/dist/chunk-6TVMQH6M.js.map +1 -0
- package/dist/{chunk-6VVVGYKS.js → chunk-6XPMU65K.js} +5 -5
- package/dist/{chunk-6VVVGYKS.js.map → chunk-6XPMU65K.js.map} +1 -1
- package/dist/{chunk-YZEA5TGK.js → chunk-7XMZVISM.js} +16 -16
- package/dist/chunk-7XMZVISM.js.map +1 -0
- package/dist/chunk-A7AHVDG7.js +52 -0
- package/dist/chunk-A7AHVDG7.js.map +1 -0
- package/dist/chunk-AFZ76Q26.js +84 -0
- package/dist/chunk-AFZ76Q26.js.map +1 -0
- package/dist/{chunk-4V4H2ZM7.js → chunk-AL5TMEZQ.js} +31 -31
- package/dist/chunk-AL5TMEZQ.js.map +1 -0
- package/dist/{chunk-AUECDWP2.js → chunk-AOZGQM6W.js} +3 -3
- package/dist/chunk-AOZGQM6W.js.map +1 -0
- package/dist/chunk-ARJI2JUV.js +122 -0
- package/dist/chunk-ARJI2JUV.js.map +1 -0
- package/dist/chunk-AVFZ4P4B.js +25 -0
- package/dist/chunk-AVFZ4P4B.js.map +1 -0
- package/dist/chunk-B2GIBUQD.js +11 -0
- package/dist/chunk-B2GIBUQD.js.map +1 -0
- package/dist/{chunk-JXI2MYL3.js → chunk-C46ITXE4.js} +5 -5
- package/dist/chunk-C46ITXE4.js.map +1 -0
- package/dist/{chunk-A2OXCNNY.js → chunk-CNTWQSUT.js} +3 -3
- package/dist/{chunk-A2OXCNNY.js.map → chunk-CNTWQSUT.js.map} +1 -1
- package/dist/chunk-D2LIXA2Y.js +65 -0
- package/dist/chunk-D2LIXA2Y.js.map +1 -0
- package/dist/{chunk-T5VX5DYO.js → chunk-F47U5KNW.js} +5 -5
- package/dist/chunk-F47U5KNW.js.map +1 -0
- package/dist/chunk-FEJAZFP3.js +1100 -0
- package/dist/chunk-FEJAZFP3.js.map +1 -0
- package/dist/{chunk-2B3MFHBQ.js → chunk-FK42ZGGV.js} +21 -21
- package/dist/chunk-FK42ZGGV.js.map +1 -0
- package/dist/{chunk-XISSLIMH.js → chunk-FTTNGGLA.js} +2 -2
- package/dist/{chunk-XISSLIMH.js.map → chunk-FTTNGGLA.js.map} +1 -1
- package/dist/chunk-G5YKBPBF.js +74 -0
- package/dist/chunk-G5YKBPBF.js.map +1 -0
- package/dist/{chunk-KB5T5LWM.js → chunk-IJCT5IJD.js} +3 -3
- package/dist/{chunk-KB5T5LWM.js.map → chunk-IJCT5IJD.js.map} +1 -1
- package/dist/{chunk-44TULYGG.js → chunk-J6FBA7PH.js} +3 -3
- package/dist/{chunk-44TULYGG.js.map → chunk-J6FBA7PH.js.map} +1 -1
- package/dist/chunk-JAMLFMDS.js +12 -0
- package/dist/chunk-JAMLFMDS.js.map +1 -0
- package/dist/{chunk-C6H7AMO4.js → chunk-LNFF2RBD.js} +9 -9
- package/dist/chunk-LNFF2RBD.js.map +1 -0
- package/dist/{chunk-QBZMY2AF.js → chunk-M62CHO3N.js} +18 -18
- package/dist/chunk-M62CHO3N.js.map +1 -0
- package/dist/{chunk-5Q4FABZQ.js → chunk-NUXW6NPP.js} +8 -8
- package/dist/chunk-NUXW6NPP.js.map +1 -0
- package/dist/{chunk-ZJFSZFPI.js → chunk-NWSCYLPT.js} +77 -18
- package/dist/chunk-NWSCYLPT.js.map +1 -0
- package/dist/{chunk-63FW5ZUA.js → chunk-P3ZL6FGR.js} +7 -7
- package/dist/chunk-P3ZL6FGR.js.map +1 -0
- package/dist/chunk-P64MFQXZ.js +191 -0
- package/dist/chunk-P64MFQXZ.js.map +1 -0
- package/dist/chunk-PLIYF6KI.js +52 -0
- package/dist/chunk-PLIYF6KI.js.map +1 -0
- package/dist/chunk-PSR47JRA.js +26 -0
- package/dist/chunk-PSR47JRA.js.map +1 -0
- package/dist/{chunk-QLCDAFS7.js → chunk-Q4I4SFBD.js} +3 -3
- package/dist/chunk-Q4I4SFBD.js.map +1 -0
- package/dist/{chunk-SBJV3K4G.js → chunk-QJ6P2DW6.js} +28 -28
- package/dist/chunk-QJ6P2DW6.js.map +1 -0
- package/dist/{chunk-IP6TMT3D.js → chunk-R7QFP6EL.js} +3 -3
- package/dist/chunk-R7QFP6EL.js.map +1 -0
- package/dist/{chunk-WZWR2ELB.js → chunk-SEBU6JCK.js} +6 -6
- package/dist/chunk-SEBU6JCK.js.map +1 -0
- package/dist/{chunk-7OBL3H5P.js → chunk-SEFK4NZV.js} +3 -3
- package/dist/chunk-SEFK4NZV.js.map +1 -0
- package/dist/chunk-SRIT4NFQ.js +67 -0
- package/dist/chunk-SRIT4NFQ.js.map +1 -0
- package/dist/chunk-SY62XJFA.js +19 -0
- package/dist/chunk-SY62XJFA.js.map +1 -0
- package/dist/{chunk-SVXDWPLO.js → chunk-THD3YOOZ.js} +17 -17
- package/dist/chunk-THD3YOOZ.js.map +1 -0
- package/dist/chunk-VXFYETRK.js +58 -0
- package/dist/chunk-VXFYETRK.js.map +1 -0
- package/dist/chunk-XBX6QMR5.js +58 -0
- package/dist/chunk-XBX6QMR5.js.map +1 -0
- package/dist/{chunk-SCUT2ZCD.js → chunk-XCGZPFT7.js} +17 -17
- package/dist/chunk-XCGZPFT7.js.map +1 -0
- package/dist/chunk-XMK3T4TA.js +73 -0
- package/dist/chunk-XMK3T4TA.js.map +1 -0
- package/dist/chunk-YJ6MPS6U.js +226 -0
- package/dist/chunk-YJ6MPS6U.js.map +1 -0
- package/dist/chunk-YRYQXU3G.js +38 -0
- package/dist/chunk-YRYQXU3G.js.map +1 -0
- package/dist/{chunk-5J7BP5DI.js → chunk-YWFPMND7.js} +10 -10
- package/dist/chunk-YWFPMND7.js.map +1 -0
- package/dist/chunk-YYEGAFUE.js +94 -0
- package/dist/chunk-YYEGAFUE.js.map +1 -0
- package/dist/{chunk-TKA4LOMT.js → chunk-ZZ7H7VVX.js} +8 -8
- package/dist/chunk-ZZ7H7VVX.js.map +1 -0
- package/dist/components/data/index.d.ts +194 -211
- package/dist/components/data/index.js +362 -1381
- package/dist/components/data/index.js.map +1 -1
- package/dist/components/layout/dashboard-page.d.ts +4 -0
- package/dist/components/layout/dashboard-page.js +5 -0
- package/dist/components/layout/dashboard-page.js.map +1 -0
- package/dist/components/layout/detail-page.d.ts +91 -0
- package/dist/components/layout/detail-page.js +6 -0
- package/dist/components/layout/detail-page.js.map +1 -0
- package/dist/components/layout/form-page.d.ts +82 -0
- package/dist/components/layout/form-page.js +5 -0
- package/dist/components/layout/form-page.js.map +1 -0
- package/dist/components/layout/index.d.ts +15 -0
- package/dist/components/layout/index.js +21 -0
- package/dist/components/layout/index.js.map +1 -0
- package/dist/components/layout/settings-page.d.ts +114 -0
- package/dist/components/layout/settings-page.js +6 -0
- package/dist/components/layout/settings-page.js.map +1 -0
- package/dist/components/patterns/empty-state.d.ts +74 -0
- package/dist/components/{ui → patterns}/empty-state.js +2 -1
- package/dist/components/{ui → patterns}/form-field.d.ts +2 -2
- package/dist/components/{ui → patterns}/form-field.js +2 -2
- package/dist/components/patterns/index.d.ts +18 -0
- package/dist/components/patterns/index.js +18 -0
- package/dist/components/patterns/index.js.map +1 -0
- package/dist/components/patterns/page-loading.d.ts +25 -0
- package/dist/components/patterns/page-loading.js +5 -0
- package/dist/components/patterns/page-loading.js.map +1 -0
- package/dist/components/patterns/settings-row.d.ts +42 -0
- package/dist/components/patterns/settings-row.js +6 -0
- package/dist/components/patterns/settings-row.js.map +1 -0
- package/dist/components/patterns/status-badge.d.ts +38 -0
- package/dist/components/patterns/status-badge.js +4 -0
- package/dist/components/patterns/status-badge.js.map +1 -0
- package/dist/components/patterns/toggle-row.d.ts +36 -0
- package/dist/components/patterns/toggle-row.js +8 -0
- package/dist/components/patterns/toggle-row.js.map +1 -0
- package/dist/components/patterns/user-avatar.d.ts +34 -0
- package/dist/components/patterns/user-avatar.js +5 -0
- package/dist/components/patterns/user-avatar.js.map +1 -0
- package/dist/components/ui/accessible-icon.d.ts +48 -0
- package/dist/components/ui/accessible-icon.js +3 -0
- package/dist/components/ui/accessible-icon.js.map +1 -0
- package/dist/components/ui/accordion.d.ts +5 -5
- package/dist/components/ui/accordion.js +1 -1
- package/dist/components/ui/alert-dialog.d.ts +10 -10
- package/dist/components/ui/alert-dialog.js +1 -1
- package/dist/components/ui/aspect-ratio.d.ts +2 -2
- package/dist/components/ui/aspect-ratio.js +1 -1
- package/dist/components/ui/avatar.d.ts +4 -4
- package/dist/components/ui/avatar.js +1 -1
- package/dist/components/ui/button.d.ts +73 -8
- package/dist/components/ui/button.js +1 -1
- package/dist/components/ui/calendar.js +2 -2
- package/dist/components/ui/carousel.d.ts +4 -3
- package/dist/components/ui/carousel.js +2 -2
- package/dist/components/ui/checkbox.d.ts +2 -2
- package/dist/components/ui/checkbox.js +1 -1
- package/dist/components/ui/collapsible.d.ts +4 -4
- package/dist/components/ui/collapsible.js +1 -1
- package/dist/components/ui/command-palette.js +3 -3
- package/dist/components/ui/command.d.ts +9 -9
- package/dist/components/ui/command.js +2 -2
- package/dist/components/ui/context-menu.d.ts +15 -15
- package/dist/components/ui/context-menu.js +1 -1
- package/dist/components/ui/date-picker.js +4 -4
- package/dist/components/ui/dialog.d.ts +9 -9
- package/dist/components/ui/dialog.js +1 -1
- package/dist/components/ui/drawer.d.ts +7 -7
- package/dist/components/ui/dropdown-menu.d.ts +15 -15
- package/dist/components/ui/dropdown-menu.js +1 -1
- package/dist/components/ui/hover-card.d.ts +4 -4
- package/dist/components/ui/hover-card.js +1 -1
- package/dist/components/ui/input-otp.d.ts +2 -2
- package/dist/components/ui/label.d.ts +2 -2
- package/dist/components/ui/label.js +1 -1
- package/dist/components/ui/menubar.d.ts +16 -16
- package/dist/components/ui/menubar.js +1 -1
- package/dist/components/ui/navigation-menu.d.ts +9 -9
- package/dist/components/ui/navigation-menu.js +1 -1
- package/dist/components/ui/pagination.js +2 -2
- package/dist/components/ui/password-toggle-field.d.ts +121 -0
- package/dist/components/ui/password-toggle-field.js +4 -0
- package/dist/components/ui/password-toggle-field.js.map +1 -0
- package/dist/components/ui/popover.d.ts +4 -4
- package/dist/components/ui/popover.js +1 -1
- package/dist/components/ui/radio-group.d.ts +3 -3
- package/dist/components/ui/radio-group.js +1 -1
- package/dist/components/ui/resizable.d.ts +1 -1
- package/dist/components/ui/scroll-area.d.ts +60 -3
- package/dist/components/ui/scroll-area.js +1 -1
- package/dist/components/ui/select.d.ts +9 -9
- package/dist/components/ui/select.js +1 -1
- package/dist/components/ui/sheet.d.ts +11 -9
- package/dist/components/ui/sheet.js +1 -1
- package/dist/components/ui/slider.d.ts +2 -2
- package/dist/components/ui/slider.js +1 -1
- package/dist/components/ui/switch.d.ts +2 -2
- package/dist/components/ui/switch.js +1 -1
- package/dist/components/ui/tabs.d.ts +29 -14
- package/dist/components/ui/tabs.js +1 -1
- package/dist/components/ui/toggle-group.d.ts +3 -3
- package/dist/components/ui/toggle-group.js +2 -2
- package/dist/components/ui/toggle.d.ts +2 -2
- package/dist/components/ui/toggle.js +1 -1
- package/dist/components/ui/toolbar.d.ts +104 -0
- package/dist/components/ui/toolbar.js +6 -0
- package/dist/components/ui/toolbar.js.map +1 -0
- package/dist/components/ui/tooltip.d.ts +46 -4
- package/dist/components/ui/tooltip.js +1 -1
- package/dist/components/ui/visually-hidden.d.ts +48 -0
- package/dist/components/ui/visually-hidden.js +4 -0
- package/dist/components/ui/visually-hidden.js.map +1 -0
- package/dist/dashboard-page-C0TihRl5.d.ts +107 -0
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +6 -6
- package/dist/hooks/use-keyboard-navigation.d.ts +58 -2
- package/dist/hooks/use-keyboard-navigation.js +1 -1
- package/dist/hooks/use-resource-page.d.ts +2 -2
- package/dist/hooks/use-resource-page.js +2 -2
- package/dist/hooks/use-view-preference.d.ts +1 -1
- package/dist/hooks/use-view-preference.js +1 -1
- package/dist/index.d.ts +23 -25
- package/dist/index.js +54 -38
- package/dist/spacing-BS6qECD4.d.ts +191 -0
- package/dist/split-Dk9f4Mi0.d.ts +57 -0
- package/dist/{use-resource-page-BXBv_Xah.d.ts → use-resource-page-CPs6wjKt.d.ts} +1 -1
- package/dist/view-settings--KXNT_jE.d.ts +12 -0
- package/package.json +73 -32
- package/dist/chunk-2B3MFHBQ.js.map +0 -1
- package/dist/chunk-2MXMWBDV.js.map +0 -1
- package/dist/chunk-4V4H2ZM7.js.map +0 -1
- package/dist/chunk-5J7BP5DI.js.map +0 -1
- package/dist/chunk-5Q4FABZQ.js.map +0 -1
- package/dist/chunk-63FW5ZUA.js.map +0 -1
- package/dist/chunk-7OBL3H5P.js.map +0 -1
- package/dist/chunk-AUECDWP2.js.map +0 -1
- package/dist/chunk-C6H7AMO4.js.map +0 -1
- package/dist/chunk-EI5EGKHL.js +0 -32
- package/dist/chunk-EI5EGKHL.js.map +0 -1
- package/dist/chunk-IP6TMT3D.js.map +0 -1
- package/dist/chunk-JJ4NOMMI.js +0 -73
- package/dist/chunk-JJ4NOMMI.js.map +0 -1
- package/dist/chunk-JXI2MYL3.js.map +0 -1
- package/dist/chunk-KBS4BHME.js +0 -11
- package/dist/chunk-KBS4BHME.js.map +0 -1
- package/dist/chunk-LRXDZBV2.js +0 -26
- package/dist/chunk-LRXDZBV2.js.map +0 -1
- package/dist/chunk-NJMO3VPA.js.map +0 -1
- package/dist/chunk-OCTV3S4I.js +0 -29
- package/dist/chunk-OCTV3S4I.js.map +0 -1
- package/dist/chunk-QBZMY2AF.js.map +0 -1
- package/dist/chunk-QLCDAFS7.js.map +0 -1
- package/dist/chunk-SBJV3K4G.js.map +0 -1
- package/dist/chunk-SCUT2ZCD.js.map +0 -1
- package/dist/chunk-SVXDWPLO.js.map +0 -1
- package/dist/chunk-T465NJRL.js +0 -134
- package/dist/chunk-T465NJRL.js.map +0 -1
- package/dist/chunk-T5VX5DYO.js.map +0 -1
- package/dist/chunk-TKA4LOMT.js.map +0 -1
- package/dist/chunk-UGHQFQOE.js.map +0 -1
- package/dist/chunk-WALXVR6V.js +0 -9
- package/dist/chunk-WALXVR6V.js.map +0 -1
- package/dist/chunk-WZWR2ELB.js.map +0 -1
- package/dist/chunk-YZEA5TGK.js.map +0 -1
- package/dist/chunk-ZDAT5JDH.js.map +0 -1
- package/dist/chunk-ZJFSZFPI.js.map +0 -1
- package/dist/components/ui/empty-state.d.ts +0 -22
- /package/dist/components/{ui → patterns}/empty-state.js.map +0 -0
- /package/dist/components/{ui → patterns}/form-field.js.map +0 -0
- /package/dist/{ViewToggle-DDe_Luj2.d.ts → view-toggle-DDe_Luj2.d.ts} +0 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
+
|
|
4
|
+
// src/hooks/use-keyboard-navigation.ts
|
|
5
|
+
var INTERACTIVE_TAGS = /* @__PURE__ */ new Set(["BUTTON", "A", "SUMMARY"]);
|
|
6
|
+
var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
|
|
7
|
+
"button",
|
|
8
|
+
"link",
|
|
9
|
+
"checkbox",
|
|
10
|
+
"radio",
|
|
11
|
+
"switch",
|
|
12
|
+
"tab",
|
|
13
|
+
"menuitem",
|
|
14
|
+
"menuitemcheckbox",
|
|
15
|
+
"menuitemradio",
|
|
16
|
+
"option",
|
|
17
|
+
"textbox"
|
|
18
|
+
]);
|
|
19
|
+
var OVERLAY_SELECTOR = '[role="dialog"], [role="alertdialog"], [role="menu"], [role="listbox"]';
|
|
20
|
+
var KEEPS_BACKSPACE_SELECTOR = 'canvas, [role="listbox"], [role="menu"], [role="menubar"], [role="tree"], [role="grid"], [role="combobox"], [role="spinbutton"], [role="slider"], [data-keyboard-nav="off"]';
|
|
21
|
+
function keepsBackspace(el) {
|
|
22
|
+
if (!el || typeof el.closest !== "function") return false;
|
|
23
|
+
return el.closest(KEEPS_BACKSPACE_SELECTOR) !== null;
|
|
24
|
+
}
|
|
25
|
+
function isTypingTarget(el) {
|
|
26
|
+
if (!el || typeof el.tagName !== "string") return false;
|
|
27
|
+
const tag = el.tagName;
|
|
28
|
+
return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || el.isContentEditable === true;
|
|
29
|
+
}
|
|
30
|
+
function measureColumns(container) {
|
|
31
|
+
if (!container) return 1;
|
|
32
|
+
const view = container.ownerDocument?.defaultView;
|
|
33
|
+
if (typeof view?.getComputedStyle !== "function") return 1;
|
|
34
|
+
const template = view.getComputedStyle(container).gridTemplateColumns;
|
|
35
|
+
if (!template || template === "none") return 1;
|
|
36
|
+
if (template.includes("(")) return 1;
|
|
37
|
+
const tracks = template.trim().split(/\s+/).filter(Boolean).length;
|
|
38
|
+
return tracks > 0 ? tracks : 1;
|
|
39
|
+
}
|
|
40
|
+
function ownsItsKeys(el) {
|
|
41
|
+
if (!el || typeof el.tagName !== "string") return false;
|
|
42
|
+
if (INTERACTIVE_TAGS.has(el.tagName)) return true;
|
|
43
|
+
const role = el.getAttribute?.("role");
|
|
44
|
+
if (role && INTERACTIVE_ROLES.has(role)) return true;
|
|
45
|
+
return typeof el.closest === "function" && el.closest(OVERLAY_SELECTOR) !== null;
|
|
46
|
+
}
|
|
47
|
+
function useKeyboardNavigation({
|
|
48
|
+
itemCount,
|
|
49
|
+
onOpen,
|
|
50
|
+
onToggleSelect,
|
|
51
|
+
onBack,
|
|
52
|
+
searchInputRef,
|
|
53
|
+
enabled = true,
|
|
54
|
+
columns,
|
|
55
|
+
overlayOpen = false
|
|
56
|
+
}) {
|
|
57
|
+
const [focusedIndex, setFocusedIndex] = useState(-1);
|
|
58
|
+
const [isActive, setIsActive] = useState(false);
|
|
59
|
+
const containerRef = useRef(null);
|
|
60
|
+
const [scrollRequest, setScrollRequest] = useState(0);
|
|
61
|
+
const scrollInstantRef = useRef(false);
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
setFocusedIndex(-1);
|
|
64
|
+
setIsActive(false);
|
|
65
|
+
}, [itemCount]);
|
|
66
|
+
const scrollToItem = useCallback((index, instant = false) => {
|
|
67
|
+
if (!containerRef.current) return;
|
|
68
|
+
const items = containerRef.current.querySelectorAll("[data-nav-item]");
|
|
69
|
+
const item = items[index];
|
|
70
|
+
if (item) {
|
|
71
|
+
item.scrollIntoView({
|
|
72
|
+
block: "nearest",
|
|
73
|
+
behavior: instant ? "auto" : "smooth"
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}, []);
|
|
77
|
+
const navigableCount = useCallback(() => {
|
|
78
|
+
const container = containerRef.current;
|
|
79
|
+
if (!container) return itemCount;
|
|
80
|
+
const rendered = container.querySelectorAll("[data-nav-item]").length;
|
|
81
|
+
return rendered > 0 ? Math.min(rendered, itemCount) : itemCount;
|
|
82
|
+
}, [itemCount]);
|
|
83
|
+
const firstVisibleIndex = useCallback(() => {
|
|
84
|
+
const container = containerRef.current;
|
|
85
|
+
const view = container?.ownerDocument?.defaultView;
|
|
86
|
+
if (!container || !view) return -1;
|
|
87
|
+
const viewportBottom = view.innerHeight || container.ownerDocument.documentElement.clientHeight;
|
|
88
|
+
if (!viewportBottom) return -1;
|
|
89
|
+
const items = container.querySelectorAll("[data-nav-item]");
|
|
90
|
+
for (let i = 0; i < items.length; i++) {
|
|
91
|
+
const rect = items[i].getBoundingClientRect();
|
|
92
|
+
if (rect.height <= 0 && rect.width <= 0) continue;
|
|
93
|
+
if (rect.bottom > 0 && rect.top < viewportBottom) return i;
|
|
94
|
+
}
|
|
95
|
+
return -1;
|
|
96
|
+
}, []);
|
|
97
|
+
const step = useCallback(
|
|
98
|
+
(delta, instant = false) => {
|
|
99
|
+
const max = navigableCount();
|
|
100
|
+
if (max <= 0) return false;
|
|
101
|
+
const current = focusedIndex;
|
|
102
|
+
const next = current < 0 ? (
|
|
103
|
+
// First move from "nothing focused" adopts the top visible item
|
|
104
|
+
// whichever direction it came from, rather than the row a
|
|
105
|
+
// stride-sized jump would land on.
|
|
106
|
+
Math.min(Math.max(firstVisibleIndex(), 0), max - 1)
|
|
107
|
+
) : delta > 0 ? Math.min(current + delta, max - 1) : Math.max(current + delta, 0);
|
|
108
|
+
if (next === current) {
|
|
109
|
+
if (delta > 0 && max < itemCount) {
|
|
110
|
+
scrollInstantRef.current = instant;
|
|
111
|
+
setScrollRequest((n) => n + 1);
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
setIsActive(true);
|
|
117
|
+
setFocusedIndex(next);
|
|
118
|
+
scrollInstantRef.current = instant;
|
|
119
|
+
setScrollRequest((n) => n + 1);
|
|
120
|
+
return true;
|
|
121
|
+
},
|
|
122
|
+
[focusedIndex, firstVisibleIndex, itemCount, navigableCount]
|
|
123
|
+
);
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (scrollRequest === 0 || focusedIndex < 0) return;
|
|
126
|
+
scrollToItem(focusedIndex, scrollInstantRef.current);
|
|
127
|
+
}, [scrollRequest, focusedIndex, scrollToItem]);
|
|
128
|
+
const columnCount = useCallback(() => {
|
|
129
|
+
if (typeof columns === "number") return Math.max(1, Math.floor(columns));
|
|
130
|
+
return measureColumns(containerRef.current);
|
|
131
|
+
}, [columns]);
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (!enabled) return;
|
|
134
|
+
const handler = (e) => {
|
|
135
|
+
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
136
|
+
const target = e.target;
|
|
137
|
+
if (isTypingTarget(target)) {
|
|
138
|
+
if (e.key === "Escape") {
|
|
139
|
+
target?.blur();
|
|
140
|
+
e.preventDefault();
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (e.key === "Backspace") {
|
|
145
|
+
if (onBack && !keepsBackspace(target)) {
|
|
146
|
+
e.preventDefault();
|
|
147
|
+
onBack(focusedIndex);
|
|
148
|
+
}
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (e.key === "Escape") {
|
|
152
|
+
setFocusedIndex(-1);
|
|
153
|
+
setIsActive(false);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (ownsItsKeys(target)) return;
|
|
157
|
+
if (overlayOpen) return;
|
|
158
|
+
switch (e.key) {
|
|
159
|
+
case "j":
|
|
160
|
+
case "ArrowDown": {
|
|
161
|
+
if (step(columnCount(), e.repeat)) e.preventDefault();
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
case "k":
|
|
165
|
+
case "ArrowUp": {
|
|
166
|
+
if (step(-columnCount(), e.repeat)) e.preventDefault();
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
case "ArrowRight": {
|
|
170
|
+
if (columnCount() <= 1) break;
|
|
171
|
+
if (step(1, e.repeat)) e.preventDefault();
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
case "ArrowLeft": {
|
|
175
|
+
if (columnCount() <= 1) break;
|
|
176
|
+
if (step(-1, e.repeat)) e.preventDefault();
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
case "Enter": {
|
|
180
|
+
if (focusedIndex >= 0 && focusedIndex < navigableCount() && onOpen) {
|
|
181
|
+
e.preventDefault();
|
|
182
|
+
onOpen(focusedIndex);
|
|
183
|
+
}
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case "x": {
|
|
187
|
+
if (focusedIndex >= 0 && focusedIndex < navigableCount() && onToggleSelect) {
|
|
188
|
+
e.preventDefault();
|
|
189
|
+
onToggleSelect(focusedIndex);
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
case "/": {
|
|
194
|
+
if (searchInputRef?.current) {
|
|
195
|
+
e.preventDefault();
|
|
196
|
+
searchInputRef.current.focus();
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
document.addEventListener("keydown", handler);
|
|
203
|
+
return () => document.removeEventListener("keydown", handler);
|
|
204
|
+
}, [
|
|
205
|
+
enabled,
|
|
206
|
+
overlayOpen,
|
|
207
|
+
focusedIndex,
|
|
208
|
+
onOpen,
|
|
209
|
+
onToggleSelect,
|
|
210
|
+
onBack,
|
|
211
|
+
searchInputRef,
|
|
212
|
+
step,
|
|
213
|
+
navigableCount,
|
|
214
|
+
columnCount
|
|
215
|
+
]);
|
|
216
|
+
return {
|
|
217
|
+
focusedIndex,
|
|
218
|
+
setFocusedIndex,
|
|
219
|
+
containerRef,
|
|
220
|
+
isActive
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export { useKeyboardNavigation };
|
|
225
|
+
//# sourceMappingURL=chunk-YJ6MPS6U.js.map
|
|
226
|
+
//# sourceMappingURL=chunk-YJ6MPS6U.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/use-keyboard-navigation.ts"],"names":[],"mappings":"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","file":"chunk-YJ6MPS6U.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { useState, useEffect, useCallback, useRef } from \"react\";\n\n/** Elements that own their own key handling — never steal keys from these. */\nconst INTERACTIVE_TAGS = new Set([\"BUTTON\", \"A\", \"SUMMARY\"]);\nconst INTERACTIVE_ROLES = new Set([\n \"button\",\n \"link\",\n \"checkbox\",\n \"radio\",\n \"switch\",\n \"tab\",\n \"menuitem\",\n \"menuitemcheckbox\",\n \"menuitemradio\",\n \"option\",\n \"textbox\",\n]);\n/** Containers whose contents sit \"above\" the list and own their keys. */\nconst OVERLAY_SELECTOR =\n '[role=\"dialog\"], [role=\"alertdialog\"], [role=\"menu\"], [role=\"listbox\"]';\n\n/**\n * Composite widgets that run their own key handling and may want Backspace\n * for themselves — type-ahead reset in a listbox/menu/tree, value editing in\n * a spinbutton/slider, \"delete selection\" in a canvas-based editor. ⌫ must\n * not be repurposed as \"dismiss the overlay\" while focus sits inside one.\n * A plain button or the dialog container itself is deliberately NOT here:\n * that is the common case after opening a detail panel, and dismissing is\n * exactly what ⌫ means there. `[data-keyboard-nav=\"off\"]` is the explicit\n * escape hatch for anything this list cannot know about.\n */\nconst KEEPS_BACKSPACE_SELECTOR =\n 'canvas, [role=\"listbox\"], [role=\"menu\"], [role=\"menubar\"], [role=\"tree\"],' +\n ' [role=\"grid\"], [role=\"combobox\"], [role=\"spinbutton\"], [role=\"slider\"],' +\n ' [data-keyboard-nav=\"off\"]';\n\n/** Whether `el` sits inside a widget that owns Backspace (see above). */\nfunction keepsBackspace(el: HTMLElement | null): boolean {\n if (!el || typeof el.closest !== \"function\") return false;\n return el.closest(KEEPS_BACKSPACE_SELECTOR) !== null;\n}\n\n/** Text-entry surfaces: every key belongs to them (including Backspace). */\nfunction isTypingTarget(el: HTMLElement | null): boolean {\n if (!el || typeof el.tagName !== \"string\") return false;\n const tag = el.tagName;\n return (\n tag === \"INPUT\" ||\n tag === \"TEXTAREA\" ||\n tag === \"SELECT\" ||\n el.isContentEditable === true\n );\n}\n\n/**\n * Live column count of a navigable container: the number of tracks in its\n * resolved `grid-template-columns`.\n *\n * Measuring beats being told. A responsive ramp (`sm:grid-cols-2\n * lg:grid-cols-3`) has no single column count a caller could pass in — the\n * answer depends on the viewport at the moment the key is pressed, which is\n * exactly what the computed style reports. Anything that isn't a CSS grid (a\n * list view's stacked rows, a bare test container) computes to `none`/empty\n * and counts as one column, preserving flat-list stepping.\n */\nfunction measureColumns(container: HTMLElement | null): number {\n if (!container) return 1;\n const view = container.ownerDocument?.defaultView;\n if (typeof view?.getComputedStyle !== \"function\") return 1;\n const template = view.getComputedStyle(container).gridTemplateColumns;\n if (!template || template === \"none\") return 1;\n // Browsers resolve the track list to used values (\"240px 240px 240px\").\n // An unresolved *specified* value (\"repeat(3, minmax(0, 1fr))\") is not a\n // track list and its spaces don't count tracks — don't guess from it.\n if (template.includes(\"(\")) return 1;\n const tracks = template.trim().split(/\\s+/).filter(Boolean).length;\n return tracks > 0 ? tracks : 1;\n}\n\n/**\n * A focused control (or anything inside a dialog/menu/listbox) owns its own\n * keys — most importantly Enter and Space. Stealing those for the list\n * cursor is what makes an open overlay keyboard-hostile.\n */\nfunction ownsItsKeys(el: HTMLElement | null): boolean {\n if (!el || typeof el.tagName !== \"string\") return false;\n if (INTERACTIVE_TAGS.has(el.tagName)) return true;\n const role = el.getAttribute?.(\"role\");\n if (role && INTERACTIVE_ROLES.has(role)) return true;\n return (\n typeof el.closest === \"function\" && el.closest(OVERLAY_SELECTOR) !== null\n );\n}\n\n/**\n * Vim/Superhuman-style list navigation: j/k (or Arrow Up/Down) move a\n * focused-item cursor *one row at a time*, Enter opens the focused item, x\n * toggles its selection, and Backspace goes \"back\" (e.g. closes an open\n * detail view). In a multi-column grid the vertical keys step by the\n * container's live column count and Arrow Left/Right step by one, so the\n * cursor follows the grid the user can see rather than treating it as a flat\n * list. Intended for list/grid views such as `DataGrid` — attach\n * `containerRef` to the scrollable item container so the column count can be\n * measured and focus changes can scroll the focused item into view.\n *\n * Deliberately inert, so a default-on consumer can't break the surrounding\n * app: modified chords (Ctrl/Meta/Alt) are never captured, text-entry\n * surfaces keep every key, focused controls (or anything inside a\n * dialog/menu/listbox) keep theirs, composite widgets keep Backspace, and a\n * key that *does nothing* is never swallowed — Arrow Up/Down fall through to\n * the browser's page scrolling on an empty list, or at either end of a full\n * one, instead of dying silently.\n *\n * @stability Beta\n */\nexport interface KeyboardNavOptions {\n /** Total number of navigable items */\n itemCount: number;\n /** Called when Enter is pressed on focused item */\n onOpen?: (index: number) => void;\n /** Called when x is pressed on focused item */\n onToggleSelect?: (index: number) => void;\n /**\n * Called when Backspace (⌫) is pressed — the conventional \"go back\" key,\n * e.g. to close an open detail panel/modal and return to the list. Fires\n * regardless of whether an item is currently focused (mirrors Escape),\n * since \"go back\" should still work if a detail view was opened by mouse\n * click rather than keyboard navigation. Not gated behind `focusedIndex`.\n *\n * Backspace is only intercepted (and its default suppressed) while this\n * is supplied — pass it conditionally, i.e. only while there is something\n * to go back from, so the key stays available to the browser and the\n * surrounding app the rest of the time. Even then it is left alone for\n * text-entry surfaces and for composite widgets that use Backspace\n * themselves (see `KEEPS_BACKSPACE_SELECTOR`).\n */\n onBack?: (focusedIndex: number) => void;\n /** Ref to the search input to focus on \"/\" */\n searchInputRef?: React.RefObject<HTMLInputElement | null>;\n /** Whether navigation is enabled. Default true */\n enabled?: boolean;\n /**\n * Columns in the navigable grid. Drives the vertical stride: Arrow\n * Down/Up (and j/k) move by `columns`, Arrow Left/Right by one — so in a\n * 3-up grid ArrowDown moves *down* a row instead of one card to the right.\n *\n * Leave unset (the default) to measure the live count off `containerRef`'s\n * resolved `grid-template-columns` on each keypress, which is the only\n * value that stays correct across a responsive column ramp. Pass a number\n * only to override that measurement. Either way a single-column container\n * behaves exactly as a flat list: stride 1, Left/Right inert.\n */\n columns?: number;\n /**\n * An overlay (detail panel, modal, form) is open above the list. Cursor\n * movement and activation keys are suspended so they can't drive the list\n * hidden behind it, while the dismissal keys (`onBack`/Backspace, Escape)\n * stay live so the overlay can still be closed from the keyboard.\n * Default false.\n */\n overlayOpen?: boolean;\n}\n\n/** @stability Beta */\nexport interface KeyboardNavResult {\n /** Currently focused item index (-1 = none) */\n focusedIndex: number;\n /** Set focused index manually */\n setFocusedIndex: (index: number) => void;\n /** Ref to attach to the grid container for scroll management */\n containerRef: React.RefObject<HTMLDivElement | null>;\n /** Whether keyboard nav is actively engaged (user has pressed j/k) */\n isActive: boolean;\n}\n\n/** @stability Beta */\nexport function useKeyboardNavigation({\n itemCount,\n onOpen,\n onToggleSelect,\n onBack,\n searchInputRef,\n enabled = true,\n columns,\n overlayOpen = false,\n}: KeyboardNavOptions): KeyboardNavResult {\n const [focusedIndex, setFocusedIndex] = useState(-1);\n const [isActive, setIsActive] = useState(false);\n const containerRef = useRef<HTMLDivElement | null>(null);\n /**\n * Scrolling is requested by `step`, not inferred from `focusedIndex`\n * changing, for two reasons. (1) A *clamped* step leaves the index where\n * it was yet must still scroll — bringing the last rendered item back into\n * view is what trips `DataGrid`'s batch observer and lifts the ceiling\n * described on `navigableCount` below. (2) State updaters must be pure;\n * React StrictMode double-invokes them in development, so a scroll called\n * from inside one fires twice. Bumping a nonce keeps the updater pure and\n * moves the scroll into a committed effect, where the row it targets\n * actually exists in the DOM.\n */\n const [scrollRequest, setScrollRequest] = useState(0);\n const scrollInstantRef = useRef(false);\n\n // Reset when items change\n useEffect(() => {\n setFocusedIndex(-1);\n setIsActive(false);\n }, [itemCount]);\n\n const scrollToItem = useCallback((index: number, instant = false) => {\n if (!containerRef.current) return;\n const items = containerRef.current.querySelectorAll(\"[data-nav-item]\");\n const item = items[index] as HTMLElement | undefined;\n if (item) {\n // Key-repeat fires faster than a smooth scroll settles, and a new\n // programmatic scroll can interrupt the in-flight one (MDN\n // scrollIntoView). Instant scroll under repeat lets the batch\n // IntersectionObserver see the sentinel before the next keydown.\n item.scrollIntoView({\n block: \"nearest\",\n behavior: instant ? \"auto\" : \"smooth\",\n });\n }\n }, []);\n\n /**\n * How far the cursor may travel *right now*. A batched grid (see\n * `DataGrid`'s infinite-scroll batching) renders only a slice of\n * `itemCount`, so the DOM — not the data length — is the real ceiling.\n * Walking past the rendered slice would drop the focus ring and leave\n * Enter/x acting on a row the user cannot see.\n *\n * Stopping at the last rendered item is self-healing: `scrollToItem`\n * brings it into view, which trips the batch observer, which renders the\n * next batch — so the next keypress continues where this one stopped.\n * (Do not feed the rendered count into `itemCount` — the reset effect\n * above clears focus whenever `itemCount` changes.)\n */\n const navigableCount = useCallback(() => {\n const container = containerRef.current;\n if (!container) return itemCount;\n const rendered = container.querySelectorAll(\"[data-nav-item]\").length;\n // No nav items marked up (a view that doesn't opt in) — trust itemCount.\n return rendered > 0 ? Math.min(rendered, itemCount) : itemCount;\n }, [itemCount]);\n\n /**\n * Where an *unset* cursor should land on its first move: the first item\n * that is still at or below the top of the viewport, so a user who has\n * scrolled halfway down a long grid isn't yanked back to item 0 by their\n * first ArrowDown. Returns -1 when geometry can't answer (no layout, no\n * container, everything scrolled past), leaving the caller on item 0.\n */\n const firstVisibleIndex = useCallback((): number => {\n const container = containerRef.current;\n const view = container?.ownerDocument?.defaultView;\n if (!container || !view) return -1;\n const viewportBottom =\n view.innerHeight || container.ownerDocument.documentElement.clientHeight;\n if (!viewportBottom) return -1;\n const items = container.querySelectorAll(\"[data-nav-item]\");\n for (let i = 0; i < items.length; i++) {\n const rect = (items[i] as HTMLElement).getBoundingClientRect();\n // A zero-height rect means \"no layout information\" (jsdom, display:none)\n // rather than \"at the very top\" — skip rather than guess.\n if (rect.height <= 0 && rect.width <= 0) continue;\n if (rect.bottom > 0 && rect.top < viewportBottom) return i;\n }\n return -1;\n }, []);\n\n /**\n * Move the cursor by `delta` and report whether the keystroke actually did\n * something. The caller uses the return value to decide whether to\n * `preventDefault()`: a default-on hook that swallows ArrowUp/Down even\n * when it has nothing to move would silently take page scrolling away from\n * every existing consumer — worst of all on an empty page, where there is\n * no cursor at all.\n */\n const step = useCallback(\n (delta: number, instant = false): boolean => {\n const max = navigableCount();\n // Empty / not-yet-mounted list: no cursor exists, so the key is not\n // ours. (Also guards the upward clamp from inventing index 0.)\n if (max <= 0) return false;\n\n const current = focusedIndex;\n const next =\n current < 0\n ? // First move from \"nothing focused\" adopts the top visible item\n // whichever direction it came from, rather than the row a\n // stride-sized jump would land on.\n Math.min(Math.max(firstVisibleIndex(), 0), max - 1)\n : delta > 0\n ? Math.min(current + delta, max - 1)\n : Math.max(current + delta, 0);\n\n if (next === current) {\n // Pinned at the *rendered* ceiling while more rows exist: scrolling\n // the last rendered item into view trips DataGrid's batch observer,\n // so the next keypress continues (see `navigableCount`). That is\n // real work, so the key stays ours.\n if (delta > 0 && max < itemCount) {\n scrollInstantRef.current = instant;\n setScrollRequest((n) => n + 1);\n return true;\n }\n // Genuinely at the top or the end of the data — hand the key back so\n // the browser can scroll the page.\n return false;\n }\n\n setIsActive(true);\n setFocusedIndex(next);\n scrollInstantRef.current = instant;\n setScrollRequest((n) => n + 1);\n return true;\n },\n [focusedIndex, firstVisibleIndex, itemCount, navigableCount],\n );\n\n // Committed scroll: the row exists in the DOM by the time this runs.\n useEffect(() => {\n // 0 = no step taken yet. A negative index is the Escape/itemCount-reset\n // path, where scrolling to a stale row would yank the viewport.\n if (scrollRequest === 0 || focusedIndex < 0) return;\n scrollToItem(focusedIndex, scrollInstantRef.current);\n }, [scrollRequest, focusedIndex, scrollToItem]);\n\n /**\n * Columns to step per vertical key press, measured live unless the caller\n * pinned it with the `columns` option.\n */\n const columnCount = useCallback((): number => {\n if (typeof columns === \"number\") return Math.max(1, Math.floor(columns));\n return measureColumns(containerRef.current);\n }, [columns]);\n\n useEffect(() => {\n if (!enabled) return;\n\n const handler = (e: KeyboardEvent) => {\n // Never hijack a modified chord. Cmd/Ctrl+K (command palettes),\n // Cmd/Ctrl+X (cut), Alt+Arrow (browser history) and friends belong to\n // the app or the browser — a default-on list must not eat them.\n if (e.ctrlKey || e.metaKey || e.altKey) return;\n\n const target = e.target as HTMLElement | null;\n\n // Don't capture when typing in inputs/textareas\n if (isTypingTarget(target)) {\n // Only handle Escape to blur out of search\n if (e.key === \"Escape\") {\n target?.blur();\n e.preventDefault();\n }\n return;\n }\n\n // ── Dismissal keys — live even while an overlay covers the list,\n // since dismissing that overlay is exactly what they are for. Handled\n // ahead of the interactive-target guard below so ⌫ still works when\n // focus sits on the dialog itself (or a button inside it).\n if (e.key === \"Backspace\") {\n if (onBack && !keepsBackspace(target)) {\n e.preventDefault();\n onBack(focusedIndex);\n }\n return;\n }\n if (e.key === \"Escape\") {\n setFocusedIndex(-1);\n setIsActive(false);\n return;\n }\n\n // A focused control owns its own keys — notably Enter/Space. Without\n // this, Enter on a dialog's button would be prevented and re-trigger\n // the list's \"open focused row\" instead of activating the button.\n if (ownsItsKeys(target)) return;\n\n // Everything below moves or acts on the list cursor.\n if (overlayOpen) return;\n\n // Vertical keys move a whole row; horizontal keys move one cell. In a\n // single-column container the two are the same stride, which is why a\n // list keeps behaving exactly as before.\n switch (e.key) {\n case \"j\":\n case \"ArrowDown\": {\n // preventDefault only if the cursor moved: see `step`.\n if (step(columnCount(), e.repeat)) e.preventDefault();\n break;\n }\n case \"k\":\n case \"ArrowUp\": {\n if (step(-columnCount(), e.repeat)) e.preventDefault();\n break;\n }\n case \"ArrowRight\": {\n if (columnCount() <= 1) break;\n if (step(1, e.repeat)) e.preventDefault();\n break;\n }\n case \"ArrowLeft\": {\n if (columnCount() <= 1) break;\n if (step(-1, e.repeat)) e.preventDefault();\n break;\n }\n case \"Enter\": {\n // Re-check the live rendered ceiling — focus can outlive a\n // shrunk batch (filter/reset) without `itemCount` changing.\n if (\n focusedIndex >= 0 &&\n focusedIndex < navigableCount() &&\n onOpen\n ) {\n e.preventDefault();\n onOpen(focusedIndex);\n }\n break;\n }\n case \"x\": {\n if (\n focusedIndex >= 0 &&\n focusedIndex < navigableCount() &&\n onToggleSelect\n ) {\n e.preventDefault();\n onToggleSelect(focusedIndex);\n }\n break;\n }\n case \"/\": {\n if (searchInputRef?.current) {\n e.preventDefault();\n searchInputRef.current.focus();\n }\n break;\n }\n }\n };\n\n document.addEventListener(\"keydown\", handler);\n return () => document.removeEventListener(\"keydown\", handler);\n }, [\n enabled,\n overlayOpen,\n focusedIndex,\n onOpen,\n onToggleSelect,\n onBack,\n searchInputRef,\n step,\n navigableCount,\n columnCount,\n ]);\n\n return {\n focusedIndex,\n setFocusedIndex,\n containerRef,\n isActive,\n };\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Spinner } from './chunk-OVU3Z2MT.js';
|
|
2
|
+
import { cn } from './chunk-NZ5WBA4R.js';
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var pageLoadingVariants = cva(
|
|
7
|
+
"flex flex-col items-center justify-center gap-3 px-4 text-center",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
page: "min-h-[50vh]",
|
|
12
|
+
section: "min-h-48 py-12"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
variant: "page"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
function PageLoading({ label, variant, className, testID }) {
|
|
21
|
+
return /* @__PURE__ */ jsxs(
|
|
22
|
+
"div",
|
|
23
|
+
{
|
|
24
|
+
"data-slot": "page-loading",
|
|
25
|
+
"data-testid": testID,
|
|
26
|
+
role: "status",
|
|
27
|
+
className: cn(pageLoadingVariants({ variant }), className),
|
|
28
|
+
children: [
|
|
29
|
+
/* @__PURE__ */ jsx(Spinner, { size: variant === "section" ? "default" : "lg", "aria-hidden": "true" }),
|
|
30
|
+
label ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: label }) : /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { PageLoading, pageLoadingVariants };
|
|
37
|
+
//# sourceMappingURL=chunk-YRYQXU3G.js.map
|
|
38
|
+
//# sourceMappingURL=chunk-YRYQXU3G.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/patterns/page-loading.tsx"],"names":[],"mappings":";;;;;AAKA,IAAM,mBAAA,GAAsB,GAAA;AAAA,EAC1B,kEAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,cAAA;AAAA,QACN,OAAA,EAAS;AAAA;AACX,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS;AAAA;AACX;AAEJ;AAkBO,SAAS,YAAY,EAAE,KAAA,EAAO,OAAA,EAAS,SAAA,EAAW,QAAO,EAAqB;AACnF,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,cAAA;AAAA,MACV,aAAA,EAAa,MAAA;AAAA,MACb,IAAA,EAAK,QAAA;AAAA,MACL,WAAW,EAAA,CAAG,mBAAA,CAAoB,EAAE,OAAA,EAAS,GAAG,SAAS,CAAA;AAAA,MAEzD,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,WAAQ,IAAA,EAAM,OAAA,KAAY,YAAY,SAAA,GAAY,IAAA,EAAM,eAAY,MAAA,EAAO,CAAA;AAAA,QAC3E,KAAA,mBACC,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,+BAAA,EAAiC,QAAA,EAAA,KAAA,EAAM,CAAA,mBAEpD,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EAAU,QAAA,EAAA,SAAA,EAAO;AAAA;AAAA;AAAA,GAErC;AAEJ","file":"chunk-YRYQXU3G.js","sourcesContent":["import * as React from \"react\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport { Spinner } from \"../ui/spinner\";\nimport { cn } from \"../../utils\";\n\nconst pageLoadingVariants = cva(\n \"flex flex-col items-center justify-center gap-3 px-4 text-center\",\n {\n variants: {\n variant: {\n page: \"min-h-[50vh]\",\n section: \"min-h-48 py-12\",\n },\n },\n defaultVariants: {\n variant: \"page\",\n },\n },\n);\n\nexport interface PageLoadingProps extends VariantProps<typeof pageLoadingVariants> {\n /** Optional message shown under the spinner (e.g. \"Loading dashboard…\"). */\n label?: string;\n className?: string;\n /** Stable test/automation selector (emitted as `data-testid`). */\n testID?: string;\n}\n\n/**\n * PageLoading — full-page or in-section loading state: a centered `Spinner`\n * with an optional message. The loading-state counterpart to `EmptyState`.\n * Reach for `Skeleton` instead when the placeholder should mimic the shape\n * of the content that's arriving rather than a generic wait state.\n *\n * @stability Beta\n */\nexport function PageLoading({ label, variant, className, testID }: PageLoadingProps) {\n return (\n <div\n data-slot=\"page-loading\"\n data-testid={testID}\n role=\"status\"\n className={cn(pageLoadingVariants({ variant }), className)}\n >\n <Spinner size={variant === \"section\" ? \"default\" : \"lg\"} aria-hidden=\"true\" />\n {label ? (\n <p className=\"text-sm text-muted-foreground\">{label}</p>\n ) : (\n <span className=\"sr-only\">Loading</span>\n )}\n </div>\n );\n}\n\nexport { pageLoadingVariants };\n"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from './chunk-NZ5WBA4R.js';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import
|
|
4
|
+
import { Accordion as Accordion$1 } from 'radix-ui';
|
|
5
5
|
import { ChevronDown } from 'lucide-react';
|
|
6
6
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
7
|
|
|
8
|
-
var Accordion =
|
|
8
|
+
var Accordion = Accordion$1.Root;
|
|
9
9
|
var AccordionItem = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
10
|
-
|
|
10
|
+
Accordion$1.Item,
|
|
11
11
|
{
|
|
12
12
|
ref,
|
|
13
13
|
className: cn("border-b", className),
|
|
@@ -15,8 +15,8 @@ var AccordionItem = React.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
15
15
|
}
|
|
16
16
|
));
|
|
17
17
|
AccordionItem.displayName = "AccordionItem";
|
|
18
|
-
var AccordionTrigger = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
19
|
-
|
|
18
|
+
var AccordionTrigger = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(Accordion$1.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
|
|
19
|
+
Accordion$1.Trigger,
|
|
20
20
|
{
|
|
21
21
|
ref,
|
|
22
22
|
className: cn(
|
|
@@ -30,9 +30,9 @@ var AccordionTrigger = React.forwardRef(({ className, children, ...props }, ref)
|
|
|
30
30
|
]
|
|
31
31
|
}
|
|
32
32
|
) }));
|
|
33
|
-
AccordionTrigger.displayName =
|
|
33
|
+
AccordionTrigger.displayName = Accordion$1.Trigger.displayName;
|
|
34
34
|
var AccordionContent = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
35
|
-
|
|
35
|
+
Accordion$1.Content,
|
|
36
36
|
{
|
|
37
37
|
ref,
|
|
38
38
|
className: "overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
|
|
@@ -40,8 +40,8 @@ var AccordionContent = React.forwardRef(({ className, children, ...props }, ref)
|
|
|
40
40
|
children: /* @__PURE__ */ jsx("div", { className: cn("pb-4 pt-0", className), children })
|
|
41
41
|
}
|
|
42
42
|
));
|
|
43
|
-
AccordionContent.displayName =
|
|
43
|
+
AccordionContent.displayName = Accordion$1.Content.displayName;
|
|
44
44
|
|
|
45
45
|
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };
|
|
46
|
-
//# sourceMappingURL=chunk-
|
|
47
|
-
//# sourceMappingURL=chunk-
|
|
46
|
+
//# sourceMappingURL=chunk-YWFPMND7.js.map
|
|
47
|
+
//# sourceMappingURL=chunk-YWFPMND7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/accordion.tsx"],"names":["AccordionPrimitive"],"mappings":";;;;;;AAOA,IAAM,YAAYA,WAAA,CAAmB;AAErC,IAAM,aAAA,GAAsB,iBAG1B,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC1B,GAAA;AAAA,EAACA,WAAA,CAAmB,IAAA;AAAA,EAAnB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,UAAA,EAAY,SAAS,CAAA;AAAA,IAClC,GAAG;AAAA;AACN,CACD;AACD,aAAA,CAAc,WAAA,GAAc,eAAA;AAE5B,IAAM,gBAAA,GAAyB,KAAA,CAAA,UAAA,CAG7B,CAAC,EAAE,WAAW,QAAA,EAAU,GAAG,KAAA,EAAM,EAAG,wBACpC,GAAA,CAACA,WAAA,CAAmB,MAAA,EAAnB,EAA0B,WAAU,MAAA,EACnC,QAAA,kBAAA,IAAA;AAAA,EAACA,WAAA,CAAmB,OAAA;AAAA,EAAnB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,8HAAA;AAAA,MACA;AAAA,KACF;AAAA,IACC,GAAG,KAAA;AAAA,IAEH,QAAA,EAAA;AAAA,MAAA,QAAA;AAAA,sBACD,GAAA,CAAC,WAAA,EAAA,EAAY,SAAA,EAAU,oDAAA,EAAqD;AAAA;AAAA;AAC9E,CAAA,EACF,CACD;AACD,gBAAA,CAAiB,WAAA,GAAcA,YAAmB,OAAA,CAAQ,WAAA;AAE1D,IAAM,gBAAA,GAAyB,iBAG7B,CAAC,EAAE,WAAW,QAAA,EAAU,GAAG,KAAA,EAAM,EAAG,GAAA,qBACpC,GAAA;AAAA,EAACA,WAAA,CAAmB,OAAA;AAAA,EAAnB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAU,0HAAA;AAAA,IACT,GAAG,KAAA;AAAA,IAEJ,8BAAC,KAAA,EAAA,EAAI,SAAA,EAAW,GAAG,WAAA,EAAa,SAAS,GAAI,QAAA,EAAS;AAAA;AACxD,CACD;AACD,gBAAA,CAAiB,WAAA,GAAcA,YAAmB,OAAA,CAAQ,WAAA","file":"chunk-YWFPMND7.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\nimport { ChevronDown } from \"lucide-react\";\nimport { cn } from \"../../utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n"]}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { toggleVariants } from './chunk-C46ITXE4.js';
|
|
3
|
+
import { buttonVariants } from './chunk-NWSCYLPT.js';
|
|
4
|
+
import { cn } from './chunk-NZ5WBA4R.js';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { Toolbar as Toolbar$1 } from 'radix-ui';
|
|
7
|
+
import { cva } from 'class-variance-authority';
|
|
8
|
+
import { jsx } from 'react/jsx-runtime';
|
|
9
|
+
|
|
10
|
+
var toolbarVariants = cva(
|
|
11
|
+
"flex items-center gap-1 rounded-md border border-border bg-background p-1",
|
|
12
|
+
{
|
|
13
|
+
variants: {
|
|
14
|
+
orientation: {
|
|
15
|
+
horizontal: "flex-row",
|
|
16
|
+
vertical: "w-fit flex-col"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
defaultVariants: {
|
|
20
|
+
orientation: "horizontal"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
var Toolbar = React.forwardRef(({ className, orientation = "horizontal", testID, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
25
|
+
Toolbar$1.Root,
|
|
26
|
+
{
|
|
27
|
+
ref,
|
|
28
|
+
orientation,
|
|
29
|
+
"data-testid": testID,
|
|
30
|
+
className: cn(toolbarVariants({ orientation }), className),
|
|
31
|
+
...props
|
|
32
|
+
}
|
|
33
|
+
));
|
|
34
|
+
Toolbar.displayName = Toolbar$1.Root.displayName;
|
|
35
|
+
var ToolbarButton = React.forwardRef(({ className, variant = "ghost", size = "sm", testID, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
36
|
+
Toolbar$1.Button,
|
|
37
|
+
{
|
|
38
|
+
ref,
|
|
39
|
+
"data-testid": testID,
|
|
40
|
+
className: cn(buttonVariants({ variant, size }), className),
|
|
41
|
+
...props
|
|
42
|
+
}
|
|
43
|
+
));
|
|
44
|
+
ToolbarButton.displayName = Toolbar$1.Button.displayName;
|
|
45
|
+
var ToolbarLink = React.forwardRef(({ className, testID, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
46
|
+
Toolbar$1.Link,
|
|
47
|
+
{
|
|
48
|
+
ref,
|
|
49
|
+
"data-testid": testID,
|
|
50
|
+
className: cn(
|
|
51
|
+
"inline-flex h-9 items-center justify-center gap-2 rounded-md px-3 text-sm font-medium text-foreground underline-offset-4 ring-offset-background transition-colors hover:bg-accent hover:text-accent-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
52
|
+
className
|
|
53
|
+
),
|
|
54
|
+
...props
|
|
55
|
+
}
|
|
56
|
+
));
|
|
57
|
+
ToolbarLink.displayName = Toolbar$1.Link.displayName;
|
|
58
|
+
var ToolbarSeparator = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
59
|
+
Toolbar$1.Separator,
|
|
60
|
+
{
|
|
61
|
+
ref,
|
|
62
|
+
className: cn(
|
|
63
|
+
"shrink-0 bg-border",
|
|
64
|
+
"data-[orientation=vertical]:mx-1 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-4 data-[orientation=vertical]:w-px",
|
|
65
|
+
"data-[orientation=horizontal]:my-1 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full",
|
|
66
|
+
className
|
|
67
|
+
),
|
|
68
|
+
...props
|
|
69
|
+
}
|
|
70
|
+
));
|
|
71
|
+
ToolbarSeparator.displayName = Toolbar$1.Separator.displayName;
|
|
72
|
+
var ToolbarToggleGroup = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
73
|
+
Toolbar$1.ToggleGroup,
|
|
74
|
+
{
|
|
75
|
+
ref,
|
|
76
|
+
className: cn("flex items-center gap-1", className),
|
|
77
|
+
...props
|
|
78
|
+
}
|
|
79
|
+
));
|
|
80
|
+
ToolbarToggleGroup.displayName = Toolbar$1.ToggleGroup.displayName;
|
|
81
|
+
var ToolbarToggleItem = React.forwardRef(({ className, variant, size = "sm", testID, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
82
|
+
Toolbar$1.ToggleItem,
|
|
83
|
+
{
|
|
84
|
+
ref,
|
|
85
|
+
"data-testid": testID,
|
|
86
|
+
className: cn(toggleVariants({ variant, size }), className),
|
|
87
|
+
...props
|
|
88
|
+
}
|
|
89
|
+
));
|
|
90
|
+
ToolbarToggleItem.displayName = Toolbar$1.ToggleItem.displayName;
|
|
91
|
+
|
|
92
|
+
export { Toolbar, ToolbarButton, ToolbarLink, ToolbarSeparator, ToolbarToggleGroup, ToolbarToggleItem, toolbarVariants };
|
|
93
|
+
//# sourceMappingURL=chunk-YYEGAFUE.js.map
|
|
94
|
+
//# sourceMappingURL=chunk-YYEGAFUE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/toolbar.tsx"],"names":["ToolbarPrimitive"],"mappings":"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","file":"chunk-YYEGAFUE.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Toolbar as ToolbarPrimitive } from \"radix-ui\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\n\nimport { cn } from \"../../utils\";\nimport { buttonVariants } from \"./button\";\nimport { toggleVariants } from \"./toggle\";\n\nexport const toolbarVariants = cva(\n \"flex items-center gap-1 rounded-md border border-border bg-background p-1\",\n {\n variants: {\n orientation: {\n horizontal: \"flex-row\",\n vertical: \"w-fit flex-col\",\n },\n },\n defaultVariants: {\n orientation: \"horizontal\",\n },\n }\n);\n\nexport interface ToolbarProps\n extends React.ComponentPropsWithoutRef<typeof ToolbarPrimitive.Root> {\n /** Stable test/automation selector (emitted as `data-testid`). */\n testID?: string;\n}\n\n/**\n * Toolbar — a grouped set of controls that behaves as ONE tab stop.\n *\n * This is a primitive, not a layout, and the distinction is the whole reason\n * it wraps Radix instead of a `<div className=\"flex gap-1\">`. Radix's Toolbar\n * owns a roving tabindex: Tab moves into and out of the whole group, and\n * Arrow/Home/End move between the items inside it. A layout, by the framework's\n * own definition, \"positions things without knowing what they are\" — this one\n * knows its children are focusable controls and manages their focus, so it\n * fails that test and passes the primitive one.\n *\n * `orientation` is passed to BOTH Radix (which uses it to decide whether\n * Left/Right or Up/Down are the navigation keys) and the CVA class (which uses\n * it to decide the flex direction). Splitting those would let the visual axis\n * and the keyboard axis disagree — arrows moving \"down\" a row of buttons.\n *\n * @stability Beta\n */\nexport const Toolbar = React.forwardRef<\n React.ComponentRef<typeof ToolbarPrimitive.Root>,\n ToolbarProps\n>(({ className, orientation = \"horizontal\", testID, ...props }, ref) => (\n <ToolbarPrimitive.Root\n ref={ref}\n orientation={orientation}\n data-testid={testID}\n className={cn(toolbarVariants({ orientation }), className)}\n {...props}\n />\n));\nToolbar.displayName = ToolbarPrimitive.Root.displayName;\n\nexport interface ToolbarButtonProps\n extends React.ComponentPropsWithoutRef<typeof ToolbarPrimitive.Button>,\n VariantProps<typeof buttonVariants> {\n /** Stable test/automation selector (emitted as `data-testid`). */\n testID?: string;\n}\n\n/**\n * ToolbarButton — a button that participates in the toolbar's roving tabindex.\n *\n * Styling reuses `buttonVariants` rather than declaring a second button look:\n * per the framework's \"one home per concept\", the question \"what does a button\n * look like?\" already has an answer. Only the DEFAULTS differ — `ghost`/`sm`,\n * because a toolbar is a dense strip of controls, not a page's primary action —\n * and both remain overridable.\n *\n * @stability Beta\n */\nexport const ToolbarButton = React.forwardRef<\n React.ComponentRef<typeof ToolbarPrimitive.Button>,\n ToolbarButtonProps\n>(({ className, variant = \"ghost\", size = \"sm\", testID, ...props }, ref) => (\n <ToolbarPrimitive.Button\n ref={ref}\n data-testid={testID}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n />\n));\nToolbarButton.displayName = ToolbarPrimitive.Button.displayName;\n\nexport interface ToolbarLinkProps\n extends React.ComponentPropsWithoutRef<typeof ToolbarPrimitive.Link> {\n /** Stable test/automation selector (emitted as `data-testid`). */\n testID?: string;\n}\n\n/**\n * ToolbarLink — an anchor inside the toolbar's roving tabindex.\n *\n * Kept distinct from `ToolbarButton` because the element matters: a link\n * navigates and must stay an `<a>` for middle-click, \"open in new tab\" and the\n * screen-reader link rotor. Radix also gives it the toolbar's Enter/Space\n * handling without turning it into a button.\n *\n * @stability Beta\n */\nexport const ToolbarLink = React.forwardRef<\n React.ComponentRef<typeof ToolbarPrimitive.Link>,\n ToolbarLinkProps\n>(({ className, testID, ...props }, ref) => (\n <ToolbarPrimitive.Link\n ref={ref}\n data-testid={testID}\n className={cn(\n \"inline-flex h-9 items-center justify-center gap-2 rounded-md px-3 text-sm font-medium text-foreground underline-offset-4 ring-offset-background transition-colors hover:bg-accent hover:text-accent-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n className\n )}\n {...props}\n />\n));\nToolbarLink.displayName = ToolbarPrimitive.Link.displayName;\n\nexport interface ToolbarSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof ToolbarPrimitive.Separator> {}\n\n/**\n * ToolbarSeparator — a decorative divider between toolbar groups.\n *\n * Radix excludes it from the roving tabindex, so arrow keys skip straight over\n * it instead of landing on a 1px line.\n *\n * Note the inverted axis, which is easy to get backwards: Radix gives the\n * separator the orientation PERPENDICULAR to the toolbar's, so a horizontal\n * toolbar contains separators with `data-orientation=\"vertical\"`. The classes\n * below are keyed on the separator's own orientation accordingly — a vertical\n * separator is the tall thin rule.\n *\n * @stability Beta\n */\nexport const ToolbarSeparator = React.forwardRef<\n React.ComponentRef<typeof ToolbarPrimitive.Separator>,\n ToolbarSeparatorProps\n>(({ className, ...props }, ref) => (\n <ToolbarPrimitive.Separator\n ref={ref}\n className={cn(\n \"shrink-0 bg-border\",\n \"data-[orientation=vertical]:mx-1 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-4 data-[orientation=vertical]:w-px\",\n \"data-[orientation=horizontal]:my-1 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full\",\n className\n )}\n {...props}\n />\n));\nToolbarSeparator.displayName = ToolbarPrimitive.Separator.displayName;\n\n/**\n * ToolbarToggleGroup — a set of pressed/unpressed controls inside a toolbar\n * (the classic bold / italic / underline cluster).\n *\n * @stability Beta\n */\nexport const ToolbarToggleGroup = React.forwardRef<\n React.ComponentRef<typeof ToolbarPrimitive.ToggleGroup>,\n React.ComponentPropsWithoutRef<typeof ToolbarPrimitive.ToggleGroup>\n>(({ className, ...props }, ref) => (\n <ToolbarPrimitive.ToggleGroup\n ref={ref}\n className={cn(\"flex items-center gap-1\", className)}\n {...props}\n />\n));\nToolbarToggleGroup.displayName = ToolbarPrimitive.ToggleGroup.displayName;\n\nexport interface ToolbarToggleItemProps\n extends React.ComponentPropsWithoutRef<typeof ToolbarPrimitive.ToggleItem>,\n VariantProps<typeof toggleVariants> {\n /** Stable test/automation selector (emitted as `data-testid`). */\n testID?: string;\n}\n\n/**\n * ToolbarToggleItem — one member of a `ToolbarToggleGroup`.\n *\n * Reuses `toggleVariants` for the same reason `ToolbarButton` reuses\n * `buttonVariants`: `Toggle` already answers \"what does a pressed control look\n * like?\", and a second answer is how two implementations get born.\n *\n * @stability Beta\n */\nexport const ToolbarToggleItem = React.forwardRef<\n React.ComponentRef<typeof ToolbarPrimitive.ToggleItem>,\n ToolbarToggleItemProps\n>(({ className, variant, size = \"sm\", testID, ...props }, ref) => (\n <ToolbarPrimitive.ToggleItem\n ref={ref}\n data-testid={testID}\n className={cn(toggleVariants({ variant, size }), className)}\n {...props}\n />\n));\nToolbarToggleItem.displayName = ToolbarPrimitive.ToggleItem.displayName;\n"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from './chunk-NZ5WBA4R.js';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import
|
|
4
|
+
import { RadioGroup as RadioGroup$1 } from 'radix-ui';
|
|
5
5
|
import { Circle } from 'lucide-react';
|
|
6
6
|
import { jsx } from 'react/jsx-runtime';
|
|
7
7
|
|
|
8
8
|
var RadioGroup = React.forwardRef(({ className, ...props }, ref) => {
|
|
9
9
|
return /* @__PURE__ */ jsx(
|
|
10
|
-
|
|
10
|
+
RadioGroup$1.Root,
|
|
11
11
|
{
|
|
12
12
|
className: cn("grid gap-2", className),
|
|
13
13
|
...props,
|
|
@@ -15,10 +15,10 @@ var RadioGroup = React.forwardRef(({ className, ...props }, ref) => {
|
|
|
15
15
|
}
|
|
16
16
|
);
|
|
17
17
|
});
|
|
18
|
-
RadioGroup.displayName =
|
|
18
|
+
RadioGroup.displayName = RadioGroup$1.Root.displayName;
|
|
19
19
|
var RadioGroupItem = React.forwardRef(({ className, ...props }, ref) => {
|
|
20
20
|
return /* @__PURE__ */ jsx(
|
|
21
|
-
|
|
21
|
+
RadioGroup$1.Item,
|
|
22
22
|
{
|
|
23
23
|
ref,
|
|
24
24
|
className: cn(
|
|
@@ -26,12 +26,12 @@ var RadioGroupItem = React.forwardRef(({ className, ...props }, ref) => {
|
|
|
26
26
|
className
|
|
27
27
|
),
|
|
28
28
|
...props,
|
|
29
|
-
children: /* @__PURE__ */ jsx(
|
|
29
|
+
children: /* @__PURE__ */ jsx(RadioGroup$1.Indicator, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(Circle, { className: "h-2.5 w-2.5 fill-current text-current" }) })
|
|
30
30
|
}
|
|
31
31
|
);
|
|
32
32
|
});
|
|
33
|
-
RadioGroupItem.displayName =
|
|
33
|
+
RadioGroupItem.displayName = RadioGroup$1.Item.displayName;
|
|
34
34
|
|
|
35
35
|
export { RadioGroup, RadioGroupItem };
|
|
36
|
-
//# sourceMappingURL=chunk-
|
|
37
|
-
//# sourceMappingURL=chunk-
|
|
36
|
+
//# sourceMappingURL=chunk-ZZ7H7VVX.js.map
|
|
37
|
+
//# sourceMappingURL=chunk-ZZ7H7VVX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/radio-group.tsx"],"names":["RadioGroupPrimitive"],"mappings":";;;;;;AAOA,IAAM,UAAA,GAAmB,iBAGvB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,KAAQ;AAClC,EAAA,uBACE,GAAA;AAAA,IAACA,YAAA,CAAoB,IAAA;AAAA,IAApB;AAAA,MACC,SAAA,EAAW,EAAA,CAAG,YAAA,EAAc,SAAS,CAAA;AAAA,MACpC,GAAG,KAAA;AAAA,MACJ;AAAA;AAAA,GACF;AAEJ,CAAC;AACD,UAAA,CAAW,WAAA,GAAcA,aAAoB,IAAA,CAAK,WAAA;AAElD,IAAM,cAAA,GAAuB,iBAG3B,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,KAAQ;AAClC,EAAA,uBACE,GAAA;AAAA,IAACA,YAAA,CAAoB,IAAA;AAAA,IAApB;AAAA,MACC,GAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,0OAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEJ,QAAA,kBAAA,GAAA,CAACA,YAAA,CAAoB,SAAA,EAApB,EAA8B,SAAA,EAAU,oCACvC,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAO,SAAA,EAAU,uCAAA,EAAwC,CAAA,EAC5D;AAAA;AAAA,GACF;AAEJ,CAAC;AACD,cAAA,CAAe,WAAA,GAAcA,aAAoB,IAAA,CAAK,WAAA","file":"chunk-ZZ7H7VVX.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { RadioGroup as RadioGroupPrimitive } from \"radix-ui\";\nimport { Circle } from \"lucide-react\";\nimport { cn } from \"../../utils\";\n\nconst RadioGroup = React.forwardRef<\n React.ComponentRef<typeof RadioGroupPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>\n>(({ className, ...props }, ref) => {\n return (\n <RadioGroupPrimitive.Root\n className={cn(\"grid gap-2\", className)}\n {...props}\n ref={ref}\n />\n );\n});\nRadioGroup.displayName = RadioGroupPrimitive.Root.displayName;\n\nconst RadioGroupItem = React.forwardRef<\n React.ComponentRef<typeof RadioGroupPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>\n>(({ className, ...props }, ref) => {\n return (\n <RadioGroupPrimitive.Item\n ref={ref}\n className={cn(\n \"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator className=\"flex items-center justify-center\">\n <Circle className=\"h-2.5 w-2.5 fill-current text-current\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n );\n});\nRadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;\n\nexport { RadioGroup, RadioGroupItem };\n"]}
|