@marktiderman/genesis-ui 1.2.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-AI6CCNWK.js → chunk-6NPEMLBA.js} +2 -2
- package/dist/chunk-6NPEMLBA.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-UKSBLFEK.js → chunk-6XPMU65K.js} +5 -5
- package/dist/{chunk-UKSBLFEK.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-O4B5ALO7.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-CNTWQSUT.js +65 -0
- package/dist/chunk-CNTWQSUT.js.map +1 -0
- package/dist/chunk-D2LIXA2Y.js +65 -0
- package/dist/chunk-D2LIXA2Y.js.map +1 -0
- package/dist/{chunk-FCGFG4RV.js → chunk-D4JTQYP5.js} +3 -3
- package/dist/{chunk-FCGFG4RV.js.map → chunk-D4JTQYP5.js.map} +1 -1
- 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-GCQFVMPI.js +56 -0
- package/dist/chunk-GCQFVMPI.js.map +1 -0
- package/dist/{chunk-LDPPIBIJ.js → chunk-IJCT5IJD.js} +3 -3
- package/dist/{chunk-LDPPIBIJ.js.map → chunk-IJCT5IJD.js.map} +1 -1
- package/dist/{chunk-DGRHPJ3M.js → chunk-J6FBA7PH.js} +3 -3
- package/dist/{chunk-DGRHPJ3M.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-I6JQHP6D.js → chunk-NWSCYLPT.js} +78 -17
- 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 +223 -74
- package/dist/components/data/index.js +504 -539
- 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 +75 -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.d.ts +30 -0
- package/dist/components/ui/command-palette.js +6 -0
- package/dist/components/ui/command-palette.js.map +1 -0
- 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 +5 -3
- package/dist/hooks/index.js +10 -5
- package/dist/hooks/use-data-filters.d.ts +1 -1
- package/dist/hooks/use-data-filters.js +2 -2
- 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 +3 -2
- package/dist/hooks/use-resource-page.js +2 -2
- package/dist/hooks/use-saved-views.d.ts +28 -0
- package/dist/hooks/use-saved-views.js +3 -0
- package/dist/hooks/use-saved-views.js.map +1 -0
- package/dist/hooks/use-view-preference.d.ts +1 -1
- package/dist/hooks/use-view-preference.js +1 -1
- package/dist/index.d.ts +25 -26
- package/dist/index.js +55 -38
- package/dist/{navigation-qI86Ldug.d.ts → navigation-CpOEyUSb.d.ts} +4 -0
- package/dist/spacing-BS6qECD4.d.ts +191 -0
- package/dist/split-Dk9f4Mi0.d.ts +57 -0
- package/dist/{use-resource-page-B-CFcikK.d.ts → use-resource-page-CPs6wjKt.d.ts} +10 -2
- package/dist/view-settings--KXNT_jE.d.ts +12 -0
- package/package.json +77 -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-AI6CCNWK.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-I6JQHP6D.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-O4B5ALO7.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/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,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandShortcut } from './chunk-SEFK4NZV.js';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { useState, useEffect } from 'react';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function CommandPalette({
|
|
8
|
+
open,
|
|
9
|
+
onOpenChange,
|
|
10
|
+
commands,
|
|
11
|
+
placeholder = "Type a command or search\u2026",
|
|
12
|
+
emptyMessage = "No results found.",
|
|
13
|
+
title = "Command palette"
|
|
14
|
+
}) {
|
|
15
|
+
const groups = React.useMemo(() => {
|
|
16
|
+
const map = /* @__PURE__ */ new Map();
|
|
17
|
+
for (const cmd of commands) {
|
|
18
|
+
const key = cmd.group ?? "Actions";
|
|
19
|
+
const list = map.get(key) ?? [];
|
|
20
|
+
list.push(cmd);
|
|
21
|
+
map.set(key, list);
|
|
22
|
+
}
|
|
23
|
+
return map;
|
|
24
|
+
}, [commands]);
|
|
25
|
+
return /* @__PURE__ */ jsxs(CommandDialog, { open, onOpenChange, children: [
|
|
26
|
+
/* @__PURE__ */ jsx(CommandInput, { placeholder, "aria-label": title }),
|
|
27
|
+
/* @__PURE__ */ jsxs(CommandList, { children: [
|
|
28
|
+
/* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
|
|
29
|
+
Array.from(groups.entries()).map(([group, items]) => /* @__PURE__ */ jsx(CommandGroup, { heading: group, children: items.map((cmd) => /* @__PURE__ */ jsxs(
|
|
30
|
+
CommandItem,
|
|
31
|
+
{
|
|
32
|
+
value: `${cmd.id} ${cmd.label}`,
|
|
33
|
+
onSelect: () => {
|
|
34
|
+
onOpenChange(false);
|
|
35
|
+
cmd.onSelect();
|
|
36
|
+
},
|
|
37
|
+
children: [
|
|
38
|
+
cmd.label,
|
|
39
|
+
cmd.shortcut ? /* @__PURE__ */ jsx(CommandShortcut, { children: cmd.shortcut }) : null
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
cmd.id
|
|
43
|
+
)) }, group))
|
|
44
|
+
] })
|
|
45
|
+
] });
|
|
46
|
+
}
|
|
47
|
+
function useCommandPaletteHotkey(enabled = true) {
|
|
48
|
+
const [open, setOpen] = useState(false);
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (!enabled) return;
|
|
51
|
+
const onKeyDown = (e) => {
|
|
52
|
+
if (e.key.toLowerCase() !== "k") return;
|
|
53
|
+
if (!(e.metaKey || e.ctrlKey)) return;
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
setOpen((prev) => !prev);
|
|
56
|
+
};
|
|
57
|
+
window.addEventListener("keydown", onKeyDown);
|
|
58
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
59
|
+
}, [enabled]);
|
|
60
|
+
return [open, setOpen];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { CommandPalette, useCommandPaletteHotkey };
|
|
64
|
+
//# sourceMappingURL=chunk-CNTWQSUT.js.map
|
|
65
|
+
//# sourceMappingURL=chunk-CNTWQSUT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/command-palette.tsx"],"names":[],"mappings":";;;;;AAmCO,SAAS,cAAA,CAAe;AAAA,EAC7B,IAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA,GAAc,gCAAA;AAAA,EACd,YAAA,GAAe,mBAAA;AAAA,EACf,KAAA,GAAQ;AACV,CAAA,EAAwB;AACtB,EAAA,MAAM,MAAA,GAAe,cAAQ,MAAM;AACjC,IAAA,MAAM,GAAA,uBAAU,GAAA,EAAkC;AAClD,IAAA,KAAA,MAAW,OAAO,QAAA,EAAU;AAC1B,MAAA,MAAM,GAAA,GAAM,IAAI,KAAA,IAAS,SAAA;AACzB,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,GAAA,CAAI,GAAG,KAAK,EAAC;AAC9B,MAAA,IAAA,CAAK,KAAK,GAAG,CAAA;AACb,MAAA,GAAA,CAAI,GAAA,CAAI,KAAK,IAAI,CAAA;AAAA,IACnB;AACA,IAAA,OAAO,GAAA;AAAA,EACT,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,uBACE,IAAA,CAAC,aAAA,EAAA,EAAc,IAAA,EAAY,YAAA,EACzB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,YAAA,EAAA,EAAa,WAAA,EAA0B,YAAA,EAAY,KAAA,EAAO,CAAA;AAAA,yBAC1D,WAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,gBAAc,QAAA,EAAA,YAAA,EAAa,CAAA;AAAA,MAC3B,MAAM,IAAA,CAAK,MAAA,CAAO,SAAS,CAAA,CAAE,IAAI,CAAC,CAAC,OAAO,KAAK,CAAA,yBAC7C,YAAA,EAAA,EAAyB,OAAA,EAAS,OAChC,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,GAAA,qBACV,IAAA;AAAA,QAAC,WAAA;AAAA,QAAA;AAAA,UAEC,OAAO,CAAA,EAAG,GAAA,CAAI,EAAE,CAAA,CAAA,EAAI,IAAI,KAAK,CAAA,CAAA;AAAA,UAC7B,UAAU,MAAM;AACd,YAAA,YAAA,CAAa,KAAK,CAAA;AAClB,YAAA,GAAA,CAAI,QAAA,EAAS;AAAA,UACf,CAAA;AAAA,UAEC,QAAA,EAAA;AAAA,YAAA,GAAA,CAAI,KAAA;AAAA,YACJ,IAAI,QAAA,mBACH,GAAA,CAAC,eAAA,EAAA,EAAiB,QAAA,EAAA,GAAA,CAAI,UAAS,CAAA,GAC7B;AAAA;AAAA,SAAA;AAAA,QAVC,GAAA,CAAI;AAAA,OAYZ,CAAA,EAAA,EAfgB,KAgBnB,CACD;AAAA,KAAA,EACH;AAAA,GAAA,EACF,CAAA;AAEJ;AAMO,SAAS,uBAAA,CACd,UAAU,IAAA,EACgD;AAC1D,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,KAAK,CAAA;AAEtC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAqB;AACtC,MAAA,IAAI,CAAA,CAAE,GAAA,CAAI,WAAA,EAAY,KAAM,GAAA,EAAK;AACjC,MAAA,IAAI,EAAE,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,OAAA,CAAA,EAAU;AAC/B,MAAA,CAAA,CAAE,cAAA,EAAe;AACjB,MAAA,OAAA,CAAQ,CAAC,IAAA,KAAS,CAAC,IAAI,CAAA;AAAA,IACzB,CAAA;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC5C,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,SAAS,CAAA;AAAA,EAC9D,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,OAAO,CAAC,MAAM,OAAO,CAAA;AACvB","file":"chunk-CNTWQSUT.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { useEffect, useState } from \"react\";\nimport {\n CommandDialog,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandShortcut,\n} from \"./command\";\n\nexport interface CommandPaletteItem {\n id: string;\n label: string;\n shortcut?: string;\n group?: string;\n onSelect: () => void;\n}\n\nexport interface CommandPaletteProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n commands: CommandPaletteItem[];\n placeholder?: string;\n emptyMessage?: string;\n title?: string;\n}\n\n/**\n * Thin action registry over `CommandDialog` / cmdk.\n * Consumers register flat commands; optional `group` buckets them.\n */\nexport function CommandPalette({\n open,\n onOpenChange,\n commands,\n placeholder = \"Type a command or search…\",\n emptyMessage = \"No results found.\",\n title = \"Command palette\",\n}: CommandPaletteProps) {\n const groups = React.useMemo(() => {\n const map = new Map<string, CommandPaletteItem[]>();\n for (const cmd of commands) {\n const key = cmd.group ?? \"Actions\";\n const list = map.get(key) ?? [];\n list.push(cmd);\n map.set(key, list);\n }\n return map;\n }, [commands]);\n\n return (\n <CommandDialog open={open} onOpenChange={onOpenChange}>\n <CommandInput placeholder={placeholder} aria-label={title} />\n <CommandList>\n <CommandEmpty>{emptyMessage}</CommandEmpty>\n {Array.from(groups.entries()).map(([group, items]) => (\n <CommandGroup key={group} heading={group}>\n {items.map((cmd) => (\n <CommandItem\n key={cmd.id}\n value={`${cmd.id} ${cmd.label}`}\n onSelect={() => {\n onOpenChange(false);\n cmd.onSelect();\n }}\n >\n {cmd.label}\n {cmd.shortcut ? (\n <CommandShortcut>{cmd.shortcut}</CommandShortcut>\n ) : null}\n </CommandItem>\n ))}\n </CommandGroup>\n ))}\n </CommandList>\n </CommandDialog>\n );\n}\n\n/**\n * Toggle a command palette with Cmd/Ctrl+K.\n * Returns `[open, setOpen]` — pass into `<CommandPalette open onOpenChange />`.\n */\nexport function useCommandPaletteHotkey(\n enabled = true,\n): [boolean, React.Dispatch<React.SetStateAction<boolean>>] {\n const [open, setOpen] = useState(false);\n\n useEffect(() => {\n if (!enabled) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key.toLowerCase() !== \"k\") return;\n if (!(e.metaKey || e.ctrlKey)) return;\n e.preventDefault();\n setOpen((prev) => !prev);\n };\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, [enabled]);\n\n return [open, setOpen];\n}\n"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { GAP_CLASSES } from './chunk-AVFZ4P4B.js';
|
|
2
|
+
import { cn } from './chunk-NZ5WBA4R.js';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { cva } from 'class-variance-authority';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var splitVariants = cva(
|
|
8
|
+
// Below `at`, this is a plain vertical stack: master first, detail after,
|
|
9
|
+
// which is the correct reading order on a phone. At `at` and up it becomes
|
|
10
|
+
// a twelve-column grid. `flex-col` is simply inert once `display: grid`
|
|
11
|
+
// takes over, so the two never fight.
|
|
12
|
+
"flex flex-col",
|
|
13
|
+
{
|
|
14
|
+
variants: {
|
|
15
|
+
at: {
|
|
16
|
+
sm: "sm:grid sm:grid-cols-12",
|
|
17
|
+
md: "md:grid md:grid-cols-12",
|
|
18
|
+
lg: "lg:grid lg:grid-cols-12",
|
|
19
|
+
xl: "xl:grid xl:grid-cols-12"
|
|
20
|
+
},
|
|
21
|
+
gap: GAP_CLASSES
|
|
22
|
+
},
|
|
23
|
+
defaultVariants: {
|
|
24
|
+
at: "md",
|
|
25
|
+
gap: "md"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
var COL_SPAN = {
|
|
30
|
+
sm: { 4: "sm:col-span-4", 6: "sm:col-span-6", 8: "sm:col-span-8" },
|
|
31
|
+
md: { 4: "md:col-span-4", 6: "md:col-span-6", 8: "md:col-span-8" },
|
|
32
|
+
lg: { 4: "lg:col-span-4", 6: "lg:col-span-6", 8: "lg:col-span-8" },
|
|
33
|
+
xl: { 4: "xl:col-span-4", 6: "xl:col-span-6", 8: "xl:col-span-8" }
|
|
34
|
+
};
|
|
35
|
+
var START_SPAN = {
|
|
36
|
+
"1/3": 4,
|
|
37
|
+
"1/2": 6,
|
|
38
|
+
"2/3": 8
|
|
39
|
+
};
|
|
40
|
+
var END_SPAN = {
|
|
41
|
+
"1/3": 8,
|
|
42
|
+
"1/2": 6,
|
|
43
|
+
"2/3": 4
|
|
44
|
+
};
|
|
45
|
+
var Split = React.forwardRef(
|
|
46
|
+
({ className, start, end, ratio = "1/3", at = "md", gap, testID, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
47
|
+
"div",
|
|
48
|
+
{
|
|
49
|
+
ref,
|
|
50
|
+
"data-slot": "split",
|
|
51
|
+
"data-testid": testID,
|
|
52
|
+
className: cn(splitVariants({ at, gap }), className),
|
|
53
|
+
...props,
|
|
54
|
+
children: [
|
|
55
|
+
/* @__PURE__ */ jsx("div", { "data-slot": "split-start", className: cn("min-w-0", COL_SPAN[at][START_SPAN[ratio]]), children: start }),
|
|
56
|
+
/* @__PURE__ */ jsx("div", { "data-slot": "split-end", className: cn("min-w-0", COL_SPAN[at][END_SPAN[ratio]]), children: end })
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
);
|
|
61
|
+
Split.displayName = "Split";
|
|
62
|
+
|
|
63
|
+
export { Split, splitVariants };
|
|
64
|
+
//# sourceMappingURL=chunk-D2LIXA2Y.js.map
|
|
65
|
+
//# sourceMappingURL=chunk-D2LIXA2Y.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/layout/split.tsx"],"names":[],"mappings":";;;;;;AAeA,IAAM,aAAA,GAAgB,GAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKpB,eAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,EAAA,EAAI;AAAA,QACF,EAAA,EAAI,yBAAA;AAAA,QACJ,EAAA,EAAI,yBAAA;AAAA,QACJ,EAAA,EAAI,yBAAA;AAAA,QACJ,EAAA,EAAI;AAAA,OACN;AAAA,MACA,GAAA,EAAK;AAAA,KACP;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,EAAA,EAAI,IAAA;AAAA,MACJ,GAAA,EAAK;AAAA;AACP;AAEJ;AAWA,IAAM,QAAA,GAA+D;AAAA,EACnE,IAAI,EAAE,CAAA,EAAG,iBAAiB,CAAA,EAAG,eAAA,EAAiB,GAAG,eAAA,EAAgB;AAAA,EACjE,IAAI,EAAE,CAAA,EAAG,iBAAiB,CAAA,EAAG,eAAA,EAAiB,GAAG,eAAA,EAAgB;AAAA,EACjE,IAAI,EAAE,CAAA,EAAG,iBAAiB,CAAA,EAAG,eAAA,EAAiB,GAAG,eAAA,EAAgB;AAAA,EACjE,IAAI,EAAE,CAAA,EAAG,iBAAiB,CAAA,EAAG,eAAA,EAAiB,GAAG,eAAA;AACnD,CAAA;AAGA,IAAM,UAAA,GAA4C;AAAA,EAChD,KAAA,EAAO,CAAA;AAAA,EACP,KAAA,EAAO,CAAA;AAAA,EACP,KAAA,EAAO;AACT,CAAA;AAGA,IAAM,QAAA,GAA0C;AAAA,EAC9C,KAAA,EAAO,CAAA;AAAA,EACP,KAAA,EAAO,CAAA;AAAA,EACP,KAAA,EAAO;AACT,CAAA;AA2CO,IAAM,KAAA,GAAc,KAAA,CAAA,UAAA;AAAA,EACzB,CACE,EAAE,SAAA,EAAW,KAAA,EAAO,KAAK,KAAA,GAAQ,KAAA,EAAO,EAAA,GAAK,IAAA,EAAM,GAAA,EAAK,MAAA,EAAQ,GAAG,KAAA,IACnE,GAAA,qBAEA,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,WAAA,EAAU,OAAA;AAAA,MACV,aAAA,EAAa,MAAA;AAAA,MACb,SAAA,EAAW,GAAG,aAAA,CAAc,EAAE,IAAI,GAAA,EAAK,GAAG,SAAS,CAAA;AAAA,MAClD,GAAG,KAAA;AAAA,MAEJ,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAA,EAAU,aAAA,EAAc,SAAA,EAAW,GAAG,SAAA,EAAW,QAAA,CAAS,EAAE,CAAA,CAAE,UAAA,CAAW,KAAK,CAAC,CAAC,GAClF,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,wBACA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAA,EAAU,WAAA,EAAY,WAAW,EAAA,CAAG,SAAA,EAAW,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,KAAK,CAAC,CAAC,GAC9E,QAAA,EAAA,GAAA,EACH;AAAA;AAAA;AAAA;AAGN;AACA,KAAA,CAAM,WAAA,GAAc,OAAA","file":"chunk-D2LIXA2Y.js","sourcesContent":["import * as React from \"react\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport { cn } from \"../../utils\";\nimport { GAP_CLASSES } from \"./spacing\";\n\n/**\n * Breakpoint at which a `Split` stops stacking and becomes side-by-side.\n * These are Tailwind's own breakpoint names, so `at=\"lg\"` means exactly\n * what `lg:` means everywhere else in the app.\n */\nexport type SplitBreakpoint = \"sm\" | \"md\" | \"lg\" | \"xl\";\n\n/** How the horizontal space divides once the split is side-by-side. */\nexport type SplitRatio = \"1/3\" | \"1/2\" | \"2/3\";\n\nconst splitVariants = cva(\n // Below `at`, this is a plain vertical stack: master first, detail after,\n // which is the correct reading order on a phone. At `at` and up it becomes\n // a twelve-column grid. `flex-col` is simply inert once `display: grid`\n // takes over, so the two never fight.\n \"flex flex-col\",\n {\n variants: {\n at: {\n sm: \"sm:grid sm:grid-cols-12\",\n md: \"md:grid md:grid-cols-12\",\n lg: \"lg:grid lg:grid-cols-12\",\n xl: \"xl:grid xl:grid-cols-12\",\n },\n gap: GAP_CLASSES,\n },\n defaultVariants: {\n at: \"md\",\n gap: \"md\",\n },\n }\n);\n\n/**\n * Column spans, written out literally per breakpoint because Tailwind\n * scans source text — a class name assembled at runtime (`${at}:col-span-${n}`)\n * is a class name Tailwind never generates.\n *\n * Only 4 / 6 / 8 appear: the twelve-column track makes every ratio and its\n * complement land inside that set (12-4=8, 12-6=6, 12-8=4), so one table\n * serves both panes.\n */\nconst COL_SPAN: Record<SplitBreakpoint, Record<4 | 6 | 8, string>> = {\n sm: { 4: \"sm:col-span-4\", 6: \"sm:col-span-6\", 8: \"sm:col-span-8\" },\n md: { 4: \"md:col-span-4\", 6: \"md:col-span-6\", 8: \"md:col-span-8\" },\n lg: { 4: \"lg:col-span-4\", 6: \"lg:col-span-6\", 8: \"lg:col-span-8\" },\n xl: { 4: \"xl:col-span-4\", 6: \"xl:col-span-6\", 8: \"xl:col-span-8\" },\n};\n\n/** Track count the `start` pane occupies, out of twelve. */\nconst START_SPAN: Record<SplitRatio, 4 | 6 | 8> = {\n \"1/3\": 4,\n \"1/2\": 6,\n \"2/3\": 8,\n};\n\n/** The `end` pane always takes what `start` left behind. */\nconst END_SPAN: Record<SplitRatio, 4 | 6 | 8> = {\n \"1/3\": 8,\n \"1/2\": 6,\n \"2/3\": 4,\n};\n\nexport interface SplitProps\n extends React.HTMLAttributes<HTMLDivElement>,\n Omit<VariantProps<typeof splitVariants>, \"at\"> {\n /** Leading pane — the \"master\" half. Renders first when stacked. */\n start: React.ReactNode;\n /** Trailing pane — the \"detail\" half. Renders second when stacked. */\n end: React.ReactNode;\n /** Share of the width the `start` pane takes. Default `\"1/3\"`. */\n ratio?: SplitRatio;\n /** Breakpoint at and above which the panes sit side by side. Default `\"md\"`. */\n at?: SplitBreakpoint;\n /** Stable test/automation selector (emitted as `data-testid`). */\n testID?: string;\n}\n\n/**\n * Split — the master-detail layout: two panes side by side above a\n * breakpoint, stacked below it.\n *\n * ```tsx\n * <Split\n * ratio=\"1/3\"\n * at=\"lg\"\n * gap=\"lg\"\n * start={<ConversationList />}\n * end={<ConversationDetail />}\n * />\n * ```\n *\n * The stacking behaviour is the whole reason this is a component rather\n * than two divs: a hand-rolled split usually forgets the small screen, and\n * a hand-rolled split that remembers usually picks a different breakpoint\n * from the one next door.\n *\n * Two panes only, and both are required — a \"split\" with an optional half\n * is a `Stack`, and a three-pane shell (nav + list + detail) is an\n * application shell, not a layout primitive. Nest a `Split` inside a\n * `Split` if you genuinely need three.\n *\n * @stability Beta\n */\nexport const Split = React.forwardRef<HTMLDivElement, SplitProps>(\n (\n { className, start, end, ratio = \"1/3\", at = \"md\", gap, testID, ...props },\n ref\n ) => (\n <div\n ref={ref}\n data-slot=\"split\"\n data-testid={testID}\n className={cn(splitVariants({ at, gap }), className)}\n {...props}\n >\n <div data-slot=\"split-start\" className={cn(\"min-w-0\", COL_SPAN[at][START_SPAN[ratio]])}>\n {start}\n </div>\n <div data-slot=\"split-end\" className={cn(\"min-w-0\", COL_SPAN[at][END_SPAN[ratio]])}>\n {end}\n </div>\n </div>\n )\n);\nSplit.displayName = \"Split\";\n\nexport { splitVariants };\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useBrowserSearchParams } from './chunk-
|
|
2
|
+
import { useBrowserSearchParams } from './chunk-6NPEMLBA.js';
|
|
3
3
|
import { useRef, useCallback, useState, useEffect } from 'react';
|
|
4
4
|
import { useStorage } from '@marktiderman/genesis-core';
|
|
5
5
|
|
|
@@ -116,5 +116,5 @@ function useDataFilters(storageKey, defs, options) {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
export { useDataFilters };
|
|
119
|
-
//# sourceMappingURL=chunk-
|
|
120
|
-
//# sourceMappingURL=chunk-
|
|
119
|
+
//# sourceMappingURL=chunk-D4JTQYP5.js.map
|
|
120
|
+
//# sourceMappingURL=chunk-D4JTQYP5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/use-data-filters.ts"],"names":[],"mappings":"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","file":"chunk-FCGFG4RV.js","sourcesContent":["\"use client\";\n\nimport { useState, useCallback, useEffect, useRef } from \"react\";\nimport { useStorage } from \"@marktiderman/genesis-core\";\nimport {\n useBrowserSearchParams,\n type SearchParamsAdapter,\n} from \"../navigation\";\n\ntype FilterType = \"string\" | \"multi\";\n\nexport interface FilterDef {\n type: FilterType;\n default: string | string[];\n}\n\nexport type FilterDefs = Record<string, FilterDef>;\n\nexport type FilterValues<T extends FilterDefs> = {\n [K in keyof T]: T[K][\"type\"] extends \"multi\" ? string[] : string;\n};\n\nfunction parseArray(val: string | null): string[] {\n if (!val) return [];\n return val.split(\",\").filter(Boolean);\n}\n\n/**\n * @stability Beta\n */\nexport interface UseDataFiltersOptions {\n /**\n * Injectable URL search-params adapter. Defaults to a browser History-API\n * implementation (no router). Router consumers may pass their own — e.g.\n * React Router's `useSearchParams()` result — for full SPA integration.\n */\n searchParams?: SearchParamsAdapter;\n}\n\nexport function useDataFilters<T extends FilterDefs>(\n storageKey: string,\n defs: T,\n options?: UseDataFiltersOptions\n) {\n // Always call the default hook (rules-of-hooks); use the override if provided.\n const browserAdapter = useBrowserSearchParams();\n const { searchParams, setSearchParams } =\n options?.searchParams ?? browserAdapter;\n const storage = useStorage();\n const initialized = useRef(false);\n\n // Build initial state from URL -> storage -> defaults\n const getInitial = useCallback((): FilterValues<T> => {\n const result = {} as Record<string, unknown>;\n const localKey = `${storageKey}-filters`;\n let stored: Record<string, unknown> = {};\n\n try {\n const raw = storage.getItem(localKey);\n if (raw) stored = JSON.parse(raw);\n } catch {\n /* ignore */\n }\n\n // Check if URL has any of our params\n const hasUrlParams = Object.keys(defs).some((k) => searchParams.has(k));\n\n for (const [key, def] of Object.entries(defs)) {\n if (def.type === \"multi\") {\n const urlVal = hasUrlParams ? searchParams.get(key) : null;\n if (urlVal !== null) {\n result[key] = parseArray(urlVal);\n } else if (Array.isArray(stored[key])) {\n result[key] = stored[key];\n } else {\n result[key] = def.default;\n }\n } else {\n const urlVal = hasUrlParams ? searchParams.get(key) : null;\n if (urlVal !== null) {\n result[key] = urlVal;\n } else if (typeof stored[key] === \"string\") {\n result[key] = stored[key];\n } else {\n result[key] = def.default;\n }\n }\n }\n\n return result as FilterValues<T>;\n }, [defs, searchParams, storageKey, storage]);\n\n const [filters, setFilters] = useState<FilterValues<T>>(() => getInitial());\n\n // Mark as initialized after first render\n useEffect(() => {\n if (!initialized.current) {\n initialized.current = true;\n }\n }, []);\n\n // Persist to storage + URL whenever filters change\n useEffect(() => {\n if (!initialized.current) return;\n\n const localKey = `${storageKey}-filters`;\n storage.setItem(localKey, JSON.stringify(filters));\n\n // Update URL params. When using the DEFAULT browser adapter, seed from the\n // LIVE URL (not the adapter's possibly stale snapshot) so a second\n // useDataFilters instance on the same page can't merge against an old query\n // string and drop params another instance just wrote. When a caller\n // explicitly injects a SearchParamsAdapter (custom router / test double\n // whose URL state may not be synced to the DOM), trust ITS snapshot instead\n // of reading the real DOM location. Also falls back to the adapter snapshot\n // in non-browser envs.\n const newParams = new URLSearchParams(\n !options?.searchParams && typeof window !== \"undefined\"\n ? window.location.search\n : searchParams.toString(),\n );\n for (const [key, def] of Object.entries(defs)) {\n const val = (filters as Record<string, unknown>)[key];\n const isDefault =\n def.type === \"multi\"\n ? (val as string[]).length === 0\n : val === def.default;\n\n if (isDefault) {\n newParams.delete(key);\n } else if (def.type === \"multi\") {\n newParams.set(key, (val as string[]).join(\",\"));\n } else {\n newParams.set(key, val as string);\n }\n }\n setSearchParams(newParams, { replace: true });\n }, [filters, defs, storageKey, storage]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const setFilter = useCallback(\n <K extends keyof T>(\n key: K,\n value: T[K][\"type\"] extends \"multi\" ? string[] : string\n ) => {\n setFilters((prev) => ({ ...prev, [key]: value }));\n },\n []\n );\n\n const resetFilters = useCallback(() => {\n const result = {} as Record<string, unknown>;\n for (const [key, def] of Object.entries(defs)) {\n result[key] = def.default;\n }\n setFilters(result as FilterValues<T>);\n }, [defs]);\n\n const loadView = useCallback(\n (viewFilters: Record<string, unknown>) => {\n const result = {} as Record<string, unknown>;\n for (const [key, def] of Object.entries(defs)) {\n const v = viewFilters[key];\n if (def.type === \"multi\" && Array.isArray(v)) {\n result[key] = v;\n } else if (def.type === \"string\" && typeof v === \"string\") {\n result[key] = v;\n } else {\n result[key] = def.default;\n }\n }\n setFilters(result as FilterValues<T>);\n },\n [defs]\n );\n\n const hasActiveFilters = Object.entries(defs).some(([key, def]) => {\n const val = (filters as Record<string, unknown>)[key];\n if (def.type === \"multi\") return (val as string[]).length > 0;\n return val !== def.default;\n });\n\n return {\n filters,\n setFilter,\n resetFilters,\n loadView,\n hasActiveFilters,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/hooks/use-data-filters.ts"],"names":[],"mappings":"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","file":"chunk-D4JTQYP5.js","sourcesContent":["\"use client\";\n\nimport { useState, useCallback, useEffect, useRef } from \"react\";\nimport { useStorage } from \"@marktiderman/genesis-core\";\nimport {\n useBrowserSearchParams,\n type SearchParamsAdapter,\n} from \"../navigation\";\n\ntype FilterType = \"string\" | \"multi\";\n\nexport interface FilterDef {\n type: FilterType;\n default: string | string[];\n}\n\nexport type FilterDefs = Record<string, FilterDef>;\n\nexport type FilterValues<T extends FilterDefs> = {\n [K in keyof T]: T[K][\"type\"] extends \"multi\" ? string[] : string;\n};\n\nfunction parseArray(val: string | null): string[] {\n if (!val) return [];\n return val.split(\",\").filter(Boolean);\n}\n\n/**\n * @stability Beta\n */\nexport interface UseDataFiltersOptions {\n /**\n * Injectable URL search-params adapter. Defaults to a browser History-API\n * implementation (no router). Router consumers may pass their own — e.g.\n * React Router's `useSearchParams()` result — for full SPA integration.\n */\n searchParams?: SearchParamsAdapter;\n}\n\nexport function useDataFilters<T extends FilterDefs>(\n storageKey: string,\n defs: T,\n options?: UseDataFiltersOptions\n) {\n // Always call the default hook (rules-of-hooks); use the override if provided.\n const browserAdapter = useBrowserSearchParams();\n const { searchParams, setSearchParams } =\n options?.searchParams ?? browserAdapter;\n const storage = useStorage();\n const initialized = useRef(false);\n\n // Build initial state from URL -> storage -> defaults\n const getInitial = useCallback((): FilterValues<T> => {\n const result = {} as Record<string, unknown>;\n const localKey = `${storageKey}-filters`;\n let stored: Record<string, unknown> = {};\n\n try {\n const raw = storage.getItem(localKey);\n if (raw) stored = JSON.parse(raw);\n } catch {\n /* ignore */\n }\n\n // Check if URL has any of our params\n const hasUrlParams = Object.keys(defs).some((k) => searchParams.has(k));\n\n for (const [key, def] of Object.entries(defs)) {\n if (def.type === \"multi\") {\n const urlVal = hasUrlParams ? searchParams.get(key) : null;\n if (urlVal !== null) {\n result[key] = parseArray(urlVal);\n } else if (Array.isArray(stored[key])) {\n result[key] = stored[key];\n } else {\n result[key] = def.default;\n }\n } else {\n const urlVal = hasUrlParams ? searchParams.get(key) : null;\n if (urlVal !== null) {\n result[key] = urlVal;\n } else if (typeof stored[key] === \"string\") {\n result[key] = stored[key];\n } else {\n result[key] = def.default;\n }\n }\n }\n\n return result as FilterValues<T>;\n }, [defs, searchParams, storageKey, storage]);\n\n const [filters, setFilters] = useState<FilterValues<T>>(() => getInitial());\n\n // Mark as initialized after first render\n useEffect(() => {\n if (!initialized.current) {\n initialized.current = true;\n }\n }, []);\n\n // Persist to storage + URL whenever filters change\n useEffect(() => {\n if (!initialized.current) return;\n\n const localKey = `${storageKey}-filters`;\n storage.setItem(localKey, JSON.stringify(filters));\n\n // Update URL params. When using the DEFAULT browser adapter, seed from the\n // LIVE URL (not the adapter's possibly stale snapshot) so a second\n // useDataFilters instance on the same page can't merge against an old query\n // string and drop params another instance just wrote. When a caller\n // explicitly injects a SearchParamsAdapter (custom router / test double\n // whose URL state may not be synced to the DOM), trust ITS snapshot instead\n // of reading the real DOM location. Also falls back to the adapter snapshot\n // in non-browser envs.\n const newParams = new URLSearchParams(\n !options?.searchParams && typeof window !== \"undefined\"\n ? window.location.search\n : searchParams.toString(),\n );\n for (const [key, def] of Object.entries(defs)) {\n const val = (filters as Record<string, unknown>)[key];\n const isDefault =\n def.type === \"multi\"\n ? (val as string[]).length === 0\n : val === def.default;\n\n if (isDefault) {\n newParams.delete(key);\n } else if (def.type === \"multi\") {\n newParams.set(key, (val as string[]).join(\",\"));\n } else {\n newParams.set(key, val as string);\n }\n }\n setSearchParams(newParams, { replace: true });\n }, [filters, defs, storageKey, storage]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const setFilter = useCallback(\n <K extends keyof T>(\n key: K,\n value: T[K][\"type\"] extends \"multi\" ? string[] : string\n ) => {\n setFilters((prev) => ({ ...prev, [key]: value }));\n },\n []\n );\n\n const resetFilters = useCallback(() => {\n const result = {} as Record<string, unknown>;\n for (const [key, def] of Object.entries(defs)) {\n result[key] = def.default;\n }\n setFilters(result as FilterValues<T>);\n }, [defs]);\n\n const loadView = useCallback(\n (viewFilters: Record<string, unknown>) => {\n const result = {} as Record<string, unknown>;\n for (const [key, def] of Object.entries(defs)) {\n const v = viewFilters[key];\n if (def.type === \"multi\" && Array.isArray(v)) {\n result[key] = v;\n } else if (def.type === \"string\" && typeof v === \"string\") {\n result[key] = v;\n } else {\n result[key] = def.default;\n }\n }\n setFilters(result as FilterValues<T>);\n },\n [defs]\n );\n\n const hasActiveFilters = Object.entries(defs).some(([key, def]) => {\n const val = (filters as Record<string, unknown>)[key];\n if (def.type === \"multi\") return (val as string[]).length > 0;\n return val !== def.default;\n });\n\n return {\n filters,\n setFilter,\n resetFilters,\n loadView,\n hasActiveFilters,\n };\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from './chunk-NZ5WBA4R.js';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import
|
|
4
|
+
import { Label as Label$1 } from 'radix-ui';
|
|
5
5
|
import { cva } from 'class-variance-authority';
|
|
6
6
|
import { jsx } from 'react/jsx-runtime';
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ var labelVariants = cva(
|
|
|
9
9
|
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
10
10
|
);
|
|
11
11
|
var Label = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
12
|
-
|
|
12
|
+
Label$1.Root,
|
|
13
13
|
{
|
|
14
14
|
ref,
|
|
15
15
|
"data-slot": "label",
|
|
@@ -17,8 +17,8 @@ var Label = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ j
|
|
|
17
17
|
...props
|
|
18
18
|
}
|
|
19
19
|
));
|
|
20
|
-
Label.displayName =
|
|
20
|
+
Label.displayName = Label$1.Root.displayName;
|
|
21
21
|
|
|
22
22
|
export { Label };
|
|
23
|
-
//# sourceMappingURL=chunk-
|
|
24
|
-
//# sourceMappingURL=chunk-
|
|
23
|
+
//# sourceMappingURL=chunk-F47U5KNW.js.map
|
|
24
|
+
//# sourceMappingURL=chunk-F47U5KNW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/label.tsx"],"names":["LabelPrimitive"],"mappings":";;;;;;AAOA,IAAM,aAAA,GAAgB,GAAA;AAAA,EACpB;AACF,CAAA;AAEA,IAAM,KAAA,GAAc,iBAIlB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC1B,GAAA;AAAA,EAACA,OAAA,CAAe,IAAA;AAAA,EAAf;AAAA,IACC,GAAA;AAAA,IACA,WAAA,EAAU,OAAA;AAAA,IACV,SAAA,EAAW,EAAA,CAAG,aAAA,EAAc,EAAG,SAAS,CAAA;AAAA,IACvC,GAAG;AAAA;AACN,CACD;AACD,KAAA,CAAM,WAAA,GAAcA,QAAe,IAAA,CAAK,WAAA","file":"chunk-F47U5KNW.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Label as LabelPrimitive } from \"radix-ui\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport { cn } from \"../../utils\";\n\nconst labelVariants = cva(\n \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n);\n\nconst Label = React.forwardRef<\n React.ComponentRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n data-slot=\"label\"\n className={cn(labelVariants(), className)}\n {...props}\n />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n"]}
|