@craftzbay/ui 0.10.0 → 0.11.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 (187) hide show
  1. package/README.md +18 -12
  2. package/dist-lib/__tests__/helpers/color.d.ts +9 -0
  3. package/dist-lib/__tests__/helpers/theme.d.ts +18 -0
  4. package/dist-lib/components/ui/Accordion.js +18 -7
  5. package/dist-lib/components/ui/Accordion.js.map +1 -1
  6. package/dist-lib/components/ui/Alert.d.ts +16 -0
  7. package/dist-lib/components/ui/Alert.js +47 -34
  8. package/dist-lib/components/ui/Alert.js.map +1 -1
  9. package/dist-lib/components/ui/Avatar.d.ts +1 -1
  10. package/dist-lib/components/ui/Avatar.js +45 -47
  11. package/dist-lib/components/ui/Avatar.js.map +1 -1
  12. package/dist-lib/components/ui/Badge.d.ts +3 -1
  13. package/dist-lib/components/ui/Badge.js +24 -15
  14. package/dist-lib/components/ui/Badge.js.map +1 -1
  15. package/dist-lib/components/ui/Breadcrumbs.d.ts +2 -0
  16. package/dist-lib/components/ui/Breadcrumbs.js +46 -28
  17. package/dist-lib/components/ui/Breadcrumbs.js.map +1 -1
  18. package/dist-lib/components/ui/Button.d.ts +5 -3
  19. package/dist-lib/components/ui/Button.js +59 -45
  20. package/dist-lib/components/ui/Button.js.map +1 -1
  21. package/dist-lib/components/ui/Calendar.d.ts +1 -1
  22. package/dist-lib/components/ui/Calendar.js +87 -59
  23. package/dist-lib/components/ui/Calendar.js.map +1 -1
  24. package/dist-lib/components/ui/Card.d.ts +2 -0
  25. package/dist-lib/components/ui/Card.js +48 -67
  26. package/dist-lib/components/ui/Card.js.map +1 -1
  27. package/dist-lib/components/ui/Carousel.d.ts +6 -6
  28. package/dist-lib/components/ui/Carousel.js +133 -102
  29. package/dist-lib/components/ui/Carousel.js.map +1 -1
  30. package/dist-lib/components/ui/Chart.d.ts +49 -10
  31. package/dist-lib/components/ui/Chart.js +415 -181
  32. package/dist-lib/components/ui/Chart.js.map +1 -1
  33. package/dist-lib/components/ui/Checkbox.js +42 -28
  34. package/dist-lib/components/ui/Checkbox.js.map +1 -1
  35. package/dist-lib/components/ui/Combobox.d.ts +2 -0
  36. package/dist-lib/components/ui/Combobox.js +142 -111
  37. package/dist-lib/components/ui/Combobox.js.map +1 -1
  38. package/dist-lib/components/ui/CommandPalette.d.ts +6 -3
  39. package/dist-lib/components/ui/CommandPalette.js +92 -87
  40. package/dist-lib/components/ui/CommandPalette.js.map +1 -1
  41. package/dist-lib/components/ui/ContextMenu.d.ts +7 -2
  42. package/dist-lib/components/ui/ContextMenu.js +77 -62
  43. package/dist-lib/components/ui/ContextMenu.js.map +1 -1
  44. package/dist-lib/components/ui/DataGrid.d.ts +17 -4
  45. package/dist-lib/components/ui/DataGrid.js +65 -50
  46. package/dist-lib/components/ui/DataGrid.js.map +1 -1
  47. package/dist-lib/components/ui/DatePicker.js +118 -99
  48. package/dist-lib/components/ui/DatePicker.js.map +1 -1
  49. package/dist-lib/components/ui/DesignSystemProvider.d.ts +94 -40
  50. package/dist-lib/components/ui/DesignSystemProvider.js +111 -55
  51. package/dist-lib/components/ui/DesignSystemProvider.js.map +1 -1
  52. package/dist-lib/components/ui/Dialog.d.ts +18 -3
  53. package/dist-lib/components/ui/Dialog.js +105 -80
  54. package/dist-lib/components/ui/Dialog.js.map +1 -1
  55. package/dist-lib/components/ui/Drawer.d.ts +17 -2
  56. package/dist-lib/components/ui/Drawer.js +89 -55
  57. package/dist-lib/components/ui/Drawer.js.map +1 -1
  58. package/dist-lib/components/ui/DropdownMenu.js +14 -9
  59. package/dist-lib/components/ui/DropdownMenu.js.map +1 -1
  60. package/dist-lib/components/ui/EmptyState.d.ts +2 -0
  61. package/dist-lib/components/ui/EmptyState.js +30 -16
  62. package/dist-lib/components/ui/EmptyState.js.map +1 -1
  63. package/dist-lib/components/ui/ErrorState.d.ts +13 -2
  64. package/dist-lib/components/ui/ErrorState.js +44 -23
  65. package/dist-lib/components/ui/ErrorState.js.map +1 -1
  66. package/dist-lib/components/ui/FileUpload.js +59 -56
  67. package/dist-lib/components/ui/FileUpload.js.map +1 -1
  68. package/dist-lib/components/ui/Form.d.ts +15 -2
  69. package/dist-lib/components/ui/Form.js +97 -71
  70. package/dist-lib/components/ui/Form.js.map +1 -1
  71. package/dist-lib/components/ui/Icon.d.ts +1 -1
  72. package/dist-lib/components/ui/Icon.js +20 -14
  73. package/dist-lib/components/ui/Icon.js.map +1 -1
  74. package/dist-lib/components/ui/IconButton.d.ts +2 -2
  75. package/dist-lib/components/ui/IconButton.js +28 -20
  76. package/dist-lib/components/ui/IconButton.js.map +1 -1
  77. package/dist-lib/components/ui/Input.d.ts +3 -1
  78. package/dist-lib/components/ui/Input.js +102 -79
  79. package/dist-lib/components/ui/Input.js.map +1 -1
  80. package/dist-lib/components/ui/Kbd.js +1 -1
  81. package/dist-lib/components/ui/Kbd.js.map +1 -1
  82. package/dist-lib/components/ui/MultiSelect.js +121 -107
  83. package/dist-lib/components/ui/MultiSelect.js.map +1 -1
  84. package/dist-lib/components/ui/Pagination.js +67 -62
  85. package/dist-lib/components/ui/Pagination.js.map +1 -1
  86. package/dist-lib/components/ui/Popover.js +14 -14
  87. package/dist-lib/components/ui/Popover.js.map +1 -1
  88. package/dist-lib/components/ui/Progress.d.ts +3 -3
  89. package/dist-lib/components/ui/Progress.js +77 -72
  90. package/dist-lib/components/ui/Progress.js.map +1 -1
  91. package/dist-lib/components/ui/RadioGroup.d.ts +1 -1
  92. package/dist-lib/components/ui/RadioGroup.js +69 -52
  93. package/dist-lib/components/ui/RadioGroup.js.map +1 -1
  94. package/dist-lib/components/ui/RelativeTime.d.ts +19 -0
  95. package/dist-lib/components/ui/RelativeTime.js +31 -0
  96. package/dist-lib/components/ui/RelativeTime.js.map +1 -0
  97. package/dist-lib/components/ui/ScrollArea.d.ts +9 -1
  98. package/dist-lib/components/ui/ScrollArea.js +43 -27
  99. package/dist-lib/components/ui/ScrollArea.js.map +1 -1
  100. package/dist-lib/components/ui/Select.d.ts +6 -1
  101. package/dist-lib/components/ui/Select.js +79 -71
  102. package/dist-lib/components/ui/Select.js.map +1 -1
  103. package/dist-lib/components/ui/Separator.js +1 -1
  104. package/dist-lib/components/ui/Separator.js.map +1 -1
  105. package/dist-lib/components/ui/Sheet.d.ts +9 -0
  106. package/dist-lib/components/ui/Sheet.js +69 -46
  107. package/dist-lib/components/ui/Sheet.js.map +1 -1
  108. package/dist-lib/components/ui/Sidebar.d.ts +12 -9
  109. package/dist-lib/components/ui/Sidebar.js +152 -109
  110. package/dist-lib/components/ui/Sidebar.js.map +1 -1
  111. package/dist-lib/components/ui/Skeleton.d.ts +13 -2
  112. package/dist-lib/components/ui/Skeleton.js +15 -14
  113. package/dist-lib/components/ui/Skeleton.js.map +1 -1
  114. package/dist-lib/components/ui/Slider.js +41 -29
  115. package/dist-lib/components/ui/Slider.js.map +1 -1
  116. package/dist-lib/components/ui/Snackbar.js +23 -22
  117. package/dist-lib/components/ui/Snackbar.js.map +1 -1
  118. package/dist-lib/components/ui/Spinner.js +18 -6
  119. package/dist-lib/components/ui/Spinner.js.map +1 -1
  120. package/dist-lib/components/ui/Stepper.d.ts +6 -0
  121. package/dist-lib/components/ui/Stepper.js +71 -48
  122. package/dist-lib/components/ui/Stepper.js.map +1 -1
  123. package/dist-lib/components/ui/Switch.js +46 -43
  124. package/dist-lib/components/ui/Switch.js.map +1 -1
  125. package/dist-lib/components/ui/Table.d.ts +33 -5
  126. package/dist-lib/components/ui/Table.js +141 -119
  127. package/dist-lib/components/ui/Table.js.map +1 -1
  128. package/dist-lib/components/ui/Tabs.js +50 -48
  129. package/dist-lib/components/ui/Tabs.js.map +1 -1
  130. package/dist-lib/components/ui/TagInput.js +45 -45
  131. package/dist-lib/components/ui/TagInput.js.map +1 -1
  132. package/dist-lib/components/ui/Textarea.js +65 -54
  133. package/dist-lib/components/ui/Textarea.js.map +1 -1
  134. package/dist-lib/components/ui/Timeline.js +39 -35
  135. package/dist-lib/components/ui/Timeline.js.map +1 -1
  136. package/dist-lib/components/ui/Toast.js +44 -57
  137. package/dist-lib/components/ui/Toast.js.map +1 -1
  138. package/dist-lib/components/ui/Tooltip.d.ts +4 -1
  139. package/dist-lib/components/ui/Tooltip.js +24 -22
  140. package/dist-lib/components/ui/Tooltip.js.map +1 -1
  141. package/dist-lib/components/ui/TopNav.d.ts +7 -3
  142. package/dist-lib/components/ui/TopNav.js +39 -22
  143. package/dist-lib/components/ui/TopNav.js.map +1 -1
  144. package/dist-lib/components/ui/Tree.d.ts +15 -10
  145. package/dist-lib/components/ui/Tree.js +82 -79
  146. package/dist-lib/components/ui/Tree.js.map +1 -1
  147. package/dist-lib/hooks/use-debounce.d.ts +19 -0
  148. package/dist-lib/hooks/use-debounce.js +36 -0
  149. package/dist-lib/hooks/use-debounce.js.map +1 -0
  150. package/dist-lib/hooks/use-delayed-loading.d.ts +21 -0
  151. package/dist-lib/hooks/use-delayed-loading.js +20 -0
  152. package/dist-lib/hooks/use-delayed-loading.js.map +1 -0
  153. package/dist-lib/hooks/use-field-ids.d.ts +2 -1
  154. package/dist-lib/hooks/use-field-ids.js +9 -9
  155. package/dist-lib/hooks/use-field-ids.js.map +1 -1
  156. package/dist-lib/hooks/use-media-query.d.ts +3 -1
  157. package/dist-lib/hooks/use-media-query.js +16 -12
  158. package/dist-lib/hooks/use-media-query.js.map +1 -1
  159. package/dist-lib/hooks/use-modifier-key.d.ts +13 -0
  160. package/dist-lib/hooks/use-modifier-key.js +19 -0
  161. package/dist-lib/hooks/use-modifier-key.js.map +1 -0
  162. package/dist-lib/hooks/use-toast.d.ts +7 -2
  163. package/dist-lib/hooks/use-toast.js +61 -30
  164. package/dist-lib/hooks/use-toast.js.map +1 -1
  165. package/dist-lib/icons/index.d.ts +9 -0
  166. package/dist-lib/icons/index.js +148 -130
  167. package/dist-lib/icons/index.js.map +1 -1
  168. package/dist-lib/illustrations/index.d.ts +1 -0
  169. package/dist-lib/illustrations/index.js +15 -6
  170. package/dist-lib/illustrations/index.js.map +1 -1
  171. package/dist-lib/index.d.ts +6 -0
  172. package/dist-lib/index.js +280 -260
  173. package/dist-lib/index.js.map +1 -1
  174. package/dist-lib/lib/format.d.ts +65 -0
  175. package/dist-lib/lib/format.js +95 -0
  176. package/dist-lib/lib/format.js.map +1 -0
  177. package/dist-lib/lib/return-focus.d.ts +11 -0
  178. package/dist-lib/lib/return-focus.js +12 -0
  179. package/dist-lib/lib/return-focus.js.map +1 -0
  180. package/dist-lib/lib/strings.d.ts +62 -1
  181. package/dist-lib/lib/strings.js +75 -19
  182. package/dist-lib/lib/strings.js.map +1 -1
  183. package/dist-lib/lib/strings.mn.js +50 -5
  184. package/dist-lib/lib/strings.mn.js.map +1 -1
  185. package/dist-lib/styles.css +1 -1
  186. package/dist-lib/theme.css +141 -78
  187. package/package.json +11 -4
@@ -14,11 +14,16 @@ const R = o.Root, k = o.Trigger, T = o.Group, g = o.Portal, j = o.Sub, G = o.Rad
14
14
  o.SubTrigger,
15
15
  {
16
16
  ref: u,
17
- className: d(p, "data-[state=open]:bg-background-muted", t && "pl-8", e),
17
+ className: d(
18
+ p,
19
+ "data-[state=open]:bg-background-muted",
20
+ t && "pl-8",
21
+ e
22
+ ),
18
23
  ...a,
19
24
  children: [
20
25
  n,
21
- /* @__PURE__ */ r(f, { className: "ml-auto size-4 text-foreground-subtle", "aria-hidden": !0 })
26
+ /* @__PURE__ */ r(f, { className: "text-foreground-subtle ml-auto size-4", "aria-hidden": !0 })
22
27
  ]
23
28
  }
24
29
  );
@@ -30,7 +35,7 @@ const w = i(function({ className: e, ...t }, n) {
30
35
  {
31
36
  ref: n,
32
37
  className: d(
33
- "z-[var(--z-popover)] min-w-[8rem] overflow-hidden rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md",
38
+ "border-border bg-popover text-popover-foreground z-[var(--z-popover)] min-w-[8rem] overflow-hidden rounded-lg border p-1 shadow-md",
34
39
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
35
40
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
36
41
  "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
@@ -49,7 +54,7 @@ const h = i(function({ className: e, sideOffset: t = 4, align: n = "end", ...a }
49
54
  sideOffset: t,
50
55
  align: n,
51
56
  className: d(
52
- "z-[var(--z-popover)] min-w-[12rem] overflow-hidden rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md",
57
+ "border-border bg-popover text-popover-foreground z-[var(--z-popover)] min-w-[12rem] overflow-hidden rounded-lg border p-1 shadow-md",
53
58
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
54
59
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
55
60
  "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
@@ -86,7 +91,7 @@ const M = i(function({ className: e, children: t, checked: n, ...a }, u) {
86
91
  className: d(p, "pl-8", e),
87
92
  ...a,
88
93
  children: [
89
- /* @__PURE__ */ r("span", { className: "absolute left-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ r(o.ItemIndicator, { children: /* @__PURE__ */ r(l, { className: "size-4 text-accent", "aria-hidden": !0 }) }) }),
94
+ /* @__PURE__ */ r("span", { className: "absolute left-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ r(o.ItemIndicator, { children: /* @__PURE__ */ r(l, { className: "text-accent size-4", "aria-hidden": !0 }) }) }),
90
95
  t
91
96
  ]
92
97
  }
@@ -101,7 +106,7 @@ const x = i(function({ className: e, children: t, ...n }, a) {
101
106
  className: d(p, "pl-8", e),
102
107
  ...n,
103
108
  children: [
104
- /* @__PURE__ */ r("span", { className: "absolute left-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ r(o.ItemIndicator, { children: /* @__PURE__ */ r(m, { className: "size-2 fill-accent text-accent", "aria-hidden": !0 }) }) }),
109
+ /* @__PURE__ */ r("span", { className: "absolute left-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ r(o.ItemIndicator, { children: /* @__PURE__ */ r(m, { className: "fill-accent text-accent size-2", "aria-hidden": !0 }) }) }),
105
110
  t
106
111
  ]
107
112
  }
@@ -114,7 +119,7 @@ const N = i(function({ className: e, inset: t, ...n }, a) {
114
119
  {
115
120
  ref: a,
116
121
  className: d(
117
- "px-2 py-1.5 text-xs font-medium text-foreground-subtle",
122
+ "text-foreground-subtle px-2 py-1.5 text-xs font-medium",
118
123
  t && "pl-8",
119
124
  e
120
125
  ),
@@ -128,7 +133,7 @@ const C = i(function({ className: e, ...t }, n) {
128
133
  o.Separator,
129
134
  {
130
135
  ref: n,
131
- className: d("-mx-1 my-1 h-px bg-border", e),
136
+ className: d("bg-border -mx-1 my-1 h-px", e),
132
137
  ...t
133
138
  }
134
139
  );
@@ -138,7 +143,7 @@ function I({ className: s, ...e }) {
138
143
  return /* @__PURE__ */ r(
139
144
  "span",
140
145
  {
141
- className: d("ml-auto text-xs tracking-widest text-foreground-subtle font-mono", s),
146
+ className: d("text-foreground-subtle ml-auto font-mono text-xs tracking-widest", s),
142
147
  ...e
143
148
  }
144
149
  );
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.js","sources":["../../../src/components/ui/DropdownMenu.tsx"],"sourcesContent":["'use client';\n\nimport {\n forwardRef,\n type ComponentPropsWithoutRef,\n type ElementRef,\n type HTMLAttributes,\n} from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { Check, ChevronRight, Circle } from '@/icons';\nimport { cn } from '@/lib/utils';\n\n/* -----------------------------------------------------------------------------\n * Full dropdown menu surface with submenu support, separators, checkbox /\n * radio items, and keyboard shortcut labels (Kbd).\n * --------------------------------------------------------------------------- */\n\nexport const DropdownMenu = DropdownMenuPrimitive.Root;\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\nexport const DropdownMenuGroup = DropdownMenuPrimitive.Group;\nexport const DropdownMenuPortal = DropdownMenuPrimitive.Portal;\nexport const DropdownMenuSub = DropdownMenuPrimitive.Sub;\nexport const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nconst itemClasses = cn(\n 'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-foreground outline-none',\n 'data-[highlighted]:bg-background-muted data-[highlighted]:text-foreground',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n 'transition-colors duration-[var(--duration-fast)]',\n);\n\nexport const DropdownMenuSubTrigger = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(function DropdownMenuSubTrigger({ className, inset, children, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(itemClasses, 'data-[state=open]:bg-background-muted', inset && 'pl-8', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4 text-foreground-subtle\" aria-hidden />\n </DropdownMenuPrimitive.SubTrigger>\n );\n});\nDropdownMenuSubTrigger.displayName = 'DropdownMenuSubTrigger';\n\nexport const DropdownMenuSubContent = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(function DropdownMenuSubContent({ className, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n 'z-[var(--z-popover)] min-w-[8rem] overflow-hidden rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n className,\n )}\n {...props}\n />\n );\n});\nDropdownMenuSubContent.displayName = 'DropdownMenuSubContent';\n\nexport const DropdownMenuContent = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Content>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(function DropdownMenuContent({ className, sideOffset = 4, align = 'end', ...props }, ref) {\n return (\n <DropdownMenuPortal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n align={align}\n className={cn(\n 'z-[var(--z-popover)] min-w-[12rem] overflow-hidden rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-1 data-[side=top]:slide-in-from-bottom-1',\n className,\n )}\n {...props}\n />\n </DropdownMenuPortal>\n );\n});\nDropdownMenuContent.displayName = 'DropdownMenuContent';\n\nexport const DropdownMenuItem = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Item>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n destructive?: boolean;\n }\n>(function DropdownMenuItem({ className, inset, destructive, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n itemClasses,\n inset && 'pl-8',\n destructive &&\n 'text-danger-text data-[highlighted]:bg-danger-soft data-[highlighted]:text-danger-text',\n className,\n )}\n {...props}\n />\n );\n});\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nexport const DropdownMenuCheckboxItem = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(function DropdownMenuCheckboxItem({ className, children, checked, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n checked={checked}\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"absolute left-2 flex size-4 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Check className=\"size-4 text-accent\" aria-hidden />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n});\nDropdownMenuCheckboxItem.displayName = 'DropdownMenuCheckboxItem';\n\nexport const DropdownMenuRadioItem = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(function DropdownMenuRadioItem({ className, children, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"absolute left-2 flex size-4 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Circle className=\"size-2 fill-accent text-accent\" aria-hidden />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n});\nDropdownMenuRadioItem.displayName = 'DropdownMenuRadioItem';\n\nexport const DropdownMenuLabel = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Label>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(function DropdownMenuLabel({ className, inset, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\n 'px-2 py-1.5 text-xs font-medium text-foreground-subtle',\n inset && 'pl-8',\n className,\n )}\n {...props}\n />\n );\n});\nDropdownMenuLabel.displayName = 'DropdownMenuLabel';\n\nexport const DropdownMenuSeparator = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Separator>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(function DropdownMenuSeparator({ className, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n});\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\n/**\n * Trailing right-aligned shortcut label inside a menu item. Pair with `<Kbd>`\n * inside the Kbd component file if you want stylised keys.\n */\nexport function DropdownMenuShortcut({ className, ...props }: HTMLAttributes<HTMLSpanElement>) {\n return (\n <span\n className={cn('ml-auto text-xs tracking-widest text-foreground-subtle font-mono', className)}\n {...props}\n />\n );\n}\nDropdownMenuShortcut.displayName = 'DropdownMenuShortcut';\n\n/**\n * @example\n * <DropdownMenu>\n * <DropdownMenuTrigger asChild><IconButton aria-label=\"More\" icon={<MoreHorizontal />} /></DropdownMenuTrigger>\n * <DropdownMenuContent>\n * <DropdownMenuItem>Open<DropdownMenuShortcut>⌘O</DropdownMenuShortcut></DropdownMenuItem>\n * <DropdownMenuItem>Rename</DropdownMenuItem>\n * <DropdownMenuSeparator />\n * <DropdownMenuItem destructive>Delete</DropdownMenuItem>\n * </DropdownMenuContent>\n * </DropdownMenu>\n *\n * @do Group destructive items at the bottom with a separator.\n * @dont Mix link navigation and action items in the same menu — split into\n * two menus or two groups with labels.\n */\n"],"names":["DropdownMenu","DropdownMenuPrimitive","DropdownMenuTrigger","DropdownMenuGroup","DropdownMenuPortal","DropdownMenuSub","DropdownMenuRadioGroup","itemClasses","cn","DropdownMenuSubTrigger","forwardRef","className","inset","children","props","ref","jsxs","jsx","ChevronRight","DropdownMenuSubContent","DropdownMenuContent","sideOffset","align","DropdownMenuItem","destructive","DropdownMenuCheckboxItem","checked","Check","DropdownMenuRadioItem","Circle","DropdownMenuLabel","DropdownMenuSeparator","DropdownMenuShortcut"],"mappings":"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"}
1
+ {"version":3,"file":"DropdownMenu.js","sources":["../../../src/components/ui/DropdownMenu.tsx"],"sourcesContent":["'use client';\n\nimport {\n forwardRef,\n type ComponentPropsWithoutRef,\n type ElementRef,\n type HTMLAttributes,\n} from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { Check, ChevronRight, Circle } from '@/icons';\nimport { cn } from '@/lib/utils';\n\n/* -----------------------------------------------------------------------------\n * Full dropdown menu surface with submenu support, separators, checkbox /\n * radio items, and keyboard shortcut labels (Kbd).\n * --------------------------------------------------------------------------- */\n\nexport const DropdownMenu = DropdownMenuPrimitive.Root;\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\nexport const DropdownMenuGroup = DropdownMenuPrimitive.Group;\nexport const DropdownMenuPortal = DropdownMenuPrimitive.Portal;\nexport const DropdownMenuSub = DropdownMenuPrimitive.Sub;\nexport const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nconst itemClasses = cn(\n 'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-foreground outline-none',\n 'data-[highlighted]:bg-background-muted data-[highlighted]:text-foreground',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n 'transition-colors duration-[var(--duration-fast)]',\n);\n\nexport const DropdownMenuSubTrigger = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(function DropdownMenuSubTrigger({ className, inset, children, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n itemClasses,\n 'data-[state=open]:bg-background-muted',\n inset && 'pl-8',\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRight className=\"text-foreground-subtle ml-auto size-4\" aria-hidden />\n </DropdownMenuPrimitive.SubTrigger>\n );\n});\nDropdownMenuSubTrigger.displayName = 'DropdownMenuSubTrigger';\n\nexport const DropdownMenuSubContent = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(function DropdownMenuSubContent({ className, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n 'border-border bg-popover text-popover-foreground z-[var(--z-popover)] min-w-[8rem] overflow-hidden rounded-lg border p-1 shadow-md',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n className,\n )}\n {...props}\n />\n );\n});\nDropdownMenuSubContent.displayName = 'DropdownMenuSubContent';\n\nexport const DropdownMenuContent = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Content>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n // `align` defaults to 'end' (Radix default is 'center'): triggers are\n // usually right-aligned icon buttons in toolbars/table rows. Pass\n // `align=\"start\"` for left-anchored triggers.\n>(function DropdownMenuContent({ className, sideOffset = 4, align = 'end', ...props }, ref) {\n return (\n <DropdownMenuPortal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n align={align}\n className={cn(\n 'border-border bg-popover text-popover-foreground z-[var(--z-popover)] min-w-[12rem] overflow-hidden rounded-lg border p-1 shadow-md',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-1 data-[side=top]:slide-in-from-bottom-1',\n className,\n )}\n {...props}\n />\n </DropdownMenuPortal>\n );\n});\nDropdownMenuContent.displayName = 'DropdownMenuContent';\n\nexport const DropdownMenuItem = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Item>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n destructive?: boolean;\n }\n>(function DropdownMenuItem({ className, inset, destructive, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n itemClasses,\n inset && 'pl-8',\n destructive &&\n 'text-danger-text data-[highlighted]:bg-danger-soft data-[highlighted]:text-danger-text',\n className,\n )}\n {...props}\n />\n );\n});\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nexport const DropdownMenuCheckboxItem = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(function DropdownMenuCheckboxItem({ className, children, checked, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n checked={checked}\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"absolute left-2 flex size-4 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Check className=\"text-accent size-4\" aria-hidden />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n});\nDropdownMenuCheckboxItem.displayName = 'DropdownMenuCheckboxItem';\n\nexport const DropdownMenuRadioItem = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(function DropdownMenuRadioItem({ className, children, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"absolute left-2 flex size-4 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Circle className=\"fill-accent text-accent size-2\" aria-hidden />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n});\nDropdownMenuRadioItem.displayName = 'DropdownMenuRadioItem';\n\nexport const DropdownMenuLabel = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Label>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(function DropdownMenuLabel({ className, inset, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\n 'text-foreground-subtle px-2 py-1.5 text-xs font-medium',\n inset && 'pl-8',\n className,\n )}\n {...props}\n />\n );\n});\nDropdownMenuLabel.displayName = 'DropdownMenuLabel';\n\nexport const DropdownMenuSeparator = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Separator>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(function DropdownMenuSeparator({ className, ...props }, ref) {\n return (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('bg-border -mx-1 my-1 h-px', className)}\n {...props}\n />\n );\n});\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\n/**\n * Trailing right-aligned shortcut label inside a menu item. Pair with `<Kbd>`\n * inside the Kbd component file if you want stylised keys.\n */\nexport function DropdownMenuShortcut({ className, ...props }: HTMLAttributes<HTMLSpanElement>) {\n return (\n <span\n className={cn('text-foreground-subtle ml-auto font-mono text-xs tracking-widest', className)}\n {...props}\n />\n );\n}\nDropdownMenuShortcut.displayName = 'DropdownMenuShortcut';\n\n/**\n * @example\n * <DropdownMenu>\n * <DropdownMenuTrigger asChild><IconButton aria-label=\"More\" icon={<MoreHorizontal />} /></DropdownMenuTrigger>\n * <DropdownMenuContent>\n * <DropdownMenuItem>Open<DropdownMenuShortcut>⌘O</DropdownMenuShortcut></DropdownMenuItem>\n * <DropdownMenuItem>Rename</DropdownMenuItem>\n * <DropdownMenuSeparator />\n * <DropdownMenuItem destructive>Delete</DropdownMenuItem>\n * </DropdownMenuContent>\n * </DropdownMenu>\n *\n * @do Group destructive items at the bottom with a separator.\n * @dont Mix link navigation and action items in the same menu — split into\n * two menus or two groups with labels.\n */\n"],"names":["DropdownMenu","DropdownMenuPrimitive","DropdownMenuTrigger","DropdownMenuGroup","DropdownMenuPortal","DropdownMenuSub","DropdownMenuRadioGroup","itemClasses","cn","DropdownMenuSubTrigger","forwardRef","className","inset","children","props","ref","jsxs","jsx","ChevronRight","DropdownMenuSubContent","DropdownMenuContent","sideOffset","align","DropdownMenuItem","destructive","DropdownMenuCheckboxItem","checked","Check","DropdownMenuRadioItem","Circle","DropdownMenuLabel","DropdownMenuSeparator","DropdownMenuShortcut"],"mappings":"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"}
@@ -19,6 +19,8 @@ export interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 't
19
19
  action?: ReactNode;
20
20
  /** Secondary helper link — "Learn more", "Import existing", etc. */
21
21
  secondaryAction?: ReactNode;
22
+ /** Heading level of the title. Default 3 — match the surrounding outline. */
23
+ headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;
22
24
  }
23
25
  /**
24
26
  * Shown when a list / dataset / surface has no content yet. Tone is helpful,
@@ -1,32 +1,46 @@
1
1
  "use client";
2
2
  import { jsxs as a, jsx as e } from "react/jsx-runtime";
3
- import { forwardRef as c } from "react";
4
- import { cn as f } from "../../lib/utils.js";
5
- import { InboxEmpty as u } from "../../illustrations/index.js";
6
- const x = c(function({ icon: t, illustration: r, title: l, description: d, action: m, secondaryAction: s, className: n, ...o }, i) {
3
+ import { forwardRef as f, createElement as u } from "react";
4
+ import { cn as x } from "../../lib/utils.js";
5
+ import { InboxEmpty as g } from "../../illustrations/index.js";
6
+ const p = f(function({
7
+ icon: t,
8
+ illustration: r,
9
+ title: l,
10
+ description: m,
11
+ action: d,
12
+ secondaryAction: s,
13
+ headingLevel: n = 3,
14
+ className: o,
15
+ ...i
16
+ }, c) {
7
17
  return /* @__PURE__ */ a(
8
18
  "div",
9
19
  {
10
- ref: i,
11
- className: f(
12
- "flex flex-col items-center justify-center gap-3 rounded-lg border border-dashed border-border bg-background-subtle p-10 text-center",
13
- n
20
+ ref: c,
21
+ className: x(
22
+ "border-border bg-background-subtle flex flex-col items-center justify-center gap-3 rounded-lg border border-dashed p-10 text-center",
23
+ o
14
24
  ),
15
- ...o,
25
+ ...i,
16
26
  children: [
17
- r || (t ? /* @__PURE__ */ e("div", { className: "inline-flex size-12 items-center justify-center rounded-full bg-background-muted text-foreground-muted [&_svg]:size-6", children: t }) : /* @__PURE__ */ e(u, { className: "size-24" })),
18
- /* @__PURE__ */ e("h3", { className: "text-base font-semibold text-foreground leading-tight", children: l }),
19
- d && /* @__PURE__ */ e("p", { className: "max-w-md text-sm text-foreground-muted leading-relaxed", children: d }),
20
- (m || s) && /* @__PURE__ */ a("div", { className: "mt-2 flex items-center gap-2", children: [
21
- m,
27
+ r || (t ? /* @__PURE__ */ e("div", { className: "bg-background-muted text-foreground-muted inline-flex size-12 items-center justify-center rounded-full [&_svg]:size-6", children: t }) : /* @__PURE__ */ e(g, { className: "size-24" })),
28
+ u(
29
+ `h${n}`,
30
+ { className: "text-base font-semibold text-foreground leading-tight" },
31
+ l
32
+ ),
33
+ m && /* @__PURE__ */ e("p", { className: "text-foreground-muted max-w-md text-sm leading-relaxed", children: m }),
34
+ (d || s) && /* @__PURE__ */ a("div", { className: "mt-2 flex items-center gap-2", children: [
35
+ d,
22
36
  s
23
37
  ] })
24
38
  ]
25
39
  }
26
40
  );
27
41
  });
28
- x.displayName = "EmptyState";
42
+ p.displayName = "EmptyState";
29
43
  export {
30
- x as EmptyState
44
+ p as EmptyState
31
45
  };
32
46
  //# sourceMappingURL=EmptyState.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState.js","sources":["../../../src/components/ui/EmptyState.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\nimport { InboxEmpty } from '@/illustrations';\n\nexport interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /**\n * Small Lucide-sized icon rendered inside a 48px circular container.\n * Use for compact empty states (table cells, sidebar panes, cards).\n */\n icon?: ReactNode;\n /**\n * Full-size illustration rendered without the icon container. Takes\n * precedence over `icon`. If neither is set, the default `InboxEmpty`\n * line illustration is used.\n */\n illustration?: ReactNode;\n /** Heading. One short sentence. */\n title: ReactNode;\n /** Description. One or two sentences max. */\n description?: ReactNode;\n /** Primary action — usually a `<Button>` that creates the missing item. */\n action?: ReactNode;\n /** Secondary helper link — \"Learn more\", \"Import existing\", etc. */\n secondaryAction?: ReactNode;\n}\n\n/**\n * Shown when a list / dataset / surface has no content yet. Tone is helpful,\n * never apologetic.\n *\n * @example Default — uses the built-in InboxEmpty illustration\n * <EmptyState\n * title=\"No projects yet\"\n * description=\"Create a project to start tracking work.\"\n * action={<Button>New project</Button>}\n * />\n *\n * @example Compact — small Lucide icon for dense layouts\n * <EmptyState\n * icon={<Folder className=\"size-6\" />}\n * title=\"No items\"\n * />\n *\n * @example Custom illustration\n * <EmptyState\n * illustration={<Illustrations.NoSearchResults className=\"size-32\" />}\n * title=\"No results\"\n * />\n */\nexport const EmptyState = forwardRef<HTMLDivElement, EmptyStateProps>(function EmptyState(\n { icon, illustration, title, description, action, secondaryAction, className, ...props },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col items-center justify-center gap-3 rounded-lg border border-dashed border-border bg-background-subtle p-10 text-center',\n className,\n )}\n {...props}\n >\n {/* Visual: illustration > icon > default illustration */}\n {illustration ? (\n illustration\n ) : icon ? (\n <div className=\"inline-flex size-12 items-center justify-center rounded-full bg-background-muted text-foreground-muted [&_svg]:size-6\">\n {icon}\n </div>\n ) : (\n <InboxEmpty className=\"size-24\" />\n )}\n <h3 className=\"text-base font-semibold text-foreground leading-tight\">{title}</h3>\n {description && (\n <p className=\"max-w-md text-sm text-foreground-muted leading-relaxed\">{description}</p>\n )}\n {(action || secondaryAction) && (\n <div className=\"mt-2 flex items-center gap-2\">\n {action}\n {secondaryAction}\n </div>\n )}\n </div>\n );\n});\nEmptyState.displayName = 'EmptyState';\n"],"names":["EmptyState","forwardRef","icon","illustration","title","description","action","secondaryAction","className","props","ref","jsxs","cn","jsx","InboxEmpty"],"mappings":";;;;;AAmDO,MAAMA,IAAaC,EAA4C,SACpE,EAAE,MAAAC,GAAM,cAAAC,GAAc,OAAAC,GAAO,aAAAC,GAAa,QAAAC,GAAQ,iBAAAC,GAAiB,WAAAC,GAAW,GAAGC,EAAA,GACjFC,GACA;AACA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAWE;AAAA,QACT;AAAA,QACAJ;AAAA,MAAA;AAAA,MAED,GAAGC;AAAA,MAGH,UAAA;AAAA,QAAAN,MAEGD,IACF,gBAAAW,EAAC,OAAA,EAAI,WAAU,yHACZ,UAAAX,EAAA,CACH,IAEA,gBAAAW,EAACC,GAAA,EAAW,WAAU,WAAU;AAAA,QAElC,gBAAAD,EAAC,MAAA,EAAG,WAAU,yDAAyD,UAAAT,GAAM;AAAA,QAC5EC,KACC,gBAAAQ,EAAC,KAAA,EAAE,WAAU,0DAA0D,UAAAR,GAAY;AAAA,SAEnFC,KAAUC,MACV,gBAAAI,EAAC,OAAA,EAAI,WAAU,gCACZ,UAAA;AAAA,UAAAL;AAAA,UACAC;AAAA,QAAA,EAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR,CAAC;AACDP,EAAW,cAAc;"}
1
+ {"version":3,"file":"EmptyState.js","sources":["../../../src/components/ui/EmptyState.tsx"],"sourcesContent":["'use client';\n\nimport { createElement, forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\nimport { InboxEmpty } from '@/illustrations';\n\nexport interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /**\n * Small Lucide-sized icon rendered inside a 48px circular container.\n * Use for compact empty states (table cells, sidebar panes, cards).\n */\n icon?: ReactNode;\n /**\n * Full-size illustration rendered without the icon container. Takes\n * precedence over `icon`. If neither is set, the default `InboxEmpty`\n * line illustration is used.\n */\n illustration?: ReactNode;\n /** Heading. One short sentence. */\n title: ReactNode;\n /** Description. One or two sentences max. */\n description?: ReactNode;\n /** Primary action — usually a `<Button>` that creates the missing item. */\n action?: ReactNode;\n /** Secondary helper link — \"Learn more\", \"Import existing\", etc. */\n secondaryAction?: ReactNode;\n /** Heading level of the title. Default 3 — match the surrounding outline. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n}\n\n/**\n * Shown when a list / dataset / surface has no content yet. Tone is helpful,\n * never apologetic.\n *\n * @example Default — uses the built-in InboxEmpty illustration\n * <EmptyState\n * title=\"No projects yet\"\n * description=\"Create a project to start tracking work.\"\n * action={<Button>New project</Button>}\n * />\n *\n * @example Compact — small Lucide icon for dense layouts\n * <EmptyState\n * icon={<Folder className=\"size-6\" />}\n * title=\"No items\"\n * />\n *\n * @example Custom illustration\n * <EmptyState\n * illustration={<Illustrations.NoSearchResults className=\"size-32\" />}\n * title=\"No results\"\n * />\n */\nexport const EmptyState = forwardRef<HTMLDivElement, EmptyStateProps>(function EmptyState(\n {\n icon,\n illustration,\n title,\n description,\n action,\n secondaryAction,\n headingLevel = 3,\n className,\n ...props\n },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn(\n 'border-border bg-background-subtle flex flex-col items-center justify-center gap-3 rounded-lg border border-dashed p-10 text-center',\n className,\n )}\n {...props}\n >\n {/* Visual: illustration > icon > default illustration */}\n {illustration ? (\n illustration\n ) : icon ? (\n <div className=\"bg-background-muted text-foreground-muted inline-flex size-12 items-center justify-center rounded-full [&_svg]:size-6\">\n {icon}\n </div>\n ) : (\n <InboxEmpty className=\"size-24\" />\n )}\n {createElement(\n `h${headingLevel}`,\n { className: 'text-base font-semibold text-foreground leading-tight' },\n title,\n )}\n {description && (\n <p className=\"text-foreground-muted max-w-md text-sm leading-relaxed\">{description}</p>\n )}\n {(action || secondaryAction) && (\n <div className=\"mt-2 flex items-center gap-2\">\n {action}\n {secondaryAction}\n </div>\n )}\n </div>\n );\n});\nEmptyState.displayName = 'EmptyState';\n"],"names":["EmptyState","forwardRef","icon","illustration","title","description","action","secondaryAction","headingLevel","className","props","ref","jsxs","cn","jsx","InboxEmpty","createElement"],"mappings":";;;;;AAqDO,MAAMA,IAAaC,EAA4C,SACpE;AAAA,EACE,MAAAC;AAAA,EACA,cAAAC;AAAA,EACA,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,QAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,cAAAC,IAAe;AAAA,EACf,WAAAC;AAAA,EACA,GAAGC;AACL,GACAC,GACA;AACA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAWE;AAAA,QACT;AAAA,QACAJ;AAAA,MAAA;AAAA,MAED,GAAGC;AAAA,MAGH,UAAA;AAAA,QAAAP,MAEGD,IACF,gBAAAY,EAAC,OAAA,EAAI,WAAU,yHACZ,UAAAZ,EAAA,CACH,IAEA,gBAAAY,EAACC,GAAA,EAAW,WAAU,WAAU;AAAA,QAEjCC;AAAA,UACC,IAAIR,CAAY;AAAA,UAChB,EAAE,WAAW,wDAAA;AAAA,UACbJ;AAAA,QAAA;AAAA,QAEDC,KACC,gBAAAS,EAAC,KAAA,EAAE,WAAU,0DAA0D,UAAAT,GAAY;AAAA,SAEnFC,KAAUC,MACV,gBAAAK,EAAC,OAAA,EAAI,WAAU,gCACZ,UAAA;AAAA,UAAAN;AAAA,UACAC;AAAA,QAAA,EAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR,CAAC;AACDP,EAAW,cAAc;"}
@@ -1,7 +1,7 @@
1
1
  import { HTMLAttributes, ReactNode } from 'react';
2
2
  export interface ErrorStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
3
- /** `404` not-found, `500` server, or `generic` (catch-all). */
4
- variant?: '404' | '500' | 'generic';
3
+ /** `403` permission-denied, `404` not-found, `500` server, or `generic` (catch-all). */
4
+ variant?: '403' | '404' | '500' | 'generic';
5
5
  /** Override the default title. */
6
6
  title?: ReactNode;
7
7
  /** Override the default description. */
@@ -15,6 +15,14 @@ export interface ErrorStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 't
15
15
  action?: ReactNode;
16
16
  /** When provided, renders a default "Try again" button calling this handler. */
17
17
  onRetry?: () => void;
18
+ /** Heading level of the title. Default 3 — match the surrounding outline. */
19
+ headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;
20
+ /**
21
+ * Announce the error politely when it appears in-place (e.g. a failed
22
+ * refetch inside a panel). Off by default — page-level errors are read as
23
+ * part of the page and must not double-announce.
24
+ */
25
+ live?: boolean;
18
26
  }
19
27
  /**
20
28
  * Page-level error placeholder. Pair with `onRetry` for transient failures.
@@ -25,6 +33,9 @@ export interface ErrorStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 't
25
33
  * @example 500 with retry
26
34
  * <ErrorState variant="500" onRetry={refetch} />
27
35
  *
36
+ * @example 403 with a way out (no retry — permission won't change on reload)
37
+ * <ErrorState variant="403" action={<Button variant="outline" asChild><a href="/">Go home</a></Button>} />
38
+ *
28
39
  * @example Custom
29
40
  * <ErrorState
30
41
  * title="Quota exceeded"
@@ -1,48 +1,69 @@
1
1
  "use client";
2
- import { jsxs as u, jsx as r } from "react/jsx-runtime";
3
- import { forwardRef as g } from "react";
4
- import { cn as f } from "../../lib/utils.js";
5
- import { useStrings as x } from "../../hooks/use-strings.js";
6
- import { ConnectionLost as S, ServerError as N, NotFound as b } from "../../illustrations/index.js";
7
- import { Button as h } from "./Button.js";
8
- const v = (e) => ({
2
+ import { jsxs as g, jsx as r } from "react/jsx-runtime";
3
+ import { forwardRef as S, createElement as x } from "react";
4
+ import { cn as b } from "../../lib/utils.js";
5
+ import { useStrings as N } from "../../hooks/use-strings.js";
6
+ import { ConnectionLost as v, ServerError as h, NotFound as E, Locked as z } from "../../illustrations/index.js";
7
+ import { Button as D } from "./Button.js";
8
+ const T = (e) => ({
9
+ 403: {
10
+ illustration: /* @__PURE__ */ r(z, { className: "size-32" }),
11
+ title: e.errorState.forbiddenTitle,
12
+ description: e.errorState.forbiddenDescription
13
+ },
9
14
  404: {
10
- illustration: /* @__PURE__ */ r(b, { className: "size-32" }),
15
+ illustration: /* @__PURE__ */ r(E, { className: "size-32" }),
11
16
  title: e.errorState.notFoundTitle,
12
17
  description: e.errorState.notFoundDescription
13
18
  },
14
19
  500: {
15
- illustration: /* @__PURE__ */ r(N, { className: "size-32" }),
20
+ illustration: /* @__PURE__ */ r(h, { className: "size-32" }),
16
21
  title: e.errorState.serverTitle,
17
22
  description: e.errorState.serverDescription
18
23
  },
19
24
  generic: {
20
- illustration: /* @__PURE__ */ r(S, { className: "size-32" }),
25
+ illustration: /* @__PURE__ */ r(v, { className: "size-32" }),
21
26
  title: e.errorState.genericTitle,
22
27
  description: e.errorState.genericDescription
23
28
  }
24
- }), E = g(function({ variant: s = "generic", title: a, description: l, illustration: c, action: i, onRetry: o, className: d, ...m }, p) {
25
- const n = x(), t = v(n)[s];
26
- return /* @__PURE__ */ u(
29
+ }), j = S(function({
30
+ variant: s = "generic",
31
+ title: a,
32
+ description: l,
33
+ illustration: c,
34
+ action: i,
35
+ onRetry: o,
36
+ headingLevel: d = 3,
37
+ live: m,
38
+ className: p,
39
+ ...u
40
+ }, f) {
41
+ const n = N(), t = T(n)[s];
42
+ return /* @__PURE__ */ g(
27
43
  "div",
28
44
  {
29
- ref: p,
30
- className: f(
31
- "flex flex-col items-center justify-center gap-3 rounded-lg border border-border bg-background-subtle p-10 text-center",
32
- d
45
+ ref: f,
46
+ className: b(
47
+ "border-border bg-background-subtle flex flex-col items-center justify-center gap-3 rounded-lg border p-10 text-center",
48
+ p
33
49
  ),
34
- ...m,
50
+ "aria-live": m ? "polite" : void 0,
51
+ ...u,
35
52
  children: [
36
53
  c ?? t.illustration,
37
- /* @__PURE__ */ r("h3", { className: "text-base font-semibold text-foreground leading-tight", children: a ?? t.title }),
38
- /* @__PURE__ */ r("p", { className: "max-w-md text-sm text-foreground-muted leading-relaxed", children: l ?? t.description }),
39
- (i || o) && /* @__PURE__ */ r("div", { className: "mt-2 flex items-center gap-2", children: i ?? /* @__PURE__ */ r(h, { onClick: o, variant: "outline", children: n.errorState.tryAgain }) })
54
+ x(
55
+ `h${d}`,
56
+ { className: "text-base font-semibold text-foreground leading-tight" },
57
+ a ?? t.title
58
+ ),
59
+ /* @__PURE__ */ r("p", { className: "text-foreground-muted max-w-md text-sm leading-relaxed", children: l ?? t.description }),
60
+ (i || o) && /* @__PURE__ */ r("div", { className: "mt-2 flex items-center gap-2", children: i ?? /* @__PURE__ */ r(D, { onClick: o, variant: "outline", children: n.errorState.tryAgain }) })
40
61
  ]
41
62
  }
42
63
  );
43
64
  });
44
- E.displayName = "ErrorState";
65
+ j.displayName = "ErrorState";
45
66
  export {
46
- E as ErrorState
67
+ j as ErrorState
47
68
  };
48
69
  //# sourceMappingURL=ErrorState.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorState.js","sources":["../../../src/components/ui/ErrorState.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\nimport type { UiStrings } from '@/lib/strings';\nimport { NotFound, ServerError, ConnectionLost } from '@/illustrations';\nimport { Button } from './Button';\n\nexport interface ErrorStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** `404` not-found, `500` server, or `generic` (catch-all). */\n variant?: '404' | '500' | 'generic';\n /** Override the default title. */\n title?: ReactNode;\n /** Override the default description. */\n description?: ReactNode;\n /**\n * Override the variant's default illustration. Pass any ReactNode (e.g.\n * `<Illustrations.Construction className=\"size-32\" />`).\n */\n illustration?: ReactNode;\n /** Custom action node. Replaces the default retry button. */\n action?: ReactNode;\n /** When provided, renders a default \"Try again\" button calling this handler. */\n onRetry?: () => void;\n}\n\nconst presets = (s: UiStrings) => ({\n '404': {\n illustration: <NotFound className=\"size-32\" />,\n title: s.errorState.notFoundTitle,\n description: s.errorState.notFoundDescription,\n },\n '500': {\n illustration: <ServerError className=\"size-32\" />,\n title: s.errorState.serverTitle,\n description: s.errorState.serverDescription,\n },\n generic: {\n illustration: <ConnectionLost className=\"size-32\" />,\n title: s.errorState.genericTitle,\n description: s.errorState.genericDescription,\n },\n});\n\n/**\n * Page-level error placeholder. Pair with `onRetry` for transient failures.\n *\n * @example 404 (uses built-in line illustration)\n * <ErrorState variant=\"404\" />\n *\n * @example 500 with retry\n * <ErrorState variant=\"500\" onRetry={refetch} />\n *\n * @example Custom\n * <ErrorState\n * title=\"Quota exceeded\"\n * description=\"Your plan allows 1,000 events/day.\"\n * illustration={<Illustrations.Construction className=\"size-32\" />}\n * action={<Button>Upgrade plan</Button>}\n * />\n *\n * @do Match the tone to the cause — server errors apologise, user errors\n * explain. Always offer a next step.\n * @dont Show a raw stack trace to end users.\n */\nexport const ErrorState = forwardRef<HTMLDivElement, ErrorStateProps>(function ErrorState(\n { variant = 'generic', title, description, illustration, action, onRetry, className, ...props },\n ref,\n) {\n const strings = useStrings();\n const preset = presets(strings)[variant];\n return (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col items-center justify-center gap-3 rounded-lg border border-border bg-background-subtle p-10 text-center',\n className,\n )}\n {...props}\n >\n {illustration ?? preset.illustration}\n <h3 className=\"text-base font-semibold text-foreground leading-tight\">\n {title ?? preset.title}\n </h3>\n <p className=\"max-w-md text-sm text-foreground-muted leading-relaxed\">\n {description ?? preset.description}\n </p>\n {(action || onRetry) && (\n <div className=\"mt-2 flex items-center gap-2\">\n {action ?? (\n <Button onClick={onRetry} variant=\"outline\">\n {strings.errorState.tryAgain}\n </Button>\n )}\n </div>\n )}\n </div>\n );\n});\nErrorState.displayName = 'ErrorState';\n"],"names":["presets","s","jsx","NotFound","ServerError","ConnectionLost","ErrorState","forwardRef","variant","title","description","illustration","action","onRetry","className","props","ref","strings","useStrings","preset","jsxs","cn","Button"],"mappings":";;;;;;;AA2BA,MAAMA,IAAU,CAACC,OAAkB;AAAA,EACjC,KAAO;AAAA,IACL,cAAc,gBAAAC,EAACC,GAAA,EAAS,WAAU,UAAA,CAAU;AAAA,IAC5C,OAAOF,EAAE,WAAW;AAAA,IACpB,aAAaA,EAAE,WAAW;AAAA,EAAA;AAAA,EAE5B,KAAO;AAAA,IACL,cAAc,gBAAAC,EAACE,GAAA,EAAY,WAAU,UAAA,CAAU;AAAA,IAC/C,OAAOH,EAAE,WAAW;AAAA,IACpB,aAAaA,EAAE,WAAW;AAAA,EAAA;AAAA,EAE5B,SAAS;AAAA,IACP,cAAc,gBAAAC,EAACG,GAAA,EAAe,WAAU,UAAA,CAAU;AAAA,IAClD,OAAOJ,EAAE,WAAW;AAAA,IACpB,aAAaA,EAAE,WAAW;AAAA,EAAA;AAE9B,IAuBaK,IAAaC,EAA4C,SACpE,EAAE,SAAAC,IAAU,WAAW,OAAAC,GAAO,aAAAC,GAAa,cAAAC,GAAc,QAAAC,GAAQ,SAAAC,GAAS,WAAAC,GAAW,GAAGC,EAAA,GACxFC,GACA;AACA,QAAMC,IAAUC,EAAA,GACVC,IAASnB,EAAQiB,CAAO,EAAET,CAAO;AACvC,SACE,gBAAAY;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAJ;AAAA,MACA,WAAWK;AAAA,QACT;AAAA,QACAP;AAAA,MAAA;AAAA,MAED,GAAGC;AAAA,MAEH,UAAA;AAAA,QAAAJ,KAAgBQ,EAAO;AAAA,0BACvB,MAAA,EAAG,WAAU,yDACX,UAAAV,KAASU,EAAO,OACnB;AAAA,0BACC,KAAA,EAAE,WAAU,0DACV,UAAAT,KAAeS,EAAO,aACzB;AAAA,SACEP,KAAUC,MACV,gBAAAX,EAAC,OAAA,EAAI,WAAU,gCACZ,UAAAU,KACC,gBAAAV,EAACoB,GAAA,EAAO,SAAST,GAAS,SAAQ,WAC/B,UAAAI,EAAQ,WAAW,UACtB,EAAA,CAEJ;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR,CAAC;AACDX,EAAW,cAAc;"}
1
+ {"version":3,"file":"ErrorState.js","sources":["../../../src/components/ui/ErrorState.tsx"],"sourcesContent":["'use client';\n\nimport { createElement, forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\nimport type { UiStrings } from '@/lib/strings';\nimport { NotFound, ServerError, ConnectionLost, Locked } from '@/illustrations';\nimport { Button } from './Button';\n\nexport interface ErrorStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** `403` permission-denied, `404` not-found, `500` server, or `generic` (catch-all). */\n variant?: '403' | '404' | '500' | 'generic';\n /** Override the default title. */\n title?: ReactNode;\n /** Override the default description. */\n description?: ReactNode;\n /**\n * Override the variant's default illustration. Pass any ReactNode (e.g.\n * `<Illustrations.Construction className=\"size-32\" />`).\n */\n illustration?: ReactNode;\n /** Custom action node. Replaces the default retry button. */\n action?: ReactNode;\n /** When provided, renders a default \"Try again\" button calling this handler. */\n onRetry?: () => void;\n /** Heading level of the title. Default 3 — match the surrounding outline. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n /**\n * Announce the error politely when it appears in-place (e.g. a failed\n * refetch inside a panel). Off by default — page-level errors are read as\n * part of the page and must not double-announce.\n */\n live?: boolean;\n}\n\nconst presets = (s: UiStrings) => ({\n '403': {\n illustration: <Locked className=\"size-32\" />,\n title: s.errorState.forbiddenTitle,\n description: s.errorState.forbiddenDescription,\n },\n '404': {\n illustration: <NotFound className=\"size-32\" />,\n title: s.errorState.notFoundTitle,\n description: s.errorState.notFoundDescription,\n },\n '500': {\n illustration: <ServerError className=\"size-32\" />,\n title: s.errorState.serverTitle,\n description: s.errorState.serverDescription,\n },\n generic: {\n illustration: <ConnectionLost className=\"size-32\" />,\n title: s.errorState.genericTitle,\n description: s.errorState.genericDescription,\n },\n});\n\n/**\n * Page-level error placeholder. Pair with `onRetry` for transient failures.\n *\n * @example 404 (uses built-in line illustration)\n * <ErrorState variant=\"404\" />\n *\n * @example 500 with retry\n * <ErrorState variant=\"500\" onRetry={refetch} />\n *\n * @example 403 with a way out (no retry — permission won't change on reload)\n * <ErrorState variant=\"403\" action={<Button variant=\"outline\" asChild><a href=\"/\">Go home</a></Button>} />\n *\n * @example Custom\n * <ErrorState\n * title=\"Quota exceeded\"\n * description=\"Your plan allows 1,000 events/day.\"\n * illustration={<Illustrations.Construction className=\"size-32\" />}\n * action={<Button>Upgrade plan</Button>}\n * />\n *\n * @do Match the tone to the cause — server errors apologise, user errors\n * explain. Always offer a next step.\n * @dont Show a raw stack trace to end users.\n */\nexport const ErrorState = forwardRef<HTMLDivElement, ErrorStateProps>(function ErrorState(\n {\n variant = 'generic',\n title,\n description,\n illustration,\n action,\n onRetry,\n headingLevel = 3,\n live,\n className,\n ...props\n },\n ref,\n) {\n const strings = useStrings();\n const preset = presets(strings)[variant];\n return (\n <div\n ref={ref}\n className={cn(\n 'border-border bg-background-subtle flex flex-col items-center justify-center gap-3 rounded-lg border p-10 text-center',\n className,\n )}\n aria-live={live ? 'polite' : undefined}\n {...props}\n >\n {illustration ?? preset.illustration}\n {createElement(\n `h${headingLevel}`,\n { className: 'text-base font-semibold text-foreground leading-tight' },\n title ?? preset.title,\n )}\n <p className=\"text-foreground-muted max-w-md text-sm leading-relaxed\">\n {description ?? preset.description}\n </p>\n {(action || onRetry) && (\n <div className=\"mt-2 flex items-center gap-2\">\n {action ?? (\n <Button onClick={onRetry} variant=\"outline\">\n {strings.errorState.tryAgain}\n </Button>\n )}\n </div>\n )}\n </div>\n );\n});\nErrorState.displayName = 'ErrorState';\n"],"names":["presets","s","jsx","Locked","NotFound","ServerError","ConnectionLost","ErrorState","forwardRef","variant","title","description","illustration","action","onRetry","headingLevel","live","className","props","ref","strings","useStrings","preset","jsxs","cn","createElement","Button"],"mappings":";;;;;;;AAmCA,MAAMA,IAAU,CAACC,OAAkB;AAAA,EACjC,KAAO;AAAA,IACL,cAAc,gBAAAC,EAACC,GAAA,EAAO,WAAU,UAAA,CAAU;AAAA,IAC1C,OAAOF,EAAE,WAAW;AAAA,IACpB,aAAaA,EAAE,WAAW;AAAA,EAAA;AAAA,EAE5B,KAAO;AAAA,IACL,cAAc,gBAAAC,EAACE,GAAA,EAAS,WAAU,UAAA,CAAU;AAAA,IAC5C,OAAOH,EAAE,WAAW;AAAA,IACpB,aAAaA,EAAE,WAAW;AAAA,EAAA;AAAA,EAE5B,KAAO;AAAA,IACL,cAAc,gBAAAC,EAACG,GAAA,EAAY,WAAU,UAAA,CAAU;AAAA,IAC/C,OAAOJ,EAAE,WAAW;AAAA,IACpB,aAAaA,EAAE,WAAW;AAAA,EAAA;AAAA,EAE5B,SAAS;AAAA,IACP,cAAc,gBAAAC,EAACI,GAAA,EAAe,WAAU,UAAA,CAAU;AAAA,IAClD,OAAOL,EAAE,WAAW;AAAA,IACpB,aAAaA,EAAE,WAAW;AAAA,EAAA;AAE9B,IA0BaM,IAAaC,EAA4C,SACpE;AAAA,EACE,SAAAC,IAAU;AAAA,EACV,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,cAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,cAAAC,IAAe;AAAA,EACf,MAAAC;AAAA,EACA,WAAAC;AAAA,EACA,GAAGC;AACL,GACAC,GACA;AACA,QAAMC,IAAUC,EAAA,GACVC,IAAStB,EAAQoB,CAAO,EAAEX,CAAO;AACvC,SACE,gBAAAc;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAJ;AAAA,MACA,WAAWK;AAAA,QACT;AAAA,QACAP;AAAA,MAAA;AAAA,MAEF,aAAWD,IAAO,WAAW;AAAA,MAC5B,GAAGE;AAAA,MAEH,UAAA;AAAA,QAAAN,KAAgBU,EAAO;AAAA,QACvBG;AAAA,UACC,IAAIV,CAAY;AAAA,UAChB,EAAE,WAAW,wDAAA;AAAA,UACbL,KAASY,EAAO;AAAA,QAAA;AAAA,0BAEjB,KAAA,EAAE,WAAU,0DACV,UAAAX,KAAeW,EAAO,aACzB;AAAA,SACET,KAAUC,MACV,gBAAAZ,EAAC,OAAA,EAAI,WAAU,gCACZ,UAAAW,KACC,gBAAAX,EAACwB,GAAA,EAAO,SAASZ,GAAS,SAAQ,WAC/B,UAAAM,EAAQ,WAAW,UACtB,EAAA,CAEJ;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR,CAAC;AACDb,EAAW,cAAc;"}
@@ -1,108 +1,111 @@
1
1
  "use client";
2
- import { jsxs as m, jsx as t } from "react/jsx-runtime";
3
- import { forwardRef as A, useRef as O, useId as S, useState as y, useCallback as F } from "react";
4
- import { Upload as T, File as C, X as K } from "../../icons/index.js";
5
- import { cn as k } from "../../lib/utils.js";
6
- import { useStrings as M } from "../../hooks/use-strings.js";
7
- import { formatString as X } from "../../lib/strings.js";
8
- function _(s) {
9
- return s < 1024 ? `${s} B` : s < 1024 * 1024 ? `${(s / 1024).toFixed(1)} KB` : `${(s / 1024 / 1024).toFixed(1)} MB`;
2
+ import { jsxs as p, jsx as n } from "react/jsx-runtime";
3
+ import { forwardRef as T, useRef as F, useId as B, useState as D, useCallback as U } from "react";
4
+ import { Upload as C, File as E, X } from "../../icons/index.js";
5
+ import { cn as z } from "../../lib/utils.js";
6
+ import { useStrings as _ } from "../../hooks/use-strings.js";
7
+ import { formatString as h } from "../../lib/strings.js";
8
+ function q(s, t) {
9
+ return s < 1024 ? h(t.bytes, { n: s }) : s < 1024 * 1024 ? h(t.kilobytes, { n: (s / 1024).toFixed(1) }) : h(t.megabytes, { n: (s / 1024 / 1024).toFixed(1) });
10
10
  }
11
- function q(s, i) {
12
- if (!i) return !0;
13
- const a = i.split(",").map((r) => r.trim().toLowerCase()).filter(Boolean);
11
+ function G(s, t) {
12
+ if (!t) return !0;
13
+ const a = t.split(",").map((r) => r.trim().toLowerCase()).filter(Boolean);
14
14
  if (!a.length) return !0;
15
15
  const d = s.name.toLowerCase(), l = s.type.toLowerCase();
16
16
  return a.some((r) => r.startsWith(".") ? d.endsWith(r) : r.endsWith("/*") ? l.startsWith(r.slice(0, -1)) : l === r);
17
17
  }
18
- const E = A(function({ accept: i, multiple: a, maxSize: d, value: l, onChange: r, onReject: n, hint: b, disabled: p, className: U }, z) {
19
- const v = M(), D = O(null), N = S(), [L, $] = y([]), [B, g] = y(!1), f = l ?? L, h = F(
18
+ const H = T(function({ accept: t, multiple: a, maxSize: d, value: l, onChange: r, onReject: i, hint: y, disabled: g, className: L }, W) {
19
+ const b = _(), $ = F(null), w = B(), [I, A] = D([]), [M, x] = D(!1), f = F(0), c = l ?? I, v = U(
20
20
  (e) => {
21
- l === void 0 && $(e), r == null || r(e);
21
+ l === void 0 && A(e), r == null || r(e);
22
22
  },
23
23
  [r, l]
24
- ), w = F(
24
+ ), k = U(
25
25
  (e) => {
26
- const o = [], c = [], x = [];
27
- for (const u of Array.from(e))
28
- q(u, i) ? d && u.size > d ? c.push(u) : o.push(u) : x.push(u);
29
- x.length && (n == null || n(x, "type")), c.length && (n == null || n(c, "size")), o.length && h(a ? [...f, ...o] : o.slice(0, 1));
26
+ const o = [], u = [], N = [];
27
+ for (const m of Array.from(e))
28
+ G(m, t) ? d && m.size > d ? u.push(m) : o.push(m) : N.push(m);
29
+ N.length && (i == null || i(N, "type")), u.length && (i == null || i(u, "size")), o.length && v(a ? [...c, ...o] : o.slice(0, 1));
30
30
  },
31
- [i, f, d, a, n, h]
32
- ), W = (e) => h(f.filter((o, c) => c !== e)), I = (e) => {
33
- e.preventDefault(), g(!1), !p && w(e.dataTransfer.files);
31
+ [t, c, d, a, i, v]
32
+ ), O = (e) => v(c.filter((o, u) => u !== e)), S = (e) => {
33
+ e.preventDefault(), f.current = 0, x(!1), !g && k(e.dataTransfer.files);
34
34
  };
35
- return /* @__PURE__ */ m("div", { ref: z, className: k("flex flex-col gap-3", U), children: [
36
- /* @__PURE__ */ m(
35
+ return /* @__PURE__ */ p("div", { ref: W, className: z("flex flex-col gap-3", L), children: [
36
+ /* @__PURE__ */ p(
37
37
  "label",
38
38
  {
39
- htmlFor: N,
40
- onDragOver: (e) => {
41
- e.preventDefault(), p || g(!0);
39
+ htmlFor: w,
40
+ onDragEnter: () => {
41
+ f.current += 1, g || x(!0);
42
42
  },
43
- onDragLeave: () => g(!1),
44
- onDrop: I,
45
- className: k(
43
+ onDragOver: (e) => e.preventDefault(),
44
+ onDragLeave: () => {
45
+ f.current = Math.max(0, f.current - 1), f.current === 0 && x(!1);
46
+ },
47
+ onDrop: S,
48
+ className: z(
46
49
  "group relative flex cursor-pointer flex-col items-center justify-center gap-2",
47
- "border-border bg-background-subtle rounded-md border border-dashed px-6 py-8",
50
+ "border-border-input bg-background-subtle rounded-md border border-dashed px-6 py-8",
48
51
  "text-center transition-colors",
49
52
  "hover:border-border-strong hover:bg-background-muted",
50
53
  "focus-within:ring-ring focus-within:ring-offset-background focus-within:ring-2 focus-within:ring-offset-2",
51
- B && "border-accent bg-accent-soft",
52
- p && "pointer-events-none opacity-50"
54
+ M && "border-accent bg-accent-soft",
55
+ g && "pointer-events-none opacity-50"
53
56
  ),
54
57
  children: [
55
- /* @__PURE__ */ t(T, { className: "text-foreground-muted size-5", "aria-hidden": !0 }),
56
- /* @__PURE__ */ m("div", { className: "space-y-1", children: [
57
- /* @__PURE__ */ t("p", { className: "text-sm font-medium", children: v.fileUpload.drop }),
58
- b && /* @__PURE__ */ t("p", { className: "text-foreground-muted text-xs", children: b })
58
+ /* @__PURE__ */ n(C, { className: "text-foreground-muted size-5", "aria-hidden": !0 }),
59
+ /* @__PURE__ */ p("div", { className: "space-y-1", children: [
60
+ /* @__PURE__ */ n("p", { className: "text-sm font-medium", children: b.fileUpload.drop }),
61
+ y && /* @__PURE__ */ n("p", { className: "text-foreground-muted text-xs", children: y })
59
62
  ] }),
60
- /* @__PURE__ */ t(
63
+ /* @__PURE__ */ n(
61
64
  "input",
62
65
  {
63
- ref: D,
64
- id: N,
66
+ ref: $,
67
+ id: w,
65
68
  type: "file",
66
- accept: i,
69
+ accept: t,
67
70
  multiple: a,
68
- disabled: p,
71
+ disabled: g,
69
72
  className: "sr-only",
70
73
  onChange: (e) => {
71
- e.target.files && w(e.target.files), e.target.value = "";
74
+ e.target.files && k(e.target.files), e.target.value = "";
72
75
  }
73
76
  }
74
77
  )
75
78
  ]
76
79
  }
77
80
  ),
78
- f.length > 0 && /* @__PURE__ */ t("ul", { className: "flex flex-col gap-2", children: f.map((e, o) => /* @__PURE__ */ m(
81
+ c.length > 0 && /* @__PURE__ */ n("ul", { className: "flex flex-col gap-2", children: c.map((e, o) => /* @__PURE__ */ p(
79
82
  "li",
80
83
  {
81
84
  className: "border-border bg-card flex items-center gap-3 rounded-md border px-3 py-2",
82
85
  children: [
83
- /* @__PURE__ */ t(C, { className: "text-foreground-muted size-4 shrink-0", "aria-hidden": !0 }),
84
- /* @__PURE__ */ m("div", { className: "min-w-0 flex-1", children: [
85
- /* @__PURE__ */ t("p", { className: "truncate text-sm", title: e.name, children: e.name }),
86
- /* @__PURE__ */ t("p", { className: "text-foreground-muted text-xs", children: _(e.size) })
86
+ /* @__PURE__ */ n(E, { className: "text-foreground-muted size-4 shrink-0", "aria-hidden": !0 }),
87
+ /* @__PURE__ */ p("div", { className: "min-w-0 flex-1", children: [
88
+ /* @__PURE__ */ n("p", { className: "truncate text-sm", title: e.name, children: e.name }),
89
+ /* @__PURE__ */ n("p", { className: "text-foreground-muted text-xs", children: q(e.size, b.fileUpload) })
87
90
  ] }),
88
- /* @__PURE__ */ t(
91
+ /* @__PURE__ */ n(
89
92
  "button",
90
93
  {
91
94
  type: "button",
92
- onClick: () => W(o),
93
- className: "text-foreground-muted hover:bg-background-muted hover:text-foreground focus-visible:ring-ring rounded-sm p-1 outline-none focus-visible:ring-2",
94
- "aria-label": X(v.fileUpload.remove, { name: e.name }),
95
- children: /* @__PURE__ */ t(K, { className: "size-4", "aria-hidden": !0 })
95
+ onClick: () => O(o),
96
+ className: "text-foreground-muted hover:bg-background-muted hover:text-foreground focus-visible:ring-ring focus-visible:ring-offset-background rounded-sm p-1 outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
97
+ "aria-label": h(b.fileUpload.remove, { name: e.name }),
98
+ children: /* @__PURE__ */ n(X, { className: "size-4", "aria-hidden": !0 })
96
99
  }
97
100
  )
98
101
  ]
99
102
  },
100
- `${e.name}-${o}`
103
+ `${e.name}-${e.size}-${e.lastModified}-${o}`
101
104
  )) })
102
105
  ] });
103
106
  });
104
- E.displayName = "FileUpload";
107
+ H.displayName = "FileUpload";
105
108
  export {
106
- E as FileUpload
109
+ H as FileUpload
107
110
  };
108
111
  //# sourceMappingURL=FileUpload.js.map