@multicomma/arkcn 0.1.2 → 0.1.3

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.
Files changed (148) hide show
  1. package/package.json +1 -1
  2. package/registry/index.json +1 -1
  3. package/registry/items/accordion.json +302 -0
  4. package/registry/items/activity-feed.json +408 -0
  5. package/registry/items/alert-dialog.json +676 -0
  6. package/registry/items/alert.json +113 -0
  7. package/registry/items/angle-slider.json +378 -0
  8. package/registry/items/app-shell.json +2654 -1
  9. package/registry/items/aspect-ratio.json +36 -0
  10. package/registry/items/attachment.json +299 -1
  11. package/registry/items/avatar.json +213 -0
  12. package/registry/items/badge.json +44 -0
  13. package/registry/items/breadcrumb.json +191 -0
  14. package/registry/items/bubble.json +146 -0
  15. package/registry/items/button-group.json +110 -0
  16. package/registry/items/button.json +52 -0
  17. package/registry/items/calendar.json +499 -1
  18. package/registry/items/canvas.json +446 -1
  19. package/registry/items/card.json +192 -0
  20. package/registry/items/carousel.json +208 -1
  21. package/registry/items/cascader.json +797 -1
  22. package/registry/items/chart.json +1764 -1
  23. package/registry/items/chat.json +993 -0
  24. package/registry/items/checkbox.json +503 -0
  25. package/registry/items/clipboard.json +308 -0
  26. package/registry/items/collapsible.json +226 -0
  27. package/registry/items/color-picker.json +1261 -0
  28. package/registry/items/combobox.json +1123 -1
  29. package/registry/items/command.json +837 -1
  30. package/registry/items/comment-thread.json +952 -1
  31. package/registry/items/context-menu.json +1344 -1
  32. package/registry/items/data-grid.json +449 -1
  33. package/registry/items/data-table.json +1310 -1
  34. package/registry/items/date-input.json +476 -0
  35. package/registry/items/dialog.json +592 -0
  36. package/registry/items/direction.json +29 -1
  37. package/registry/items/drawer.json +797 -0
  38. package/registry/items/dropdown-menu.json +1311 -1
  39. package/registry/items/editable.json +503 -0
  40. package/registry/items/empty.json +166 -0
  41. package/registry/items/field.json +286 -1
  42. package/registry/items/file-upload.json +638 -0
  43. package/registry/items/floating-panel.json +720 -0
  44. package/registry/items/floating-toolbar.json +43 -0
  45. package/registry/items/format.json +109 -0
  46. package/registry/items/gantt.json +773 -1
  47. package/registry/items/hooks/use-mobile.json +1 -0
  48. package/registry/items/hotkeys.json +99 -1
  49. package/registry/items/hover-card.json +357 -0
  50. package/registry/items/image-cropper.json +431 -0
  51. package/registry/items/input-group.json +189 -0
  52. package/registry/items/input-otp.json +181 -0
  53. package/registry/items/input.json +28 -0
  54. package/registry/items/item.json +308 -0
  55. package/registry/items/json-tree-view.json +336 -0
  56. package/registry/items/kanban.json +624 -1
  57. package/registry/items/kbd.json +54 -0
  58. package/registry/items/label.json +28 -0
  59. package/registry/items/lib/controllable.json +1 -0
  60. package/registry/items/lib/data-table-adapter.json +1 -0
  61. package/registry/items/lib/drag-preview.json +1 -0
  62. package/registry/items/lib/form.json +1 -0
  63. package/registry/items/lib/history.json +1 -0
  64. package/registry/items/lib/row-layout.json +1 -0
  65. package/registry/items/lib/table.json +1 -0
  66. package/registry/items/lib/time.json +1 -0
  67. package/registry/items/lib/utils.json +1 -0
  68. package/registry/items/live-region.json +43 -0
  69. package/registry/items/marker.json +96 -0
  70. package/registry/items/marquee.json +300 -0
  71. package/registry/items/menubar.json +1282 -1
  72. package/registry/items/message.json +166 -0
  73. package/registry/items/navigation-menu.json +561 -1
  74. package/registry/items/node-graph.json +1037 -1
  75. package/registry/items/number-input.json +519 -0
  76. package/registry/items/pagination.json +244 -1
  77. package/registry/items/password-input.json +311 -0
  78. package/registry/items/popconfirm.json +566 -0
  79. package/registry/items/popover.json +615 -0
  80. package/registry/items/progress.json +516 -0
  81. package/registry/items/qr-code.json +249 -0
  82. package/registry/items/query-builder.json +1368 -1
  83. package/registry/items/radio-group.json +362 -0
  84. package/registry/items/rating-group.json +304 -0
  85. package/registry/items/resizable.json +242 -1
  86. package/registry/items/rich-text-editor.json +934 -1
  87. package/registry/items/scheduler.json +1013 -1
  88. package/registry/items/scroll-area.json +227 -0
  89. package/registry/items/segment-group.json +363 -0
  90. package/registry/items/select.json +956 -0
  91. package/registry/items/separator.json +45 -1
  92. package/registry/items/sheet.json +592 -0
  93. package/registry/items/sidebar.json +785 -1
  94. package/registry/items/signature-pad.json +330 -0
  95. package/registry/items/skeleton.json +28 -0
  96. package/registry/items/slider.json +799 -0
  97. package/registry/items/sonner.json +135 -0
  98. package/registry/items/spinner.json +28 -0
  99. package/registry/items/steps.json +483 -0
  100. package/registry/items/swap.json +107 -0
  101. package/registry/items/switch.json +362 -0
  102. package/registry/items/table.json +210 -0
  103. package/registry/items/tabs.json +326 -0
  104. package/registry/items/tags-input.json +640 -0
  105. package/registry/items/textarea.json +28 -0
  106. package/registry/items/timer.json +289 -0
  107. package/registry/items/toc.json +372 -0
  108. package/registry/items/toggle-group.json +214 -1
  109. package/registry/items/toggle.json +124 -0
  110. package/registry/items/tooltip.json +417 -0
  111. package/registry/items/tour.json +498 -0
  112. package/registry/items/transfer-list.json +609 -1
  113. package/registry/items/tree-select.json +742 -1
  114. package/registry/items/tree-view.json +794 -0
  115. package/registry/items/virtual-list.json +214 -1
  116. package/src/components/ui/app-shell.tsx +11 -0
  117. package/src/components/ui/attachment.tsx +1 -0
  118. package/src/components/ui/calendar.tsx +1 -0
  119. package/src/components/ui/canvas.tsx +8 -0
  120. package/src/components/ui/carousel.tsx +3 -0
  121. package/src/components/ui/cascader.tsx +1 -0
  122. package/src/components/ui/chart.tsx +10 -0
  123. package/src/components/ui/combobox.tsx +3 -0
  124. package/src/components/ui/command.tsx +1 -0
  125. package/src/components/ui/comment-thread.tsx +11 -0
  126. package/src/components/ui/context-menu.tsx +6 -0
  127. package/src/components/ui/data-grid.tsx +8 -0
  128. package/src/components/ui/data-table.tsx +6 -0
  129. package/src/components/ui/direction.tsx +2 -0
  130. package/src/components/ui/dropdown-menu.tsx +6 -0
  131. package/src/components/ui/field.tsx +1 -0
  132. package/src/components/ui/gantt.tsx +15 -0
  133. package/src/components/ui/hotkeys.tsx +3 -0
  134. package/src/components/ui/kanban.tsx +3 -0
  135. package/src/components/ui/menubar.tsx +6 -0
  136. package/src/components/ui/navigation-menu.tsx +1 -0
  137. package/src/components/ui/node-graph.tsx +23 -0
  138. package/src/components/ui/pagination.tsx +1 -0
  139. package/src/components/ui/query-builder.tsx +7 -0
  140. package/src/components/ui/resizable.tsx +1 -0
  141. package/src/components/ui/rich-text-editor.tsx +54 -0
  142. package/src/components/ui/scheduler.tsx +26 -0
  143. package/src/components/ui/separator.tsx +1 -0
  144. package/src/components/ui/sidebar.tsx +5 -0
  145. package/src/components/ui/toggle-group.tsx +3 -0
  146. package/src/components/ui/transfer-list.tsx +11 -0
  147. package/src/components/ui/tree-select.tsx +5 -0
  148. package/src/components/ui/virtual-list.tsx +7 -0
@@ -5,6 +5,7 @@
5
5
  "exports": [
6
6
  "useIsMobile"
7
7
  ],
8
+ "parts": [],
8
9
  "dependencies": {},
9
10
  "registryDependencies": [],
10
11
  "files": [
@@ -12,6 +12,104 @@
12
12
  "useHotkeys",
13
13
  "useHotkeysDialog"
14
14
  ],
15
+ "parts": [
16
+ {
17
+ "name": "HotkeyKbd",
18
+ "props": [
19
+ {
20
+ "name": "hotkey",
21
+ "type": "string",
22
+ "required": true,
23
+ "description": "Key combination such as `mod+k`, or a sequence such as `g d`.",
24
+ "from": "arkcn"
25
+ },
26
+ {
27
+ "name": "children",
28
+ "type": "ReactNode",
29
+ "required": false,
30
+ "description": "Content rendered inside the part.",
31
+ "from": "@types/react"
32
+ },
33
+ {
34
+ "name": "className",
35
+ "type": "string",
36
+ "required": false,
37
+ "description": "Extra classes merged into the part's own classes with `cn`.",
38
+ "from": "@types/react"
39
+ },
40
+ {
41
+ "name": "style",
42
+ "type": "CSSProperties",
43
+ "required": false,
44
+ "description": "Inline styles applied to the rendered element.",
45
+ "from": "@types/react"
46
+ }
47
+ ]
48
+ },
49
+ {
50
+ "name": "HotkeysDialog",
51
+ "props": [
52
+ {
53
+ "name": "children",
54
+ "type": "ReactNode",
55
+ "required": false,
56
+ "description": "Content rendered inside the part.",
57
+ "from": "arkcn"
58
+ },
59
+ {
60
+ "name": "className",
61
+ "type": "string",
62
+ "required": false,
63
+ "description": "Extra classes merged into the part's own classes with `cn`.",
64
+ "from": "arkcn"
65
+ },
66
+ {
67
+ "name": "description",
68
+ "type": "ReactNode",
69
+ "required": false,
70
+ "default": "\"Shortcuts work anywhere on the page except while typing.\"",
71
+ "description": "Description text.",
72
+ "from": "arkcn"
73
+ },
74
+ {
75
+ "name": "title",
76
+ "type": "ReactNode",
77
+ "required": false,
78
+ "default": "\"Keyboard shortcuts\"",
79
+ "description": "Title text.",
80
+ "from": "arkcn"
81
+ }
82
+ ]
83
+ },
84
+ {
85
+ "name": "HotkeysProvider",
86
+ "props": [
87
+ {
88
+ "name": "children",
89
+ "type": "ReactNode",
90
+ "required": true,
91
+ "description": "Content rendered inside the part.",
92
+ "from": "arkcn"
93
+ },
94
+ {
95
+ "name": "dialogHotkey",
96
+ "type": "string | null",
97
+ "required": false,
98
+ "default": "\"?\"",
99
+ "description": "Opens the shortcuts dialog; `null` disables it.",
100
+ "from": "arkcn"
101
+ },
102
+ {
103
+ "name": "sequenceTimeout",
104
+ "type": "number",
105
+ "required": false,
106
+ "default": "1000",
107
+ "description": "Milliseconds allowed between keys of a sequence.",
108
+ "from": "arkcn"
109
+ }
110
+ ]
111
+ }
112
+ ],
15
113
  "dependencies": {},
16
114
  "registryDependencies": [
17
115
  "dialog",
@@ -21,7 +119,7 @@
21
119
  "files": [
22
120
  {
23
121
  "path": "components/ui/hotkeys.tsx",
24
- "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from \"@/components/ui/dialog\"\nimport { Kbd, KbdGroup } from \"@/components/ui/kbd\"\n\n/* -------------------------------- parsing -------------------------------- */\n\nconst isMac = () => typeof navigator !== \"undefined\" && /mac|iphone|ipad|ipod/i.test(navigator.platform)\n\ntype Chord = { key: string; mod: boolean; ctrl: boolean; meta: boolean; alt: boolean; shift: boolean }\n\nconst keyAliases: Record<string, string> = {\n esc: \"escape\",\n return: \"enter\",\n space: \" \",\n up: \"arrowup\",\n down: \"arrowdown\",\n left: \"arrowleft\",\n right: \"arrowright\",\n plus: \"+\",\n del: \"delete\",\n}\n\n/** \"mod+shift+k\" → chord; \"g d\" → sequence of chords. */\nfunction parseHotkey(hotkey: string): Chord[] {\n return hotkey\n .trim()\n .split(/\\s+/)\n .map((part) => {\n const tokens = part.split(\"+\").map((t) => t.toLowerCase())\n // \"+\" itself is written as \"plus\"\n const key = tokens.pop() ?? \"\"\n const chord: Chord = {\n key: keyAliases[key] ?? key,\n mod: false,\n ctrl: false,\n meta: false,\n alt: false,\n shift: false,\n }\n for (const t of tokens) {\n if (t === \"mod\" || t === \"cmd\" || t === \"command\") chord.mod = true\n else if (t === \"ctrl\" || t === \"control\") chord.ctrl = true\n else if (t === \"meta\" || t === \"win\" || t === \"super\") chord.meta = true\n else if (t === \"alt\" || t === \"option\") chord.alt = true\n else if (t === \"shift\") chord.shift = true\n }\n return chord\n })\n}\n\nfunction matchesChord(event: KeyboardEvent, chord: Chord, mac: boolean) {\n const key = event.key.length === 1 ? event.key.toLowerCase() : event.key.toLowerCase()\n if (key !== chord.key) return false\n const wantMeta = chord.meta || (chord.mod && mac)\n const wantCtrl = chord.ctrl || (chord.mod && !mac)\n if (event.metaKey !== wantMeta || event.ctrlKey !== wantCtrl || event.altKey !== chord.alt) return false\n // Punctuation like \"?\" already implies Shift on most layouts, so only enforce Shift for letters.\n const letter = /^[a-z0-9]$/.test(chord.key) || chord.key.length > 1\n if (letter && event.shiftKey !== chord.shift) return false\n return true\n}\n\nconst symbol: Record<string, string> = {\n mod: \"⌘\",\n meta: \"⌘\",\n ctrl: \"⌃\",\n alt: \"⌥\",\n shift: \"⇧\",\n enter: \"↵\",\n escape: \"Esc\",\n backspace: \"⌫\",\n delete: \"⌦\",\n arrowup: \"↑\",\n arrowdown: \"↓\",\n arrowleft: \"←\",\n arrowright: \"→\",\n \" \": \"Space\",\n tab: \"Tab\",\n}\nconst winSymbol: Record<string, string> = {\n ...symbol,\n mod: \"Ctrl\",\n meta: \"Win\",\n ctrl: \"Ctrl\",\n alt: \"Alt\",\n shift: \"Shift\",\n}\n\n/** Platform-aware key labels: \"mod+k\" → [\"⌘\", \"K\"] on Mac, [\"Ctrl\", \"K\"] elsewhere. Sequences give one array per chord. */\nfunction formatHotkey(hotkey: string, mac = isMac()): string[][] {\n const table = mac ? symbol : winSymbol\n return parseHotkey(hotkey).map((chord) => {\n const parts: string[] = []\n if (chord.ctrl) parts.push(table.ctrl)\n if (chord.alt) parts.push(table.alt)\n if (chord.shift) parts.push(table.shift)\n if (chord.mod) parts.push(table.mod)\n if (chord.meta && !chord.mod) parts.push(table.meta)\n parts.push(table[chord.key] ?? (chord.key.length === 1 ? chord.key.toUpperCase() : chord.key))\n return parts\n })\n}\n\n/* -------------------------------- registry ------------------------------- */\n\ntype HotkeyEntry = {\n id: string\n hotkey: string\n label: string\n group: string\n enabled: boolean\n /** Fire even while typing in an input, textarea, or contenteditable. */\n allowInInput: boolean\n handler: (event: KeyboardEvent) => void\n}\n\ntype HotkeysContextValue = {\n entries: HotkeyEntry[]\n register: (entry: HotkeyEntry) => () => void\n dialogOpen: boolean\n setDialogOpen: (open: boolean) => void\n}\n\nconst HotkeysContext = React.createContext<HotkeysContextValue | null>(null)\n\nfunction useHotkeysContext() {\n const ctx = React.useContext(HotkeysContext)\n if (!ctx) throw new Error(\"Hotkeys parts must be used inside <HotkeysProvider>\")\n return ctx\n}\n\nconst isEditable = (target: EventTarget | null) => {\n const el = target as HTMLElement | null\n if (!el || !(\"tagName\" in el)) return false\n const tag = el.tagName\n return tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\" || el.isContentEditable\n}\n\n/**\n * One document-level keydown listener for every registered hotkey. Supports chords\n * (\"mod+k\"), sequences (\"g d\", one second between keys), and a built-in \"?\" that opens\n * `HotkeysDialog` when one is rendered.\n */\nfunction HotkeysProvider({\n children,\n dialogHotkey = \"?\",\n sequenceTimeout = 1000,\n}: {\n children: React.ReactNode\n /** Opens the shortcuts dialog; `null` disables it. */\n dialogHotkey?: string | null\n sequenceTimeout?: number\n}) {\n const [entries, setEntries] = React.useState<HotkeyEntry[]>([])\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const entriesRef = React.useRef(entries)\n entriesRef.current = entries\n const buffer = React.useRef<{ keys: KeyboardEvent[]; at: number }>({ keys: [], at: 0 })\n\n const register = React.useCallback((entry: HotkeyEntry) => {\n setEntries((prev) => [...prev.filter((e) => e.id !== entry.id), entry])\n return () => setEntries((prev) => prev.filter((e) => e.id !== entry.id))\n }, [])\n\n const mac = React.useMemo(isMac, [])\n React.useEffect(() => {\n const down = (event: KeyboardEvent) => {\n if (event.defaultPrevented || event.isComposing) return\n if ([\"Shift\", \"Control\", \"Alt\", \"Meta\"].includes(event.key)) return\n const editing = isEditable(event.target)\n const now = Date.now()\n const buf = buffer.current\n if (now - buf.at > sequenceTimeout) buf.keys = []\n buf.keys.push(event)\n buf.at = now\n if (buf.keys.length > 4) buf.keys.shift()\n\n const candidates = [...entriesRef.current]\n if (dialogHotkey) {\n candidates.push({\n id: \"hotkeys:dialog\",\n hotkey: dialogHotkey,\n label: \"Keyboard shortcuts\",\n group: \"General\",\n enabled: true,\n allowInInput: false,\n handler: () => setDialogOpen((open) => !open),\n })\n }\n let partial = false\n for (const entry of candidates) {\n if (!entry.enabled || (editing && !entry.allowInInput)) continue\n const chords = parseHotkey(entry.hotkey)\n const tail = buf.keys.slice(-chords.length)\n if (tail.length === chords.length && chords.every((c, i) => matchesChord(tail[i], c, mac))) {\n event.preventDefault()\n buf.keys = []\n entry.handler(event)\n return\n }\n // Is the buffer a prefix of a longer sequence? Then keep it.\n if (chords.length > 1 && buf.keys.length < chords.length) {\n const head = chords.slice(0, buf.keys.length)\n if (head.every((c, i) => matchesChord(buf.keys[i], c, mac))) partial = true\n }\n }\n if (!partial) buf.keys = []\n }\n document.addEventListener(\"keydown\", down)\n return () => document.removeEventListener(\"keydown\", down)\n }, [dialogHotkey, sequenceTimeout, mac])\n\n const ctx = React.useMemo<HotkeysContextValue>(\n () => ({ entries, register, dialogOpen, setDialogOpen }),\n [entries, register, dialogOpen]\n )\n return <HotkeysContext.Provider value={ctx}>{children}</HotkeysContext.Provider>\n}\n\n/** Register a hotkey for the lifetime of the component. Listed in `HotkeysDialog` when it has a label. */\nfunction useHotkey(\n hotkey: string,\n handler: (event: KeyboardEvent) => void,\n options: { label?: string; group?: string; enabled?: boolean; allowInInput?: boolean } = {}\n) {\n const { register } = useHotkeysContext()\n const { label = \"\", group = \"General\", enabled = true, allowInInput = false } = options\n const id = React.useId()\n const handlerRef = React.useRef(handler)\n handlerRef.current = handler\n React.useEffect(\n () =>\n register({\n id,\n hotkey,\n label,\n group,\n enabled,\n allowInInput,\n handler: (event) => handlerRef.current(event),\n }),\n [register, id, hotkey, label, group, enabled, allowInInput]\n )\n}\n\n/** Every registered hotkey with a label, grouped, for rendering a cheat sheet. */\nfunction useHotkeys() {\n const { entries } = useHotkeysContext()\n return React.useMemo(() => {\n const groups = new Map<string, HotkeyEntry[]>()\n for (const e of entries) {\n if (!e.label) continue\n const list = groups.get(e.group) ?? []\n list.push(e)\n groups.set(e.group, list)\n }\n return Array.from(groups, ([group, hotkeys]) => ({ group, hotkeys }))\n }, [entries])\n}\n\n/* ---------------------------------- parts -------------------------------- */\n\n/** Renders a hotkey as Kbd caps (\"mod+k\" → ⌘ K; \"g d\" → G then D). */\nfunction HotkeyKbd({ hotkey, className, ...props }: React.ComponentProps<\"span\"> & { hotkey: string }) {\n const chords = formatHotkey(hotkey)\n return (\n <span data-slot=\"hotkey-kbd\" className={cn(\"inline-flex items-center gap-1\", className)} {...props}>\n {chords.map((keys, i) => (\n <React.Fragment key={i}>\n {i > 0 && <span className=\"text-xs text-muted-foreground\">then</span>}\n <KbdGroup>\n {keys.map((k, j) => (\n <Kbd key={j}>{k}</Kbd>\n ))}\n </KbdGroup>\n </React.Fragment>\n ))}\n </span>\n )\n}\n\n/** The shortcuts cheat sheet. Opens from the provider's `dialogHotkey` (\"?\" by default) or `useHotkeysDialog()`. */\nfunction HotkeysDialog({\n title = \"Keyboard shortcuts\",\n description = \"Shortcuts work anywhere on the page except while typing.\",\n children,\n className,\n}: {\n title?: React.ReactNode\n description?: React.ReactNode\n children?: React.ReactNode\n className?: string\n}) {\n const { dialogOpen, setDialogOpen } = useHotkeysContext()\n const registered = useHotkeys()\n const groups = React.useMemo(() => {\n const self = { id: \"hotkeys:dialog\", hotkey: \"?\", label: \"Show this dialog\" }\n const general = registered.find((g) => g.group === \"General\")\n if (general) return registered.map((g) => (g === general ? { ...g, hotkeys: [...g.hotkeys, self] } : g))\n return [...registered, { group: \"General\", hotkeys: [self] }]\n }, [registered])\n return (\n <Dialog open={dialogOpen} onOpenChange={({ open }) => setDialogOpen(open)}>\n <DialogContent data-slot=\"hotkeys-dialog\" className={cn(\"sm:max-w-lg\", className)}>\n <DialogHeader>\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n <div className=\"grid gap-5 sm:grid-cols-2\">\n {groups.map(({ group, hotkeys }) => (\n <div key={group} data-slot=\"hotkeys-dialog-group\" className=\"flex flex-col gap-1.5\">\n <h4 className=\"text-xs font-medium text-muted-foreground uppercase\">{group}</h4>\n {hotkeys.map((h) => (\n <div\n key={h.id}\n data-slot=\"hotkeys-dialog-item\"\n className=\"flex items-center justify-between gap-3 text-sm\"\n >\n <span className=\"truncate\">{h.label}</span>\n <HotkeyKbd hotkey={h.hotkey} />\n </div>\n ))}\n </div>\n ))}\n </div>\n {children}\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction useHotkeysDialog() {\n const { dialogOpen, setDialogOpen } = useHotkeysContext()\n return { open: dialogOpen, setOpen: setDialogOpen }\n}\n\nexport { HotkeyKbd, HotkeysDialog, HotkeysProvider, formatHotkey, parseHotkey, useHotkey, useHotkeys, useHotkeysDialog }\n"
122
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from \"@/components/ui/dialog\"\nimport { Kbd, KbdGroup } from \"@/components/ui/kbd\"\n\n/* -------------------------------- parsing -------------------------------- */\n\nconst isMac = () => typeof navigator !== \"undefined\" && /mac|iphone|ipad|ipod/i.test(navigator.platform)\n\ntype Chord = { key: string; mod: boolean; ctrl: boolean; meta: boolean; alt: boolean; shift: boolean }\n\nconst keyAliases: Record<string, string> = {\n esc: \"escape\",\n return: \"enter\",\n space: \" \",\n up: \"arrowup\",\n down: \"arrowdown\",\n left: \"arrowleft\",\n right: \"arrowright\",\n plus: \"+\",\n del: \"delete\",\n}\n\n/** \"mod+shift+k\" → chord; \"g d\" → sequence of chords. */\nfunction parseHotkey(hotkey: string): Chord[] {\n return hotkey\n .trim()\n .split(/\\s+/)\n .map((part) => {\n const tokens = part.split(\"+\").map((t) => t.toLowerCase())\n // \"+\" itself is written as \"plus\"\n const key = tokens.pop() ?? \"\"\n const chord: Chord = {\n key: keyAliases[key] ?? key,\n mod: false,\n ctrl: false,\n meta: false,\n alt: false,\n shift: false,\n }\n for (const t of tokens) {\n if (t === \"mod\" || t === \"cmd\" || t === \"command\") chord.mod = true\n else if (t === \"ctrl\" || t === \"control\") chord.ctrl = true\n else if (t === \"meta\" || t === \"win\" || t === \"super\") chord.meta = true\n else if (t === \"alt\" || t === \"option\") chord.alt = true\n else if (t === \"shift\") chord.shift = true\n }\n return chord\n })\n}\n\nfunction matchesChord(event: KeyboardEvent, chord: Chord, mac: boolean) {\n const key = event.key.length === 1 ? event.key.toLowerCase() : event.key.toLowerCase()\n if (key !== chord.key) return false\n const wantMeta = chord.meta || (chord.mod && mac)\n const wantCtrl = chord.ctrl || (chord.mod && !mac)\n if (event.metaKey !== wantMeta || event.ctrlKey !== wantCtrl || event.altKey !== chord.alt) return false\n // Punctuation like \"?\" already implies Shift on most layouts, so only enforce Shift for letters.\n const letter = /^[a-z0-9]$/.test(chord.key) || chord.key.length > 1\n if (letter && event.shiftKey !== chord.shift) return false\n return true\n}\n\nconst symbol: Record<string, string> = {\n mod: \"⌘\",\n meta: \"⌘\",\n ctrl: \"⌃\",\n alt: \"⌥\",\n shift: \"⇧\",\n enter: \"↵\",\n escape: \"Esc\",\n backspace: \"⌫\",\n delete: \"⌦\",\n arrowup: \"↑\",\n arrowdown: \"↓\",\n arrowleft: \"←\",\n arrowright: \"→\",\n \" \": \"Space\",\n tab: \"Tab\",\n}\nconst winSymbol: Record<string, string> = {\n ...symbol,\n mod: \"Ctrl\",\n meta: \"Win\",\n ctrl: \"Ctrl\",\n alt: \"Alt\",\n shift: \"Shift\",\n}\n\n/** Platform-aware key labels: \"mod+k\" → [\"⌘\", \"K\"] on Mac, [\"Ctrl\", \"K\"] elsewhere. Sequences give one array per chord. */\nfunction formatHotkey(hotkey: string, mac = isMac()): string[][] {\n const table = mac ? symbol : winSymbol\n return parseHotkey(hotkey).map((chord) => {\n const parts: string[] = []\n if (chord.ctrl) parts.push(table.ctrl)\n if (chord.alt) parts.push(table.alt)\n if (chord.shift) parts.push(table.shift)\n if (chord.mod) parts.push(table.mod)\n if (chord.meta && !chord.mod) parts.push(table.meta)\n parts.push(table[chord.key] ?? (chord.key.length === 1 ? chord.key.toUpperCase() : chord.key))\n return parts\n })\n}\n\n/* -------------------------------- registry ------------------------------- */\n\ntype HotkeyEntry = {\n id: string\n /** Key combination such as `mod+k`, or a sequence such as `g d`. */\n hotkey: string\n label: string\n group: string\n enabled: boolean\n /** Fire even while typing in an input, textarea, or contenteditable. */\n allowInInput: boolean\n handler: (event: KeyboardEvent) => void\n}\n\ntype HotkeysContextValue = {\n entries: HotkeyEntry[]\n register: (entry: HotkeyEntry) => () => void\n dialogOpen: boolean\n setDialogOpen: (open: boolean) => void\n}\n\nconst HotkeysContext = React.createContext<HotkeysContextValue | null>(null)\n\nfunction useHotkeysContext() {\n const ctx = React.useContext(HotkeysContext)\n if (!ctx) throw new Error(\"Hotkeys parts must be used inside <HotkeysProvider>\")\n return ctx\n}\n\nconst isEditable = (target: EventTarget | null) => {\n const el = target as HTMLElement | null\n if (!el || !(\"tagName\" in el)) return false\n const tag = el.tagName\n return tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\" || el.isContentEditable\n}\n\n/**\n * One document-level keydown listener for every registered hotkey. Supports chords\n * (\"mod+k\"), sequences (\"g d\", one second between keys), and a built-in \"?\" that opens\n * `HotkeysDialog` when one is rendered.\n */\nfunction HotkeysProvider({\n children,\n dialogHotkey = \"?\",\n sequenceTimeout = 1000,\n}: {\n children: React.ReactNode\n /** Opens the shortcuts dialog; `null` disables it. */\n dialogHotkey?: string | null\n /** Milliseconds allowed between keys of a sequence. */\n sequenceTimeout?: number\n}) {\n const [entries, setEntries] = React.useState<HotkeyEntry[]>([])\n const [dialogOpen, setDialogOpen] = React.useState(false)\n const entriesRef = React.useRef(entries)\n entriesRef.current = entries\n const buffer = React.useRef<{ keys: KeyboardEvent[]; at: number }>({ keys: [], at: 0 })\n\n const register = React.useCallback((entry: HotkeyEntry) => {\n setEntries((prev) => [...prev.filter((e) => e.id !== entry.id), entry])\n return () => setEntries((prev) => prev.filter((e) => e.id !== entry.id))\n }, [])\n\n const mac = React.useMemo(isMac, [])\n React.useEffect(() => {\n const down = (event: KeyboardEvent) => {\n if (event.defaultPrevented || event.isComposing) return\n if ([\"Shift\", \"Control\", \"Alt\", \"Meta\"].includes(event.key)) return\n const editing = isEditable(event.target)\n const now = Date.now()\n const buf = buffer.current\n if (now - buf.at > sequenceTimeout) buf.keys = []\n buf.keys.push(event)\n buf.at = now\n if (buf.keys.length > 4) buf.keys.shift()\n\n const candidates = [...entriesRef.current]\n if (dialogHotkey) {\n candidates.push({\n id: \"hotkeys:dialog\",\n hotkey: dialogHotkey,\n label: \"Keyboard shortcuts\",\n group: \"General\",\n enabled: true,\n allowInInput: false,\n handler: () => setDialogOpen((open) => !open),\n })\n }\n let partial = false\n for (const entry of candidates) {\n if (!entry.enabled || (editing && !entry.allowInInput)) continue\n const chords = parseHotkey(entry.hotkey)\n const tail = buf.keys.slice(-chords.length)\n if (tail.length === chords.length && chords.every((c, i) => matchesChord(tail[i], c, mac))) {\n event.preventDefault()\n buf.keys = []\n entry.handler(event)\n return\n }\n // Is the buffer a prefix of a longer sequence? Then keep it.\n if (chords.length > 1 && buf.keys.length < chords.length) {\n const head = chords.slice(0, buf.keys.length)\n if (head.every((c, i) => matchesChord(buf.keys[i], c, mac))) partial = true\n }\n }\n if (!partial) buf.keys = []\n }\n document.addEventListener(\"keydown\", down)\n return () => document.removeEventListener(\"keydown\", down)\n }, [dialogHotkey, sequenceTimeout, mac])\n\n const ctx = React.useMemo<HotkeysContextValue>(\n () => ({ entries, register, dialogOpen, setDialogOpen }),\n [entries, register, dialogOpen]\n )\n return <HotkeysContext.Provider value={ctx}>{children}</HotkeysContext.Provider>\n}\n\n/** Register a hotkey for the lifetime of the component. Listed in `HotkeysDialog` when it has a label. */\nfunction useHotkey(\n /** Key combination such as `mod+k`, or a sequence such as `g d`. */\n hotkey: string,\n handler: (event: KeyboardEvent) => void,\n options: { label?: string; group?: string; enabled?: boolean; allowInInput?: boolean } = {}\n) {\n const { register } = useHotkeysContext()\n const { label = \"\", group = \"General\", enabled = true, allowInInput = false } = options\n const id = React.useId()\n const handlerRef = React.useRef(handler)\n handlerRef.current = handler\n React.useEffect(\n () =>\n register({\n id,\n hotkey,\n label,\n group,\n enabled,\n allowInInput,\n handler: (event) => handlerRef.current(event),\n }),\n [register, id, hotkey, label, group, enabled, allowInInput]\n )\n}\n\n/** Every registered hotkey with a label, grouped, for rendering a cheat sheet. */\nfunction useHotkeys() {\n const { entries } = useHotkeysContext()\n return React.useMemo(() => {\n const groups = new Map<string, HotkeyEntry[]>()\n for (const e of entries) {\n if (!e.label) continue\n const list = groups.get(e.group) ?? []\n list.push(e)\n groups.set(e.group, list)\n }\n return Array.from(groups, ([group, hotkeys]) => ({ group, hotkeys }))\n }, [entries])\n}\n\n/* ---------------------------------- parts -------------------------------- */\n\n/** Renders a hotkey as Kbd caps (\"mod+k\" → ⌘ K; \"g d\" → G then D). */\nfunction HotkeyKbd({ hotkey, className, ...props }: React.ComponentProps<\"span\"> & { hotkey: string }) {\n const chords = formatHotkey(hotkey)\n return (\n <span data-slot=\"hotkey-kbd\" className={cn(\"inline-flex items-center gap-1\", className)} {...props}>\n {chords.map((keys, i) => (\n <React.Fragment key={i}>\n {i > 0 && <span className=\"text-xs text-muted-foreground\">then</span>}\n <KbdGroup>\n {keys.map((k, j) => (\n <Kbd key={j}>{k}</Kbd>\n ))}\n </KbdGroup>\n </React.Fragment>\n ))}\n </span>\n )\n}\n\n/** The shortcuts cheat sheet. Opens from the provider's `dialogHotkey` (\"?\" by default) or `useHotkeysDialog()`. */\nfunction HotkeysDialog({\n title = \"Keyboard shortcuts\",\n description = \"Shortcuts work anywhere on the page except while typing.\",\n children,\n className,\n}: {\n title?: React.ReactNode\n description?: React.ReactNode\n children?: React.ReactNode\n className?: string\n}) {\n const { dialogOpen, setDialogOpen } = useHotkeysContext()\n const registered = useHotkeys()\n const groups = React.useMemo(() => {\n const self = { id: \"hotkeys:dialog\", hotkey: \"?\", label: \"Show this dialog\" }\n const general = registered.find((g) => g.group === \"General\")\n if (general) return registered.map((g) => (g === general ? { ...g, hotkeys: [...g.hotkeys, self] } : g))\n return [...registered, { group: \"General\", hotkeys: [self] }]\n }, [registered])\n return (\n <Dialog open={dialogOpen} onOpenChange={({ open }) => setDialogOpen(open)}>\n <DialogContent data-slot=\"hotkeys-dialog\" className={cn(\"sm:max-w-lg\", className)}>\n <DialogHeader>\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n <div className=\"grid gap-5 sm:grid-cols-2\">\n {groups.map(({ group, hotkeys }) => (\n <div key={group} data-slot=\"hotkeys-dialog-group\" className=\"flex flex-col gap-1.5\">\n <h4 className=\"text-xs font-medium text-muted-foreground uppercase\">{group}</h4>\n {hotkeys.map((h) => (\n <div\n key={h.id}\n data-slot=\"hotkeys-dialog-item\"\n className=\"flex items-center justify-between gap-3 text-sm\"\n >\n <span className=\"truncate\">{h.label}</span>\n <HotkeyKbd hotkey={h.hotkey} />\n </div>\n ))}\n </div>\n ))}\n </div>\n {children}\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction useHotkeysDialog() {\n const { dialogOpen, setDialogOpen } = useHotkeysContext()\n return { open: dialogOpen, setOpen: setDialogOpen }\n}\n\nexport { HotkeyKbd, HotkeysDialog, HotkeysProvider, formatHotkey, parseHotkey, useHotkey, useHotkeys, useHotkeysDialog }\n"
25
123
  }
26
124
  ],
27
125
  "docs": "## Shared infrastructure\n- `src/lib/controllable.ts` `useControllable(controlled, default, onChange)` is the one\n controllable-state hook (updater functions accepted; `onChange` fires in both modes, not on\n no-op sets). Every primitive and demo composition uses it (chat, menubar, comment thread, gantt,\n scheduler, data grid, query builder, tree select, cascader, transfer list, the table engine,\n apps view, settings layout). Never hand-roll `valueProp ?? internal` again.\n- `src/components/ui/live-region.tsx`: `useLiveRegion({ clearAfter })` → `{ message, announce }`\n (re-fires identical text) and `<LiveRegion message= assertive? />` (sr-only `role=\"status\"`).\n Kanban, canvas, gantt, scheduler, node graph, data grid, data table bulk actions, and transfer\n list all announce through it; a primitive renders its own `LiveRegion` (with its `data-slot`)\n so it works without any provider.\n- `src/components/ui/hotkeys.tsx`: `HotkeysProvider` (one document keydown listener; chords like\n `mod+k` where `mod` is ⌘ on Mac and Ctrl elsewhere, sequences like `g d` with a 1s window,\n ignores typing in inputs unless `allowInInput`, built-in `?` toggles the dialog;\n `dialogHotkey={null}` disables), `useHotkey(hotkey, handler, { label, group, enabled,\n allowInInput })` registers for the component's lifetime (labelled ones appear in the dialog),\n `useHotkeys()` (grouped list), `HotkeysDialog` (the cheat sheet on `Dialog`; `useHotkeysDialog()`\n opens it), `HotkeyKbd hotkey=` (platform-aware `Kbd` caps, \"then\" between sequence steps),\n `formatHotkey`/`parseHotkey`. The shell demo wraps everything in the provider with\n `AppShell searchShortcut={false}` and registers ⌘K, ⌘J (theme), and `g` + letter navigation in\n `ShellHotkeys`; the user menu has a \"Keyboard shortcuts\" item. Pages register their own with\n `useHotkey` and a `group`."
@@ -12,6 +12,363 @@
12
12
  "HoverCardPositioner",
13
13
  "HoverCardTrigger"
14
14
  ],
15
+ "parts": [
16
+ {
17
+ "name": "HoverCard",
18
+ "props": [
19
+ {
20
+ "name": "children",
21
+ "type": "ReactNode",
22
+ "required": false,
23
+ "description": "Content rendered inside the part.",
24
+ "from": "@ark-ui/react"
25
+ },
26
+ {
27
+ "name": "closeDelay",
28
+ "type": "number",
29
+ "required": false,
30
+ "default": "300",
31
+ "description": "The duration from when the mouse leaves the trigger or content until the hover card closes.",
32
+ "from": "@zag-js/hover-card"
33
+ },
34
+ {
35
+ "name": "defaultOpen",
36
+ "type": "boolean",
37
+ "required": false,
38
+ "description": "The initial open state of the hover card when rendered.\nUse when you don't need to control the open state of the hover card.",
39
+ "from": "@zag-js/hover-card"
40
+ },
41
+ {
42
+ "name": "defaultTriggerValue",
43
+ "type": "string | null",
44
+ "required": false,
45
+ "description": "The initial trigger value when rendered.\nUse when you don't need to control the trigger value.",
46
+ "from": "@zag-js/hover-card"
47
+ },
48
+ {
49
+ "name": "disabled",
50
+ "type": "boolean",
51
+ "required": false,
52
+ "description": "Whether the hover card is disabled",
53
+ "from": "@zag-js/hover-card"
54
+ },
55
+ {
56
+ "name": "hideMode",
57
+ "type": "HideMode",
58
+ "required": false,
59
+ "default": "'display-none'",
60
+ "description": "How to hide content when mounted but not present.\n- `'display-none'`: HTML `hidden` attribute. Effects stay alive.\n- `'activity'`: React 19 `<Activity mode=\"hidden\">`. Effects pause. Requires React 19+.",
61
+ "from": "@ark-ui/react"
62
+ },
63
+ {
64
+ "name": "id",
65
+ "type": "string",
66
+ "required": false,
67
+ "description": "The unique identifier of the machine.",
68
+ "from": "@zag-js/types"
69
+ },
70
+ {
71
+ "name": "ids",
72
+ "type": "ElementIds",
73
+ "required": false,
74
+ "description": "The ids of the elements in the popover. Useful for composition.",
75
+ "from": "@zag-js/hover-card"
76
+ },
77
+ {
78
+ "name": "immediate",
79
+ "type": "boolean",
80
+ "required": false,
81
+ "description": "Whether to synchronize the present change immediately or defer it to the next frame",
82
+ "from": "@zag-js/presence"
83
+ },
84
+ {
85
+ "name": "lazyMount",
86
+ "type": "boolean",
87
+ "required": false,
88
+ "default": "true",
89
+ "description": "Whether to enable lazy mounting",
90
+ "from": "@ark-ui/react"
91
+ },
92
+ {
93
+ "name": "onEnterComplete",
94
+ "type": "VoidFunction",
95
+ "required": false,
96
+ "description": "Function called when the animation ends in the open state",
97
+ "from": "@zag-js/presence"
98
+ },
99
+ {
100
+ "name": "onExitComplete",
101
+ "type": "VoidFunction",
102
+ "required": false,
103
+ "description": "Function called when the animation ends in the closed state",
104
+ "from": "@zag-js/presence"
105
+ },
106
+ {
107
+ "name": "onFocusOutside",
108
+ "type": "((event: FocusOutsideEvent) => void)",
109
+ "required": false,
110
+ "description": "Function called when the focus is moved outside the component",
111
+ "from": "@zag-js/interact-outside"
112
+ },
113
+ {
114
+ "name": "onInteractOutside",
115
+ "type": "((event: InteractOutsideEvent) => void)",
116
+ "required": false,
117
+ "description": "Function called when an interaction happens outside the component",
118
+ "from": "@zag-js/interact-outside"
119
+ },
120
+ {
121
+ "name": "onOpenChange",
122
+ "type": "((details: OpenChangeDetails) => void)",
123
+ "required": false,
124
+ "description": "Function called when the hover card opens or closes.",
125
+ "from": "@zag-js/hover-card"
126
+ },
127
+ {
128
+ "name": "onPointerDownOutside",
129
+ "type": "((event: PointerDownOutsideEvent) => void)",
130
+ "required": false,
131
+ "description": "Function called when the pointer is pressed down outside the component",
132
+ "from": "@zag-js/interact-outside"
133
+ },
134
+ {
135
+ "name": "onTriggerValueChange",
136
+ "type": "((details: TriggerValueChangeDetails) => void)",
137
+ "required": false,
138
+ "description": "Function called when the trigger value changes.",
139
+ "from": "@zag-js/hover-card"
140
+ },
141
+ {
142
+ "name": "open",
143
+ "type": "boolean",
144
+ "required": false,
145
+ "description": "The controlled open state of the hover card",
146
+ "from": "@zag-js/hover-card"
147
+ },
148
+ {
149
+ "name": "openDelay",
150
+ "type": "number",
151
+ "required": false,
152
+ "default": "600",
153
+ "description": "The duration from when the mouse enters the trigger until the hover card opens.",
154
+ "from": "@zag-js/hover-card"
155
+ },
156
+ {
157
+ "name": "positioning",
158
+ "type": "PositioningOptions",
159
+ "required": false,
160
+ "description": "The user provided options used to position the popover content",
161
+ "from": "@zag-js/hover-card"
162
+ },
163
+ {
164
+ "name": "present",
165
+ "type": "boolean",
166
+ "required": false,
167
+ "description": "Whether the node is present (controlled by the user)",
168
+ "from": "@zag-js/presence"
169
+ },
170
+ {
171
+ "name": "skipAnimationOnMount",
172
+ "type": "boolean",
173
+ "required": false,
174
+ "default": "false",
175
+ "description": "Whether to allow the initial presence animation.",
176
+ "from": "@ark-ui/react"
177
+ },
178
+ {
179
+ "name": "triggerValue",
180
+ "type": "string | null",
181
+ "required": false,
182
+ "description": "The controlled trigger value",
183
+ "from": "@zag-js/hover-card"
184
+ },
185
+ {
186
+ "name": "unmountOnExit",
187
+ "type": "boolean",
188
+ "required": false,
189
+ "default": "true",
190
+ "description": "Whether to unmount on exit.",
191
+ "from": "@ark-ui/react"
192
+ }
193
+ ]
194
+ },
195
+ {
196
+ "name": "HoverCardArrow",
197
+ "props": [
198
+ {
199
+ "name": "asChild",
200
+ "type": "boolean",
201
+ "required": false,
202
+ "description": "Use the provided child element as the default rendered element, combining their props and behavior.",
203
+ "from": "@ark-ui/react"
204
+ },
205
+ {
206
+ "name": "children",
207
+ "type": "ReactNode",
208
+ "required": false,
209
+ "description": "Content rendered inside the part.",
210
+ "from": "@types/react"
211
+ },
212
+ {
213
+ "name": "className",
214
+ "type": "string",
215
+ "required": false,
216
+ "description": "Extra classes merged into the part's own classes with `cn`.",
217
+ "from": "@types/react"
218
+ },
219
+ {
220
+ "name": "style",
221
+ "type": "CSSProperties",
222
+ "required": false,
223
+ "description": "Inline styles applied to the rendered element.",
224
+ "from": "@types/react"
225
+ }
226
+ ]
227
+ },
228
+ {
229
+ "name": "HoverCardContent",
230
+ "props": [
231
+ {
232
+ "name": "asChild",
233
+ "type": "boolean",
234
+ "required": false,
235
+ "description": "Use the provided child element as the default rendered element, combining their props and behavior.",
236
+ "from": "@ark-ui/react"
237
+ },
238
+ {
239
+ "name": "children",
240
+ "type": "ReactNode",
241
+ "required": false,
242
+ "description": "Content rendered inside the part.",
243
+ "from": "@types/react"
244
+ },
245
+ {
246
+ "name": "className",
247
+ "type": "string",
248
+ "required": false,
249
+ "description": "Extra classes merged into the part's own classes with `cn`.",
250
+ "from": "@types/react"
251
+ },
252
+ {
253
+ "name": "style",
254
+ "type": "CSSProperties",
255
+ "required": false,
256
+ "description": "Inline styles applied to the rendered element.",
257
+ "from": "@types/react"
258
+ }
259
+ ]
260
+ },
261
+ {
262
+ "name": "HoverCardContext",
263
+ "props": [
264
+ {
265
+ "name": "children",
266
+ "type": "(context: UseHoverCardContext) => ReactNode",
267
+ "required": true,
268
+ "description": "Content rendered inside the part.",
269
+ "from": "@ark-ui/react"
270
+ }
271
+ ]
272
+ },
273
+ {
274
+ "name": "HoverCardPortal",
275
+ "props": [
276
+ {
277
+ "name": "children",
278
+ "type": "ReactNode",
279
+ "required": false,
280
+ "description": "Content rendered inside the part.",
281
+ "from": "@types/react"
282
+ },
283
+ {
284
+ "name": "container",
285
+ "type": "RefObject<HTMLElement | null>",
286
+ "required": false,
287
+ "from": "@ark-ui/react"
288
+ },
289
+ {
290
+ "name": "disabled",
291
+ "type": "boolean",
292
+ "required": false,
293
+ "description": "Disables the part and everything inside it.",
294
+ "from": "@ark-ui/react"
295
+ }
296
+ ]
297
+ },
298
+ {
299
+ "name": "HoverCardPositioner",
300
+ "props": [
301
+ {
302
+ "name": "asChild",
303
+ "type": "boolean",
304
+ "required": false,
305
+ "description": "Use the provided child element as the default rendered element, combining their props and behavior.",
306
+ "from": "@ark-ui/react"
307
+ },
308
+ {
309
+ "name": "children",
310
+ "type": "ReactNode",
311
+ "required": false,
312
+ "description": "Content rendered inside the part.",
313
+ "from": "@types/react"
314
+ },
315
+ {
316
+ "name": "className",
317
+ "type": "string",
318
+ "required": false,
319
+ "description": "Extra classes merged into the part's own classes with `cn`.",
320
+ "from": "@types/react"
321
+ },
322
+ {
323
+ "name": "style",
324
+ "type": "CSSProperties",
325
+ "required": false,
326
+ "description": "Inline styles applied to the rendered element.",
327
+ "from": "@types/react"
328
+ }
329
+ ]
330
+ },
331
+ {
332
+ "name": "HoverCardTrigger",
333
+ "props": [
334
+ {
335
+ "name": "asChild",
336
+ "type": "boolean",
337
+ "required": false,
338
+ "description": "Use the provided child element as the default rendered element, combining their props and behavior.",
339
+ "from": "@ark-ui/react"
340
+ },
341
+ {
342
+ "name": "children",
343
+ "type": "ReactNode",
344
+ "required": false,
345
+ "description": "Content rendered inside the part.",
346
+ "from": "@types/react"
347
+ },
348
+ {
349
+ "name": "className",
350
+ "type": "string",
351
+ "required": false,
352
+ "description": "Extra classes merged into the part's own classes with `cn`.",
353
+ "from": "@types/react"
354
+ },
355
+ {
356
+ "name": "style",
357
+ "type": "CSSProperties",
358
+ "required": false,
359
+ "description": "Inline styles applied to the rendered element.",
360
+ "from": "@types/react"
361
+ },
362
+ {
363
+ "name": "value",
364
+ "type": "string",
365
+ "required": false,
366
+ "description": "The value that identifies this specific trigger",
367
+ "from": "@zag-js/hover-card"
368
+ }
369
+ ]
370
+ }
371
+ ],
15
372
  "dependencies": {
16
373
  "@ark-ui/react": "^5.39.1"
17
374
  },