@blurrow/ui 0.1.0 → 0.2.1

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 (272) hide show
  1. package/README.md +60 -20
  2. package/dist/Accordion.d.ts +17 -0
  3. package/dist/Accordion.js +138 -0
  4. package/dist/Accordion.js.map +1 -0
  5. package/dist/Alert.d.ts +13 -0
  6. package/dist/Alert.js +69 -0
  7. package/dist/Alert.js.map +1 -0
  8. package/dist/AuthorCard.d.ts +12 -0
  9. package/dist/AuthorCard.js +57 -0
  10. package/dist/AuthorCard.js.map +1 -0
  11. package/dist/Avatar.d.ts +21 -0
  12. package/dist/Avatar.js +96 -0
  13. package/dist/Avatar.js.map +1 -0
  14. package/dist/Badge.d.ts +12 -0
  15. package/dist/Badge.js +46 -0
  16. package/dist/Badge.js.map +1 -0
  17. package/dist/Banner.d.ts +15 -0
  18. package/dist/Banner.js +68 -0
  19. package/dist/Banner.js.map +1 -0
  20. package/dist/Breadcrumb.d.ts +13 -0
  21. package/dist/Breadcrumb.js +45 -0
  22. package/dist/Breadcrumb.js.map +1 -0
  23. package/dist/Button.d.ts +19 -0
  24. package/dist/Button.js +282 -0
  25. package/dist/Button.js.map +1 -0
  26. package/dist/ButtonGroup.d.ts +19 -0
  27. package/dist/ButtonGroup.js +62 -0
  28. package/dist/ButtonGroup.js.map +1 -0
  29. package/dist/Card.d.ts +40 -0
  30. package/dist/Card.js +175 -0
  31. package/dist/Card.js.map +1 -0
  32. package/dist/CardShell.d.ts +18 -0
  33. package/dist/CardShell.js +58 -0
  34. package/dist/CardShell.js.map +1 -0
  35. package/dist/Carousel.d.ts +22 -0
  36. package/dist/Carousel.js +247 -0
  37. package/dist/Carousel.js.map +1 -0
  38. package/dist/Checkbox.d.ts +15 -0
  39. package/dist/Checkbox.js +84 -0
  40. package/dist/Checkbox.js.map +1 -0
  41. package/dist/CloseButton.d.ts +12 -0
  42. package/dist/CloseButton.js +63 -0
  43. package/dist/CloseButton.js.map +1 -0
  44. package/dist/CodeBlock.d.ts +12 -0
  45. package/dist/CodeBlock.js +221 -0
  46. package/dist/CodeBlock.js.map +1 -0
  47. package/dist/ColorPicker.d.ts +24 -0
  48. package/dist/ColorPicker.js +366 -0
  49. package/dist/ColorPicker.js.map +1 -0
  50. package/dist/Combobox.d.ts +34 -0
  51. package/dist/Combobox.js +255 -0
  52. package/dist/Combobox.js.map +1 -0
  53. package/dist/CommandPalette.d.ts +25 -0
  54. package/dist/CommandPalette.js +304 -0
  55. package/dist/CommandPalette.js.map +1 -0
  56. package/dist/ContextMenu.d.ts +16 -0
  57. package/dist/ContextMenu.js +209 -0
  58. package/dist/ContextMenu.js.map +1 -0
  59. package/dist/DataList.d.ts +15 -0
  60. package/dist/DataList.js +42 -0
  61. package/dist/DataList.js.map +1 -0
  62. package/dist/DatePicker.d.ts +65 -0
  63. package/dist/DatePicker.js +391 -0
  64. package/dist/DatePicker.js.map +1 -0
  65. package/dist/DateRangePicker.d.ts +34 -0
  66. package/dist/DateRangePicker.js +180 -0
  67. package/dist/DateRangePicker.js.map +1 -0
  68. package/dist/Drawer.d.ts +17 -0
  69. package/dist/Drawer.js +132 -0
  70. package/dist/Drawer.js.map +1 -0
  71. package/dist/DropdownMenu.d.ts +23 -0
  72. package/dist/DropdownMenu.js +185 -0
  73. package/dist/DropdownMenu.js.map +1 -0
  74. package/dist/EmptyState.d.ts +13 -0
  75. package/dist/EmptyState.js +55 -0
  76. package/dist/EmptyState.js.map +1 -0
  77. package/dist/FieldMessage.d.ts +26 -0
  78. package/dist/FieldMessage.js +95 -0
  79. package/dist/FieldMessage.js.map +1 -0
  80. package/dist/FileUpload.d.ts +32 -0
  81. package/dist/FileUpload.js +253 -0
  82. package/dist/FileUpload.js.map +1 -0
  83. package/dist/Floating.d.ts +32 -0
  84. package/dist/Floating.js +95 -0
  85. package/dist/Floating.js.map +1 -0
  86. package/dist/HoverCard.d.ts +18 -0
  87. package/dist/HoverCard.js +90 -0
  88. package/dist/HoverCard.js.map +1 -0
  89. package/dist/Input.d.ts +17 -0
  90. package/dist/Input.js +96 -0
  91. package/dist/Input.js.map +1 -0
  92. package/dist/Kbd.d.ts +9 -0
  93. package/dist/Kbd.js +24 -0
  94. package/dist/Kbd.js.map +1 -0
  95. package/dist/Modal.d.ts +15 -0
  96. package/dist/Modal.js +109 -0
  97. package/dist/Modal.js.map +1 -0
  98. package/dist/NumberInput.d.ts +23 -0
  99. package/dist/NumberInput.js +162 -0
  100. package/dist/NumberInput.js.map +1 -0
  101. package/dist/OtpInput.d.ts +26 -0
  102. package/dist/OtpInput.js +173 -0
  103. package/dist/OtpInput.js.map +1 -0
  104. package/dist/Pagination.d.ts +11 -0
  105. package/dist/Pagination.js +148 -0
  106. package/dist/Pagination.js.map +1 -0
  107. package/dist/Popover.d.ts +13 -0
  108. package/dist/Popover.js +98 -0
  109. package/dist/Popover.js.map +1 -0
  110. package/dist/Progress.d.ts +12 -0
  111. package/dist/Progress.js +61 -0
  112. package/dist/Progress.js.map +1 -0
  113. package/dist/QuoteCard.d.ts +13 -0
  114. package/dist/QuoteCard.js +92 -0
  115. package/dist/QuoteCard.js.map +1 -0
  116. package/dist/Radio.d.ts +19 -0
  117. package/dist/Radio.js +161 -0
  118. package/dist/Radio.js.map +1 -0
  119. package/dist/RadioCards.d.ts +27 -0
  120. package/dist/RadioCards.js +205 -0
  121. package/dist/RadioCards.js.map +1 -0
  122. package/dist/ReactionBar.d.ts +15 -0
  123. package/dist/ReactionBar.js +92 -0
  124. package/dist/ReactionBar.js.map +1 -0
  125. package/dist/ReadingProgress.d.ts +8 -0
  126. package/dist/ReadingProgress.js +51 -0
  127. package/dist/ReadingProgress.js.map +1 -0
  128. package/dist/ReadingTime.d.ts +9 -0
  129. package/dist/ReadingTime.js +39 -0
  130. package/dist/ReadingTime.js.map +1 -0
  131. package/dist/Select.d.ts +20 -0
  132. package/dist/Select.js +244 -0
  133. package/dist/Select.js.map +1 -0
  134. package/dist/Separator.d.ts +14 -0
  135. package/dist/Separator.js +33 -0
  136. package/dist/Separator.js.map +1 -0
  137. package/dist/ShareButtons.d.ts +10 -0
  138. package/dist/ShareButtons.js +107 -0
  139. package/dist/ShareButtons.js.map +1 -0
  140. package/dist/Sidebar.d.ts +30 -0
  141. package/dist/Sidebar.js +140 -0
  142. package/dist/Sidebar.js.map +1 -0
  143. package/dist/Skeleton.d.ts +15 -0
  144. package/dist/Skeleton.js +67 -0
  145. package/dist/Skeleton.js.map +1 -0
  146. package/dist/Slider.d.ts +27 -0
  147. package/dist/Slider.js +182 -0
  148. package/dist/Slider.js.map +1 -0
  149. package/dist/Spinner.d.ts +12 -0
  150. package/dist/Spinner.js +24 -0
  151. package/dist/Spinner.js.map +1 -0
  152. package/dist/SpotlightCard.d.ts +17 -0
  153. package/dist/SpotlightCard.js +87 -0
  154. package/dist/SpotlightCard.js.map +1 -0
  155. package/dist/Stat.d.ts +19 -0
  156. package/dist/Stat.js +71 -0
  157. package/dist/Stat.js.map +1 -0
  158. package/dist/StatCard.d.ts +24 -0
  159. package/dist/StatCard.js +212 -0
  160. package/dist/StatCard.js.map +1 -0
  161. package/dist/Steps.d.ts +14 -0
  162. package/dist/Steps.js +94 -0
  163. package/dist/Steps.js.map +1 -0
  164. package/dist/Table.d.ts +21 -0
  165. package/dist/Table.js +93 -0
  166. package/dist/Table.js.map +1 -0
  167. package/dist/TableOfContents.d.ts +17 -0
  168. package/dist/TableOfContents.js +92 -0
  169. package/dist/TableOfContents.js.map +1 -0
  170. package/dist/Tabs.d.ts +17 -0
  171. package/dist/Tabs.js +123 -0
  172. package/dist/Tabs.js.map +1 -0
  173. package/dist/TagInput.d.ts +16 -0
  174. package/dist/TagInput.js +169 -0
  175. package/dist/TagInput.js.map +1 -0
  176. package/dist/Textarea.d.ts +13 -0
  177. package/dist/Textarea.js +74 -0
  178. package/dist/Textarea.js.map +1 -0
  179. package/dist/TimePicker.d.ts +28 -0
  180. package/dist/TimePicker.js +264 -0
  181. package/dist/TimePicker.js.map +1 -0
  182. package/dist/Timeline.d.ts +19 -0
  183. package/dist/Timeline.js +76 -0
  184. package/dist/Timeline.js.map +1 -0
  185. package/dist/Toast.d.ts +18 -0
  186. package/dist/Toast.js +318 -0
  187. package/dist/Toast.js.map +1 -0
  188. package/dist/Toggle.d.ts +13 -0
  189. package/dist/Toggle.js +84 -0
  190. package/dist/Toggle.js.map +1 -0
  191. package/dist/Tooltip.d.ts +13 -0
  192. package/dist/Tooltip.js +138 -0
  193. package/dist/Tooltip.js.map +1 -0
  194. package/dist/cli.js +1644 -0
  195. package/dist/index.d.ts +68 -631
  196. package/dist/index.js +67 -5558
  197. package/dist/index.js.map +1 -1
  198. package/dist/registry/Accordion.tsx +140 -0
  199. package/dist/registry/Alert.tsx +95 -0
  200. package/dist/registry/AuthorCard.tsx +67 -0
  201. package/dist/registry/Avatar.tsx +116 -0
  202. package/dist/registry/Badge.tsx +55 -0
  203. package/dist/registry/Banner.tsx +86 -0
  204. package/dist/registry/Breadcrumb.tsx +60 -0
  205. package/dist/registry/Button.tsx +361 -0
  206. package/dist/registry/ButtonGroup.tsx +82 -0
  207. package/dist/registry/Card.tsx +241 -0
  208. package/dist/registry/CardShell.tsx +78 -0
  209. package/dist/registry/Carousel.tsx +296 -0
  210. package/dist/registry/Checkbox.tsx +104 -0
  211. package/dist/registry/CloseButton.tsx +68 -0
  212. package/dist/registry/CodeBlock.tsx +202 -0
  213. package/dist/registry/ColorPicker.tsx +404 -0
  214. package/dist/registry/Combobox.tsx +318 -0
  215. package/dist/registry/CommandPalette.tsx +356 -0
  216. package/dist/registry/ContextMenu.tsx +241 -0
  217. package/dist/registry/DataList.tsx +49 -0
  218. package/dist/registry/DatePicker.tsx +494 -0
  219. package/dist/registry/DateRangePicker.tsx +232 -0
  220. package/dist/registry/Drawer.tsx +166 -0
  221. package/dist/registry/DropdownMenu.tsx +219 -0
  222. package/dist/registry/EmptyState.tsx +55 -0
  223. package/dist/registry/FieldMessage.tsx +123 -0
  224. package/dist/registry/FileUpload.tsx +318 -0
  225. package/dist/registry/Floating.tsx +134 -0
  226. package/dist/registry/HoverCard.tsx +113 -0
  227. package/dist/registry/Input.tsx +108 -0
  228. package/dist/registry/Kbd.tsx +23 -0
  229. package/dist/registry/Modal.tsx +130 -0
  230. package/dist/registry/NumberInput.tsx +183 -0
  231. package/dist/registry/OtpInput.tsx +219 -0
  232. package/dist/registry/Pagination.tsx +160 -0
  233. package/dist/registry/Popover.tsx +116 -0
  234. package/dist/registry/Progress.tsx +66 -0
  235. package/dist/registry/QuoteCard.tsx +93 -0
  236. package/dist/registry/Radio.tsx +205 -0
  237. package/dist/registry/RadioCards.tsx +247 -0
  238. package/dist/registry/ReactionBar.tsx +101 -0
  239. package/dist/registry/ReadingProgress.tsx +51 -0
  240. package/dist/registry/ReadingTime.tsx +35 -0
  241. package/dist/registry/Select.tsx +265 -0
  242. package/dist/registry/Separator.tsx +52 -0
  243. package/dist/registry/ShareButtons.tsx +134 -0
  244. package/dist/registry/Sidebar.tsx +182 -0
  245. package/dist/registry/Skeleton.tsx +83 -0
  246. package/dist/registry/Slider.tsx +229 -0
  247. package/dist/registry/Spinner.tsx +32 -0
  248. package/dist/registry/SpotlightCard.tsx +106 -0
  249. package/dist/registry/Stat.tsx +82 -0
  250. package/dist/registry/StatCard.tsx +256 -0
  251. package/dist/registry/Steps.tsx +109 -0
  252. package/dist/registry/Table.tsx +123 -0
  253. package/dist/registry/TableOfContents.tsx +116 -0
  254. package/dist/registry/Tabs.tsx +136 -0
  255. package/dist/registry/TagInput.tsx +191 -0
  256. package/dist/registry/Textarea.tsx +84 -0
  257. package/dist/registry/TimePicker.tsx +315 -0
  258. package/dist/registry/Timeline.tsx +102 -0
  259. package/dist/registry/Toast.tsx +388 -0
  260. package/dist/registry/Toggle.tsx +96 -0
  261. package/dist/registry/Tooltip.tsx +160 -0
  262. package/dist/registry/styles.css +1207 -0
  263. package/dist/registry/useFloatingPanel.ts +112 -0
  264. package/dist/registry/useModalBehavior.ts +77 -0
  265. package/dist/styles.css +868 -62
  266. package/dist/useFloatingPanel.d.ts +24 -0
  267. package/dist/useFloatingPanel.js +89 -0
  268. package/dist/useFloatingPanel.js.map +1 -0
  269. package/dist/useModalBehavior.d.ts +15 -0
  270. package/dist/useModalBehavior.js +57 -0
  271. package/dist/useModalBehavior.js.map +1 -0
  272. package/package.json +23 -6
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../components/ui/CommandPalette.tsx"],"sourcesContent":["\"use client\";\n\nimport React, {\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useMemo,\n useCallback,\n useId,\n} from \"react\";\nimport { Portal } from \"./Floating\";\nimport { Kbd } from \"./Kbd\";\nimport { useModalBehavior } from \"./useModalBehavior\";\n\ninterface CommandItem {\n key: string;\n label: string;\n description?: string;\n icon?: React.ReactNode;\n shortcut?: string;\n onSelect?: () => void;\n}\n\ninterface CommandSection {\n title: string;\n items: CommandItem[];\n}\n\ninterface CommandPaletteProps {\n open: boolean;\n onClose: () => void;\n sections: CommandSection[];\n placeholder?: string;\n className?: string;\n}\n\nconst CLOSE_MS = 240;\n\nexport function CommandPalette({\n open,\n onClose,\n sections,\n placeholder = \"search commands…\",\n className = \"\",\n}: CommandPaletteProps) {\n const [mounted, setMounted] = useState(false);\n const [visible, setVisible] = useState(false);\n const [query, setQuery] = useState(\"\");\n const [activeIndex, setActiveIndex] = useState(0);\n\n const dialogRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const uid = useId();\n\n // Filter sections based on query\n const filtered = useMemo(() => {\n const q = query.toLowerCase().trim();\n if (!q) return sections;\n return sections\n .map((section) => ({\n ...section,\n items: section.items.filter(\n (item) =>\n item.label.toLowerCase().includes(q) ||\n item.description?.toLowerCase().includes(q),\n ),\n }))\n .filter((section) => section.items.length > 0);\n }, [sections, query]);\n\n // Flat list of all visible items for keyboard nav\n const flatItems = useMemo(\n () => filtered.flatMap((s) => s.items),\n [filtered],\n );\n\n // Mount / unmount lifecycle (matches Modal pattern); every opening starts fresh\n const [wasOpen, setWasOpen] = useState(false);\n if (open !== wasOpen) {\n setWasOpen(open);\n if (open) {\n setMounted(true);\n setQuery(\"\");\n setActiveIndex(0);\n } else {\n setVisible(false);\n }\n }\n\n useEffect(() => {\n if (open || !mounted) return;\n const t = setTimeout(() => setMounted(false), CLOSE_MS);\n return () => clearTimeout(t);\n }, [open, mounted]);\n\n // Enter animation (matches Modal pattern)\n useLayoutEffect(() => {\n if (!mounted || !open || visible) return;\n\n const el = dialogRef.current;\n if (el) {\n void el.getBoundingClientRect();\n }\n\n const id = requestAnimationFrame(() => {\n setVisible(true);\n });\n return () => cancelAnimationFrame(id);\n }, [mounted, open, visible]);\n\n // Reset active index when filter changes\n useEffect(() => {\n setActiveIndex(0);\n }, [query]);\n\n // Scroll active item into view\n useEffect(() => {\n if (!listRef.current) return;\n const activeEl = listRef.current.querySelector(\n `[data-command-index=\"${activeIndex}\"]`,\n );\n if (activeEl) {\n activeEl.scrollIntoView({ block: \"nearest\" });\n }\n }, [activeIndex]);\n\n // Handle selection\n const handleSelect = useCallback(\n (item: CommandItem) => {\n item.onSelect?.();\n onClose();\n },\n [onClose],\n );\n\n // Keyboard navigation\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n setActiveIndex((i) => (i + 1 >= flatItems.length ? 0 : i + 1));\n break;\n case \"ArrowUp\":\n e.preventDefault();\n setActiveIndex((i) =>\n i - 1 < 0 ? Math.max(flatItems.length - 1, 0) : i - 1,\n );\n break;\n case \"Enter\":\n e.preventDefault();\n if (flatItems[activeIndex]) {\n handleSelect(flatItems[activeIndex]);\n }\n break;\n }\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, onClose, flatItems, activeIndex, handleSelect]);\n\n // Escape, focus trap + restore, scroll lock\n useModalBehavior({ open, ready: visible, ref: dialogRef, onClose, initialFocus: inputRef });\n\n if (!mounted) return null;\n\n let itemIndex = 0;\n\n return (\n <Portal>\n <div className=\"fixed inset-0 z-90 flex items-start justify-center pt-[min(20vh,140px)] px-4\">\n {/* Backdrop */}\n <div\n className={[\n \"absolute inset-0 backdrop-blur-[6px]\",\n \"transition-opacity ease-out\",\n visible ? \"opacity-100 duration-300\" : \"opacity-0 duration-200\",\n ].join(\" \")}\n style={{ background: \"var(--scrim)\" }}\n aria-hidden\n onClick={onClose}\n />\n\n {/* Palette panel */}\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Command palette\"\n className={[\n \"relative z-10 w-full max-w-lg rounded-[20px] p-1.5 overflow-hidden\",\n \"transition-[opacity,transform,scale,translate] ease-[var(--ease-spring)]\",\n visible\n ? \"opacity-100 scale-100 translate-y-0 duration-300\"\n : \"opacity-0 scale-[0.94] translate-y-3 duration-200\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n style={{ background: \"var(--panel-bezel)\", boxShadow: \"var(--modal-shadow)\" }}\n >\n <div\n className=\"bg-panel-face rounded-[14px] overflow-hidden\"\n style={{ boxShadow: \"var(--panel-face-shadow)\" }}\n >\n {/* Search input */}\n <div className=\"flex items-center gap-3 px-4 py-3.5\">\n <svg\n className=\"shrink-0 text-ink-faint\"\n width=\"14\"\n height=\"14\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M21 21l-4.35-4.35M11 19a8 8 0 100-16 8 8 0 000 16z\"\n />\n </svg>\n <input\n ref={inputRef}\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={placeholder}\n role=\"combobox\"\n aria-expanded=\"true\"\n aria-controls={`${uid}-list`}\n aria-activedescendant={flatItems[activeIndex] ? `${uid}-item-${activeIndex}` : undefined}\n aria-autocomplete=\"list\"\n className=\"flex-1 min-w-0 text-[14.5px] font-medium text-ink placeholder:text-ink-faint placeholder:font-normal bg-transparent border-none outline-none\"\n />\n <Kbd className=\"shrink-0\">esc</Kbd>\n </div>\n\n {/* Separator */}\n <div className=\"border-b border-line\" />\n\n {/* Results */}\n <div\n ref={listRef}\n id={`${uid}-list`}\n role=\"listbox\"\n className=\"max-h-[340px] overflow-y-auto scroll-thin py-2 px-2\"\n >\n {filtered.length === 0 ? (\n <div className=\"py-10 flex flex-col items-center gap-1 text-center\">\n <p className=\"text-[13px] font-medium text-ink-label\">\n nothing for &ldquo;{query}&rdquo;\n </p>\n <p className=\"text-[12px] text-ink-faint\">try a shorter or different word.</p>\n </div>\n ) : (\n filtered.map((section, si) => (\n <div key={section.title} role=\"group\" aria-label={section.title} className={si > 0 ? \"mt-3\" : \"\"}>\n <div aria-hidden className=\"px-3 py-1.5 text-[11.5px] font-medium text-ink-faint lowercase select-none\">\n {section.title}\n </div>\n <div className=\"flex flex-col gap-0.5\">\n {section.items.map((item) => {\n const currentIndex = itemIndex++;\n const isActive = currentIndex === activeIndex;\n return (\n <div\n key={item.key}\n id={`${uid}-item-${currentIndex}`}\n role=\"option\"\n aria-selected={isActive}\n data-command-index={currentIndex}\n onClick={() => handleSelect(item)}\n onMouseMove={() => setActiveIndex(currentIndex)}\n className={[\n \"group/cmd flex items-center gap-3 w-full text-left px-3 py-2 rounded-[10px] cursor-pointer\",\n \"transition-[background,box-shadow] duration-100\",\n isActive ? \"bg-surface-hover\" : \"\",\n ].join(\" \")}\n style={{ boxShadow: isActive ? \"var(--panel-face-shadow)\" : undefined }}\n >\n {item.icon && (\n <span\n className={[\n \"shrink-0 w-7 h-7 rounded-[8px] flex items-center justify-center transition-colors duration-100\",\n isActive ? \"text-ink\" : \"text-ink-muted\",\n ].join(\" \")}\n style={{ background: \"var(--face)\", boxShadow: \"var(--face-shadow)\" }}\n >\n {item.icon}\n </span>\n )}\n <div className=\"flex-1 min-w-0 flex flex-col\">\n <span className=\"text-[13px] font-medium text-ink truncate\">\n {item.label}\n </span>\n {item.description && (\n <span className=\"text-[12px] text-ink-muted truncate\">\n {item.description}\n </span>\n )}\n </div>\n {item.shortcut && <Kbd className=\"shrink-0\">{item.shortcut}</Kbd>}\n {!item.shortcut && (\n <svg\n aria-hidden\n width=\"12\"\n height=\"12\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n className={[\n \"shrink-0 text-ink-faint transition-all duration-150\",\n isActive ? \"opacity-100 translate-x-0\" : \"opacity-0 -translate-x-1\",\n ].join(\" \")}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n )}\n </div>\n );\n })}\n </div>\n </div>\n ))\n )}\n </div>\n\n {/* Key hints — teach the palette while it's open */}\n <div\n className=\"flex items-center gap-4 px-4 py-2.5 border-t border-line text-[11.5px] text-ink-muted select-none\"\n style={{ background: \"var(--palette-tray)\" }}\n >\n <span className=\"inline-flex items-center gap-1.5\">\n <Kbd>↑</Kbd>\n <Kbd>↓</Kbd>\n Navigate\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <Kbd>↵</Kbd>\n Open\n </span>\n <span className=\"ml-auto tabular-nums text-ink-faint\">\n {flatItems.length} {flatItems.length === 1 ? \"result\" : \"results\"}\n </span>\n </div>\n </div>\n </div>\n </div>\n </Portal>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,16 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { DropdownMenuItem } from './DropdownMenu.js';
4
+
5
+ type ContextMenuItem = DropdownMenuItem;
6
+ interface ContextMenuProps {
7
+ /** The area that answers a right-click */
8
+ children: React.ReactNode;
9
+ items: ContextMenuItem[];
10
+ onSelect?: (key: string) => void;
11
+ disabled?: boolean;
12
+ className?: string;
13
+ }
14
+ declare function ContextMenu({ children, items, onSelect, disabled, className }: ContextMenuProps): react_jsx_runtime.JSX.Element;
15
+
16
+ export { ContextMenu, type ContextMenuItem };
@@ -0,0 +1,209 @@
1
+ "use client";
2
+
3
+ // ../../components/ui/ContextMenu.tsx
4
+ import { useEffect, useId, useRef, useState } from "react";
5
+ import { LAYER, Portal } from "./Floating.js";
6
+ import { Kbd } from "./Kbd.js";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ var PAD = 8;
9
+ var LONG_PRESS = 500;
10
+ function ContextMenu({ children, items, onSelect, disabled = false, className = "" }) {
11
+ const uid = useId();
12
+ const areaRef = useRef(null);
13
+ const menuRef = useRef(null);
14
+ const [point, setPoint] = useState(null);
15
+ const [mounted, setMounted] = useState(false);
16
+ const [visible, setVisible] = useState(false);
17
+ const press = useRef(null);
18
+ const open = point !== null;
19
+ if (open && !mounted) setMounted(true);
20
+ if (!open && visible) setVisible(false);
21
+ const enabledItems = () => Array.from(menuRef.current?.querySelectorAll('[role="menuitem"]:not([disabled])') ?? []);
22
+ useEffect(() => {
23
+ if (open) {
24
+ const id = requestAnimationFrame(
25
+ () => requestAnimationFrame(() => {
26
+ setVisible(true);
27
+ menuRef.current?.querySelector('[role="menuitem"]:not([disabled])')?.focus();
28
+ })
29
+ );
30
+ return () => cancelAnimationFrame(id);
31
+ }
32
+ const t = setTimeout(() => setMounted(false), 160);
33
+ return () => clearTimeout(t);
34
+ }, [open]);
35
+ useEffect(() => {
36
+ if (!open) return;
37
+ const shut = (e) => {
38
+ if (menuRef.current?.contains(e.target)) return;
39
+ setPoint(null);
40
+ };
41
+ const onScroll = () => setPoint(null);
42
+ document.addEventListener("pointerdown", shut);
43
+ window.addEventListener("scroll", onScroll, true);
44
+ window.addEventListener("resize", onScroll);
45
+ window.addEventListener("blur", onScroll);
46
+ return () => {
47
+ document.removeEventListener("pointerdown", shut);
48
+ window.removeEventListener("scroll", onScroll, true);
49
+ window.removeEventListener("resize", onScroll);
50
+ window.removeEventListener("blur", onScroll);
51
+ };
52
+ }, [open]);
53
+ const attach = (el) => {
54
+ menuRef.current = el;
55
+ if (!el || !point) return;
56
+ const w = el.offsetWidth;
57
+ const h = el.offsetHeight;
58
+ const vw = document.documentElement.clientWidth;
59
+ const vh = window.innerHeight;
60
+ const flipX = point.x + w > vw - PAD;
61
+ const flipY = point.y + h > vh - PAD;
62
+ el.style.left = `${Math.max(PAD, flipX ? point.x - w : point.x)}px`;
63
+ el.style.top = `${Math.max(PAD, flipY ? point.y - h : point.y)}px`;
64
+ el.style.transformOrigin = `${flipY ? "bottom" : "top"} ${flipX ? "right" : "left"}`;
65
+ };
66
+ const openAt = (x, y) => {
67
+ if (disabled) return;
68
+ setPoint({ x, y });
69
+ };
70
+ const close = (refocus = true) => {
71
+ setPoint(null);
72
+ if (refocus) areaRef.current?.focus({ preventScroll: true });
73
+ };
74
+ const onMenuKeyDown = (e) => {
75
+ const list = enabledItems();
76
+ const at = list.indexOf(document.activeElement);
77
+ const go = (i) => list[(i + list.length) % list.length]?.focus();
78
+ switch (e.key) {
79
+ case "ArrowDown":
80
+ e.preventDefault();
81
+ go(at + 1);
82
+ break;
83
+ case "ArrowUp":
84
+ e.preventDefault();
85
+ go(at - 1);
86
+ break;
87
+ case "Home":
88
+ e.preventDefault();
89
+ go(0);
90
+ break;
91
+ case "End":
92
+ e.preventDefault();
93
+ go(list.length - 1);
94
+ break;
95
+ case "Escape":
96
+ e.preventDefault();
97
+ e.stopPropagation();
98
+ close();
99
+ break;
100
+ case "Tab":
101
+ e.preventDefault();
102
+ close();
103
+ break;
104
+ }
105
+ };
106
+ const cancelPress = () => {
107
+ if (press.current) clearTimeout(press.current);
108
+ };
109
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
110
+ /* @__PURE__ */ jsxs(
111
+ "div",
112
+ {
113
+ ref: areaRef,
114
+ tabIndex: 0,
115
+ "aria-haspopup": "menu",
116
+ "aria-expanded": open,
117
+ "aria-controls": open ? `${uid}-menu` : void 0,
118
+ "aria-describedby": `${uid}-how`,
119
+ className: ["outline-none focus-visible:ring-2 focus-visible:ring-ink focus-visible:ring-offset-2 focus-visible:ring-offset-page", className].join(" "),
120
+ onContextMenu: (e) => {
121
+ if (disabled) return;
122
+ e.preventDefault();
123
+ openAt(e.clientX, e.clientY);
124
+ },
125
+ onKeyDown: (e) => {
126
+ if (e.key === "ContextMenu" || e.shiftKey && e.key === "F10") {
127
+ e.preventDefault();
128
+ const r = areaRef.current.getBoundingClientRect();
129
+ openAt(r.left + 16, r.top + 16);
130
+ }
131
+ },
132
+ onPointerDown: (e) => {
133
+ if (e.pointerType !== "touch") return;
134
+ const { clientX, clientY } = e;
135
+ cancelPress();
136
+ press.current = setTimeout(() => openAt(clientX, clientY), LONG_PRESS);
137
+ },
138
+ onPointerUp: cancelPress,
139
+ onPointerMove: cancelPress,
140
+ onPointerCancel: cancelPress,
141
+ children: [
142
+ children,
143
+ /* @__PURE__ */ jsx("span", { id: `${uid}-how`, className: "sr-only", children: "right-click, long-press, or press shift f10 for options" })
144
+ ]
145
+ }
146
+ ),
147
+ mounted && /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(
148
+ "div",
149
+ {
150
+ ref: attach,
151
+ id: `${uid}-menu`,
152
+ role: "menu",
153
+ onKeyDown: onMenuKeyDown,
154
+ onContextMenu: (e) => e.preventDefault(),
155
+ className: "min-w-[200px] rounded-[16px] p-1.5 transition-[opacity,transform] duration-150 ease-[var(--ease-spring)]",
156
+ style: {
157
+ position: "fixed",
158
+ top: 0,
159
+ left: 0,
160
+ zIndex: LAYER.floating,
161
+ opacity: visible ? 1 : 0,
162
+ transform: visible ? "none" : "scale(0.94)",
163
+ background: "var(--panel-bezel)",
164
+ boxShadow: "var(--overlay-shadow)"
165
+ },
166
+ children: /* @__PURE__ */ jsx("div", { className: "flex flex-col rounded-[11px] bg-panel-face p-1", style: { boxShadow: "var(--panel-face-shadow)" }, children: items.map(
167
+ (item) => item.divider ? /* @__PURE__ */ jsx("div", { role: "separator", className: "mx-2 my-1 h-px bg-line" }, item.key) : /* @__PURE__ */ jsxs(
168
+ "button",
169
+ {
170
+ type: "button",
171
+ role: "menuitem",
172
+ tabIndex: -1,
173
+ disabled: item.disabled,
174
+ onClick: () => {
175
+ onSelect?.(item.key);
176
+ close();
177
+ },
178
+ onMouseEnter: (e) => e.currentTarget.focus(),
179
+ className: [
180
+ "group/item flex w-full cursor-pointer items-center gap-2.5 rounded-[8px] px-2.5 py-2 text-[13px] font-medium outline-none",
181
+ "transition-[background,color] duration-100 disabled:pointer-events-none disabled:opacity-35",
182
+ item.danger ? "text-danger focus:bg-danger-wash" : "text-ink-label focus:bg-surface-active/80 focus:text-ink"
183
+ ].join(" "),
184
+ children: [
185
+ item.icon && /* @__PURE__ */ jsx(
186
+ "span",
187
+ {
188
+ className: [
189
+ "flex h-4 w-4 shrink-0 items-center justify-center transition-colors duration-100",
190
+ item.danger ? "text-danger-soft" : "text-ink-faint group-focus/item:text-ink-label"
191
+ ].join(" "),
192
+ children: item.icon
193
+ }
194
+ ),
195
+ /* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: item.label }),
196
+ item.shortcut && /* @__PURE__ */ jsx(Kbd, { className: "shrink-0", children: item.shortcut })
197
+ ]
198
+ },
199
+ item.key
200
+ )
201
+ ) })
202
+ }
203
+ ) })
204
+ ] });
205
+ }
206
+ export {
207
+ ContextMenu
208
+ };
209
+ //# sourceMappingURL=ContextMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../components/ui/ContextMenu.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useEffect, useId, useRef, useState } from \"react\";\nimport type { DropdownMenuItem } from \"./DropdownMenu\";\nimport { LAYER, Portal } from \"./Floating\";\nimport { Kbd } from \"./Kbd\";\n\nexport type ContextMenuItem = DropdownMenuItem;\n\ninterface ContextMenuProps {\n /** The area that answers a right-click */\n children: React.ReactNode;\n items: ContextMenuItem[];\n onSelect?: (key: string) => void;\n disabled?: boolean;\n className?: string;\n}\n\nconst PAD = 8;\nconst LONG_PRESS = 500;\n\n/* The same panel as DropdownMenu, opened where you right-click instead of\n under a button. A long press opens it on touch, and the context-menu\n key or shift+F10 opens it from the keyboard at the focused element.\n It grows out of the corner nearest the pointer and flips to stay on\n screen. */\nexport function ContextMenu({ children, items, onSelect, disabled = false, className = \"\" }: ContextMenuProps) {\n const uid = useId();\n const areaRef = useRef<HTMLDivElement>(null);\n const menuRef = useRef<HTMLDivElement | null>(null);\n const [point, setPoint] = useState<{ x: number; y: number } | null>(null);\n const [mounted, setMounted] = useState(false);\n const [visible, setVisible] = useState(false);\n const press = useRef<ReturnType<typeof setTimeout> | null>(null);\n const open = point !== null;\n\n if (open && !mounted) setMounted(true);\n if (!open && visible) setVisible(false);\n\n const enabledItems = () =>\n Array.from(menuRef.current?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]:not([disabled])') ?? []);\n\n useEffect(() => {\n if (open) {\n const id = requestAnimationFrame(() =>\n requestAnimationFrame(() => {\n setVisible(true);\n menuRef.current?.querySelector<HTMLElement>('[role=\"menuitem\"]:not([disabled])')?.focus();\n }),\n );\n return () => cancelAnimationFrame(id);\n }\n const t = setTimeout(() => setMounted(false), 160);\n return () => clearTimeout(t);\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n const shut = (e: Event) => {\n if (menuRef.current?.contains(e.target as Node)) return;\n setPoint(null);\n };\n const onScroll = () => setPoint(null);\n document.addEventListener(\"pointerdown\", shut);\n window.addEventListener(\"scroll\", onScroll, true);\n window.addEventListener(\"resize\", onScroll);\n window.addEventListener(\"blur\", onScroll);\n return () => {\n document.removeEventListener(\"pointerdown\", shut);\n window.removeEventListener(\"scroll\", onScroll, true);\n window.removeEventListener(\"resize\", onScroll);\n window.removeEventListener(\"blur\", onScroll);\n };\n }, [open]);\n\n /* Placed as soon as it's attached: beside the pointer, flipped left or\n up if it would run off the edge. Only writes to the element, so it\n can run on every render without setting state. */\n const attach = (el: HTMLDivElement | null) => {\n menuRef.current = el;\n if (!el || !point) return;\n const w = el.offsetWidth;\n const h = el.offsetHeight;\n const vw = document.documentElement.clientWidth;\n const vh = window.innerHeight;\n const flipX = point.x + w > vw - PAD;\n const flipY = point.y + h > vh - PAD;\n el.style.left = `${Math.max(PAD, flipX ? point.x - w : point.x)}px`;\n el.style.top = `${Math.max(PAD, flipY ? point.y - h : point.y)}px`;\n el.style.transformOrigin = `${flipY ? \"bottom\" : \"top\"} ${flipX ? \"right\" : \"left\"}`;\n };\n\n const openAt = (x: number, y: number) => {\n if (disabled) return;\n setPoint({ x, y });\n };\n\n const close = (refocus = true) => {\n setPoint(null);\n if (refocus) areaRef.current?.focus({ preventScroll: true });\n };\n\n const onMenuKeyDown = (e: React.KeyboardEvent) => {\n const list = enabledItems();\n const at = list.indexOf(document.activeElement as HTMLElement);\n const go = (i: number) => list[(i + list.length) % list.length]?.focus();\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n go(at + 1);\n break;\n case \"ArrowUp\":\n e.preventDefault();\n go(at - 1);\n break;\n case \"Home\":\n e.preventDefault();\n go(0);\n break;\n case \"End\":\n e.preventDefault();\n go(list.length - 1);\n break;\n case \"Escape\":\n e.preventDefault();\n e.stopPropagation();\n close();\n break;\n case \"Tab\":\n e.preventDefault();\n close();\n break;\n }\n };\n\n const cancelPress = () => {\n if (press.current) clearTimeout(press.current);\n };\n\n return (\n <>\n <div\n ref={areaRef}\n tabIndex={0}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={open ? `${uid}-menu` : undefined}\n aria-describedby={`${uid}-how`}\n className={[\"outline-none focus-visible:ring-2 focus-visible:ring-ink focus-visible:ring-offset-2 focus-visible:ring-offset-page\", className].join(\" \")}\n onContextMenu={(e) => {\n if (disabled) return;\n e.preventDefault();\n openAt(e.clientX, e.clientY);\n }}\n onKeyDown={(e) => {\n if (e.key === \"ContextMenu\" || (e.shiftKey && e.key === \"F10\")) {\n e.preventDefault();\n const r = areaRef.current!.getBoundingClientRect();\n openAt(r.left + 16, r.top + 16);\n }\n }}\n onPointerDown={(e) => {\n if (e.pointerType !== \"touch\") return;\n const { clientX, clientY } = e;\n cancelPress();\n press.current = setTimeout(() => openAt(clientX, clientY), LONG_PRESS);\n }}\n onPointerUp={cancelPress}\n onPointerMove={cancelPress}\n onPointerCancel={cancelPress}\n >\n {children}\n <span id={`${uid}-how`} className=\"sr-only\">\n right-click, long-press, or press shift f10 for options\n </span>\n </div>\n\n {mounted && (\n <Portal>\n <div\n ref={attach}\n id={`${uid}-menu`}\n role=\"menu\"\n onKeyDown={onMenuKeyDown}\n onContextMenu={(e) => e.preventDefault()}\n className=\"min-w-[200px] rounded-[16px] p-1.5 transition-[opacity,transform] duration-150 ease-[var(--ease-spring)]\"\n style={{\n position: \"fixed\",\n top: 0,\n left: 0,\n zIndex: LAYER.floating,\n opacity: visible ? 1 : 0,\n transform: visible ? \"none\" : \"scale(0.94)\",\n background: \"var(--panel-bezel)\",\n boxShadow: \"var(--overlay-shadow)\",\n }}\n >\n <div className=\"flex flex-col rounded-[11px] bg-panel-face p-1\" style={{ boxShadow: \"var(--panel-face-shadow)\" }}>\n {items.map((item) =>\n item.divider ? (\n <div key={item.key} role=\"separator\" className=\"mx-2 my-1 h-px bg-line\" />\n ) : (\n <button\n key={item.key}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n disabled={item.disabled}\n onClick={() => {\n onSelect?.(item.key);\n close();\n }}\n onMouseEnter={(e) => e.currentTarget.focus()}\n className={[\n \"group/item flex w-full cursor-pointer items-center gap-2.5 rounded-[8px] px-2.5 py-2 text-[13px] font-medium outline-none\",\n \"transition-[background,color] duration-100 disabled:pointer-events-none disabled:opacity-35\",\n item.danger ? \"text-danger focus:bg-danger-wash\" : \"text-ink-label focus:bg-surface-active/80 focus:text-ink\",\n ].join(\" \")}\n >\n {item.icon && (\n <span\n className={[\n \"flex h-4 w-4 shrink-0 items-center justify-center transition-colors duration-100\",\n item.danger ? \"text-danger-soft\" : \"text-ink-faint group-focus/item:text-ink-label\",\n ].join(\" \")}\n >\n {item.icon}\n </span>\n )}\n <span className=\"flex-1 text-left\">{item.label}</span>\n {item.shortcut && <Kbd className=\"shrink-0\">{item.shortcut}</Kbd>}\n </button>\n ),\n )}\n </div>\n </div>\n </Portal>\n )}\n </>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,15 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+
4
+ interface DataListItem {
5
+ label: string;
6
+ value: React.ReactNode;
7
+ }
8
+ interface DataListProps {
9
+ items: DataListItem[];
10
+ columns?: 1 | 2;
11
+ className?: string;
12
+ }
13
+ declare function DataList({ items, columns, className }: DataListProps): react_jsx_runtime.JSX.Element;
14
+
15
+ export { DataList };
@@ -0,0 +1,42 @@
1
+ // ../../components/ui/DataList.tsx
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ function DataList({ items, columns = 1, className = "" }) {
4
+ return /* @__PURE__ */ jsx(
5
+ "div",
6
+ {
7
+ className: ["rounded-[18px] p-1.5", className].filter(Boolean).join(" "),
8
+ style: { background: "var(--panel-bezel)", boxShadow: "var(--panel-shadow)" },
9
+ children: /* @__PURE__ */ jsx(
10
+ "dl",
11
+ {
12
+ className: [
13
+ // 1px gaps over a hairline-coloured face draw the grid lines, so
14
+ // borders never double up whatever the item count
15
+ "grid gap-px bg-ink/[0.05] rounded-[13px] overflow-hidden",
16
+ columns === 2 ? "grid-cols-1 sm:grid-cols-2" : "grid-cols-1"
17
+ ].join(" "),
18
+ style: { boxShadow: "var(--panel-face-shadow)" },
19
+ children: items.map((item, i) => /* @__PURE__ */ jsxs(
20
+ "div",
21
+ {
22
+ className: [
23
+ "flex flex-col gap-1.5 px-5 py-4 bg-panel-face",
24
+ // An odd last cell in two columns spans the row instead of leaving a hole
25
+ columns === 2 && items.length % 2 === 1 && i === items.length - 1 ? "sm:col-span-2" : ""
26
+ ].join(" "),
27
+ children: [
28
+ /* @__PURE__ */ jsx("dt", { className: "text-[12px] text-ink-muted", children: item.label }),
29
+ /* @__PURE__ */ jsx("dd", { className: "min-h-6 flex items-center text-[14px] font-medium text-ink tracking-[-0.01em] tabular-nums", children: item.value })
30
+ ]
31
+ },
32
+ i
33
+ ))
34
+ }
35
+ )
36
+ }
37
+ );
38
+ }
39
+ export {
40
+ DataList
41
+ };
42
+ //# sourceMappingURL=DataList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../components/ui/DataList.tsx"],"sourcesContent":["import React from \"react\";\n\ninterface DataListItem {\n label: string;\n value: React.ReactNode;\n}\n\ninterface DataListProps {\n items: DataListItem[];\n columns?: 1 | 2;\n className?: string;\n}\n\nexport function DataList({ items, columns = 1, className = \"\" }: DataListProps) {\n return (\n <div\n className={[\"rounded-[18px] p-1.5\", className].filter(Boolean).join(\" \")}\n style={{ background: \"var(--panel-bezel)\", boxShadow: \"var(--panel-shadow)\" }}\n >\n <dl\n className={[\n // 1px gaps over a hairline-coloured face draw the grid lines, so\n // borders never double up whatever the item count\n \"grid gap-px bg-ink/[0.05] rounded-[13px] overflow-hidden\",\n columns === 2 ? \"grid-cols-1 sm:grid-cols-2\" : \"grid-cols-1\",\n ].join(\" \")}\n style={{ boxShadow: \"var(--panel-face-shadow)\" }}\n >\n {items.map((item, i) => (\n <div\n key={i}\n className={[\n \"flex flex-col gap-1.5 px-5 py-4 bg-panel-face\",\n // An odd last cell in two columns spans the row instead of leaving a hole\n columns === 2 && items.length % 2 === 1 && i === items.length - 1 ? \"sm:col-span-2\" : \"\",\n ].join(\" \")}\n >\n <dt className=\"text-[12px] text-ink-muted\">\n {item.label}\n </dt>\n <dd className=\"min-h-6 flex items-center text-[14px] font-medium text-ink tracking-[-0.01em] tabular-nums\">\n {item.value}\n </dd>\n </div>\n ))}\n </dl>\n </div>\n );\n}\n"],"mappings":";AA6BU,SAQE,KARF;AAhBH,SAAS,SAAS,EAAE,OAAO,UAAU,GAAG,YAAY,GAAG,GAAkB;AAC9E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,CAAC,wBAAwB,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,MACvE,OAAO,EAAE,YAAY,sBAAsB,WAAW,sBAAsB;AAAA,MAE5E;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA;AAAA;AAAA,YAGT;AAAA,YACA,YAAY,IAAI,+BAA+B;AAAA,UACjD,EAAE,KAAK,GAAG;AAAA,UACV,OAAO,EAAE,WAAW,2BAA2B;AAAA,UAE9C,gBAAM,IAAI,CAAC,MAAM,MAChB;AAAA,YAAC;AAAA;AAAA,cAEC,WAAW;AAAA,gBACT;AAAA;AAAA,gBAEA,YAAY,KAAK,MAAM,SAAS,MAAM,KAAK,MAAM,MAAM,SAAS,IAAI,kBAAkB;AAAA,cACxF,EAAE,KAAK,GAAG;AAAA,cAEV;AAAA,oCAAC,QAAG,WAAU,8BACX,eAAK,OACR;AAAA,gBACA,oBAAC,QAAG,WAAU,8FACX,eAAK,OACR;AAAA;AAAA;AAAA,YAZK;AAAA,UAaP,CACD;AAAA;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -0,0 +1,65 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ declare const startOfDay: (d: Date) => Date;
4
+ declare const sameDay: (a?: Date | null, b?: Date | null) => boolean;
5
+ declare const toISODate: (d: Date) => string;
6
+ interface DateRange {
7
+ from: Date | null;
8
+ to: Date | null;
9
+ }
10
+ interface CalendarProps {
11
+ value?: Date | null;
12
+ /** Shade a span of days instead of marking one (see DateRangePicker) */
13
+ range?: DateRange;
14
+ onChange?: (date: Date) => void;
15
+ /** The day under the pointer or keyboard, for previewing a range */
16
+ onDayHover?: (date: Date | null) => void;
17
+ /** The month shown first; defaults to the selected date, or today */
18
+ defaultMonth?: Date;
19
+ /** How many months sit side by side */
20
+ months?: 1 | 2;
21
+ min?: Date;
22
+ max?: Date;
23
+ /** Grey out and skip particular days, like weekends */
24
+ isDateDisabled?: (date: Date) => boolean;
25
+ /** 0 is Sunday, 1 is Monday */
26
+ weekStartsOn?: 0 | 1;
27
+ locale?: string;
28
+ /** Move focus onto the grid as soon as it mounts */
29
+ autoFocus?: boolean;
30
+ className?: string;
31
+ }
32
+ declare function Calendar({ value, range, onChange, onDayHover, defaultMonth, months, min, max, isDateDisabled, weekStartsOn, locale, autoFocus, className, }: CalendarProps): react_jsx_runtime.JSX.Element;
33
+ declare const CalendarIcon: ({ className }: {
34
+ className?: string;
35
+ }) => react_jsx_runtime.JSX.Element;
36
+ declare function ClearKey({ label, onClear }: {
37
+ label: string;
38
+ onClear: () => void;
39
+ }): react_jsx_runtime.JSX.Element;
40
+ interface DatePickerProps {
41
+ value?: Date | null;
42
+ defaultValue?: Date | null;
43
+ onChange?: (date: Date | null) => void;
44
+ label?: string;
45
+ hint?: string;
46
+ error?: string;
47
+ placeholder?: string;
48
+ min?: Date;
49
+ max?: Date;
50
+ isDateDisabled?: (date: Date) => boolean;
51
+ weekStartsOn?: 0 | 1;
52
+ locale?: string;
53
+ /** How the chosen date reads in the field */
54
+ format?: Intl.DateTimeFormatOptions;
55
+ /** Submit the date with a form, as yyyy-mm-dd */
56
+ name?: string;
57
+ /** Show a small key in the field that empties it */
58
+ clearable?: boolean;
59
+ disabled?: boolean;
60
+ fullWidth?: boolean;
61
+ className?: string;
62
+ }
63
+ declare function DatePicker({ value, defaultValue, onChange, label, hint, error, placeholder, min, max, isDateDisabled, weekStartsOn, locale, format, name, clearable, disabled, fullWidth, className, }: DatePickerProps): react_jsx_runtime.JSX.Element;
64
+
65
+ export { Calendar, CalendarIcon, ClearKey, DatePicker, type DateRange, sameDay, startOfDay, toISODate };