@vamos-ui/react 0.3.0 → 0.4.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 (274) hide show
  1. package/README.md +4 -0
  2. package/dist/blocks/block-heading.js +1 -1
  3. package/dist/blocks/block-image.js +1 -1
  4. package/dist/blocks/block-link.js +2 -2
  5. package/dist/blocks/index.d.ts +5 -5
  6. package/dist/blocks/index.js +5 -5
  7. package/dist/blocks/labels.d.ts +8 -0
  8. package/dist/blocks/labels.js +60 -0
  9. package/dist/blocks/section-header.js +1 -1
  10. package/dist/blocks/section.js +2 -2
  11. package/dist/blocks/site/_kit-1.js +1 -1
  12. package/dist/blocks/site/announcement-bar.js +1 -1
  13. package/dist/blocks/site/article-layout.d.ts +1 -0
  14. package/dist/blocks/site/article-layout.js +2 -1
  15. package/dist/blocks/site/blog-list.d.ts +1 -0
  16. package/dist/blocks/site/blog-list.js +3 -2
  17. package/dist/blocks/site/contact-dock.js +3 -1
  18. package/dist/blocks/site/contact-form.js +1 -1
  19. package/dist/blocks/site/cta.d.ts +2 -2
  20. package/dist/blocks/site/cta.js +6 -4
  21. package/dist/blocks/site/feature-grid.d.ts +1 -0
  22. package/dist/blocks/site/feature-grid.js +5 -4
  23. package/dist/blocks/site/feature-tabs.js +1 -1
  24. package/dist/blocks/site/footer.d.ts +11 -2
  25. package/dist/blocks/site/footer.js +36 -11
  26. package/dist/blocks/site/gallery-section.d.ts +6 -1
  27. package/dist/blocks/site/gallery-section.js +5 -4
  28. package/dist/blocks/site/hero.d.ts +3 -2
  29. package/dist/blocks/site/hero.js +7 -5
  30. package/dist/blocks/site/logo-strip.d.ts +1 -0
  31. package/dist/blocks/site/logo-strip.js +1 -1
  32. package/dist/blocks/site/map-hours.d.ts +2 -2
  33. package/dist/blocks/site/map-hours.js +4 -2
  34. package/dist/blocks/site/media-text.d.ts +4 -1
  35. package/dist/blocks/site/media-text.js +4 -3
  36. package/dist/blocks/site/menu-list.d.ts +7 -3
  37. package/dist/blocks/site/menu-list.js +34 -7
  38. package/dist/blocks/site/navbar.d.ts +1 -0
  39. package/dist/blocks/site/navbar.js +6 -5
  40. package/dist/blocks/site/not-found.js +2 -1
  41. package/dist/blocks/site/page-intro.d.ts +1 -0
  42. package/dist/blocks/site/page-intro.js +2 -1
  43. package/dist/blocks/site/process.d.ts +1 -0
  44. package/dist/blocks/site/process.js +2 -1
  45. package/dist/blocks/site/registry-1.d.ts +1 -1
  46. package/dist/blocks/site/registry-2.d.ts +5 -0
  47. package/dist/blocks/site/registry-2.js +5 -3
  48. package/dist/blocks/site/rich-text-section.js +2 -1
  49. package/dist/blocks/site/shared/heading-lines.d.ts +9 -0
  50. package/dist/blocks/site/shared/heading-lines.js +32 -0
  51. package/dist/blocks/site/shared/image-sizes.d.ts +25 -0
  52. package/dist/blocks/site/shared/image-sizes.js +37 -0
  53. package/dist/blocks/site/shared/island-keys.d.ts +1 -1
  54. package/dist/blocks/site/shared/island-keys.js +1 -1
  55. package/dist/blocks/site/shared/labels-2.d.ts +17 -1
  56. package/dist/blocks/site/shared/labels-2.js +832 -6
  57. package/dist/blocks/site/shared/open-now.d.ts +1 -1
  58. package/dist/blocks/site/shared/open-now.js +1 -1
  59. package/dist/blocks/site/shared/opening-hours.d.ts +18 -2
  60. package/dist/blocks/site/shared/opening-hours.js +36 -7
  61. package/dist/blocks/site/shared/tap.d.ts +9 -0
  62. package/dist/blocks/site/shared/tap.js +16 -0
  63. package/dist/blocks/site/site-shell.js +3 -3
  64. package/dist/blocks/site/team.d.ts +1 -1
  65. package/dist/blocks/site/team.js +4 -3
  66. package/dist/blocks/site/testimonials.d.ts +2 -2
  67. package/dist/blocks/site/testimonials.js +3 -3
  68. package/dist/business/approval-flow.js +2 -2
  69. package/dist/business/import-wizard.js +1 -1
  70. package/dist/business/line-items.js +1 -1
  71. package/dist/business/multi-step-form.js +2 -2
  72. package/dist/business/permission-matrix.js +1 -1
  73. package/dist/business/setup-checklist.js +2 -2
  74. package/dist/business/signer-status.js +1 -1
  75. package/dist/charts/bar-chart.js +1 -1
  76. package/dist/charts/bar-list.js +1 -1
  77. package/dist/charts/chart-shell.d.ts +9 -2
  78. package/dist/charts/chart-shell.js +11 -5
  79. package/dist/charts/chart.js +1 -1
  80. package/dist/charts/combo-chart.js +5 -7
  81. package/dist/charts/donut-chart.js +1 -1
  82. package/dist/charts/funnel.js +1 -1
  83. package/dist/charts/gauge.js +2 -2
  84. package/dist/charts/utils.d.ts +10 -0
  85. package/dist/charts/utils.js +46 -0
  86. package/dist/components/accordion.d.ts +1 -1
  87. package/dist/components/accordion.js +8 -8
  88. package/dist/components/activity-timeline.js +11 -11
  89. package/dist/components/address-field.js +3 -3
  90. package/dist/components/alert-dialog.d.ts +1 -1
  91. package/dist/components/alert-dialog.js +8 -8
  92. package/dist/components/alert.js +2 -2
  93. package/dist/components/app-shell.js +3 -3
  94. package/dist/components/aspect-ratio.d.ts +26 -0
  95. package/dist/components/aspect-ratio.js +42 -0
  96. package/dist/components/attachment-list.js +2 -2
  97. package/dist/components/audit-log.js +1 -1
  98. package/dist/components/avatar.d.ts +1 -1
  99. package/dist/components/avatar.js +8 -8
  100. package/dist/components/backup-codes.js +1 -1
  101. package/dist/components/badge.js +3 -3
  102. package/dist/components/breadcrumb.js +10 -9
  103. package/dist/components/button-group.js +4 -4
  104. package/dist/components/button.js +4 -4
  105. package/dist/components/calendar.js +5 -5
  106. package/dist/components/card.js +8 -8
  107. package/dist/components/carousel.d.ts +12 -3
  108. package/dist/components/carousel.js +17 -14
  109. package/dist/components/checkbox.d.ts +1 -1
  110. package/dist/components/checkbox.js +6 -6
  111. package/dist/components/collapsible.d.ts +36 -0
  112. package/dist/components/collapsible.js +37 -0
  113. package/dist/components/color-picker.js +3 -3
  114. package/dist/components/combobox.js +1 -1
  115. package/dist/components/command.js +9 -9
  116. package/dist/components/comment-thread.js +3 -3
  117. package/dist/components/context-menu.d.ts +1 -1
  118. package/dist/components/context-menu.js +9 -9
  119. package/dist/components/currency-input.js +1 -1
  120. package/dist/components/date-picker.js +2 -2
  121. package/dist/components/date-range-picker.js +1 -1
  122. package/dist/components/description-list.js +2 -2
  123. package/dist/components/dialog.d.ts +1 -1
  124. package/dist/components/dialog.js +9 -9
  125. package/dist/components/dropdown-menu.d.ts +1 -1
  126. package/dist/components/dropdown-menu.js +9 -9
  127. package/dist/components/editor-layout.js +9 -9
  128. package/dist/components/empty-state.js +2 -2
  129. package/dist/components/entity-card.js +1 -1
  130. package/dist/components/file-upload.js +5 -5
  131. package/dist/components/formatted-input.js +3 -3
  132. package/dist/components/hierarchy-chart.js +1 -1
  133. package/dist/components/hover-card.d.ts +1 -1
  134. package/dist/components/hover-card.js +3 -3
  135. package/dist/components/iban-input.js +1 -1
  136. package/dist/components/id-input.js +3 -3
  137. package/dist/components/image.d.ts +18 -2
  138. package/dist/components/image.js +16 -9
  139. package/dist/components/input-otp.js +6 -6
  140. package/dist/components/input.d.ts +1 -1
  141. package/dist/components/input.js +6 -6
  142. package/dist/components/item.js +4 -4
  143. package/dist/components/kbd.js +3 -3
  144. package/dist/components/list-layout.js +9 -9
  145. package/dist/components/menubar.d.ts +96 -0
  146. package/dist/components/menubar.js +123 -0
  147. package/dist/components/native-select.js +1 -1
  148. package/dist/components/navigation-menu.d.ts +1 -1
  149. package/dist/components/navigation-menu.js +12 -11
  150. package/dist/components/notification-center.js +4 -4
  151. package/dist/components/page-header.js +3 -3
  152. package/dist/components/pagination.js +9 -9
  153. package/dist/components/phone-input.js +1 -1
  154. package/dist/components/pin-map.js +1 -1
  155. package/dist/components/placeholder-art.d.ts +51 -0
  156. package/dist/components/placeholder-art.js +82 -0
  157. package/dist/components/popover.d.ts +1 -1
  158. package/dist/components/popover.js +7 -7
  159. package/dist/components/progress.js +3 -3
  160. package/dist/components/qr-code.js +1 -1
  161. package/dist/components/radio-group.d.ts +1 -1
  162. package/dist/components/radio-group.js +4 -4
  163. package/dist/components/record-detail-layout.js +10 -10
  164. package/dist/components/record-picker.js +2 -2
  165. package/dist/components/resizable.js +2 -2
  166. package/dist/components/scroll-area.d.ts +1 -1
  167. package/dist/components/scroll-area.js +4 -4
  168. package/dist/components/select.d.ts +1 -1
  169. package/dist/components/select.js +10 -10
  170. package/dist/components/separator.d.ts +1 -1
  171. package/dist/components/separator.js +3 -3
  172. package/dist/components/settings-layout.js +6 -6
  173. package/dist/components/sheet.js +3 -3
  174. package/dist/components/sidebar.js +12 -11
  175. package/dist/components/signature-pad.js +1 -1
  176. package/dist/components/skeleton.js +5 -5
  177. package/dist/components/sla-timer.js +2 -2
  178. package/dist/components/slider.d.ts +1 -1
  179. package/dist/components/slider.js +2 -2
  180. package/dist/components/slug-input.js +1 -1
  181. package/dist/components/sparkline.js +1 -1
  182. package/dist/components/spinner.js +2 -2
  183. package/dist/components/stat.js +5 -5
  184. package/dist/components/status-picker.js +2 -2
  185. package/dist/components/stepper.js +1 -1
  186. package/dist/components/switch.d.ts +1 -1
  187. package/dist/components/switch.js +3 -3
  188. package/dist/components/table.js +10 -10
  189. package/dist/components/tabs.d.ts +1 -1
  190. package/dist/components/tabs.js +11 -11
  191. package/dist/components/tag-input.js +1 -1
  192. package/dist/components/task-list.js +1 -1
  193. package/dist/components/time-picker.js +3 -3
  194. package/dist/components/toggle.d.ts +2 -1
  195. package/dist/components/toggle.js +7 -6
  196. package/dist/components/tooltip.d.ts +1 -1
  197. package/dist/components/tooltip.js +5 -4
  198. package/dist/components/top-bar.js +4 -4
  199. package/dist/components/tour.js +1 -1
  200. package/dist/components/tree-select.js +2 -2
  201. package/dist/components/tree-view.js +3 -3
  202. package/dist/components/typography.js +11 -11
  203. package/dist/components/user-picker.js +2 -2
  204. package/dist/components/version-history.js +3 -3
  205. package/dist/data-table/data-table.js +1 -1
  206. package/dist/data-table/filter-bar.js +2 -2
  207. package/dist/data-table/index.d.ts +15 -8
  208. package/dist/data-table/index.js +9 -8
  209. package/dist/data-table/saved-views.js +1 -1
  210. package/dist/editor/block-editor.js +1 -1
  211. package/dist/editor/context.js +1 -1
  212. package/dist/editor/menus.js +1 -1
  213. package/dist/fonts/font-picker.js +3 -3
  214. package/dist/fonts/pairing-picker.js +1 -1
  215. package/dist/fonts/provider.js +1 -1
  216. package/dist/index.d.ts +188 -90
  217. package/dist/index.js +94 -90
  218. package/dist/lib/data-islands.js +1 -1
  219. package/dist/lib/field-context.js +1 -1
  220. package/dist/lib/floating-arrow.js +1 -1
  221. package/dist/lib/islands.js +1 -1
  222. package/dist/lib/layer.js +3 -3
  223. package/dist/lib/locale.js +2 -2
  224. package/dist/lib/menu.js +2 -2
  225. package/dist/lib/provider.js +4 -4
  226. package/dist/lib/theme-scope.js +4 -3
  227. package/dist/lib/value-format.js +1 -1
  228. package/dist/lib/variants.js +2 -2
  229. package/dist/locales/ar.d.ts +2087 -0
  230. package/dist/locales/ar.js +2088 -0
  231. package/dist/locales/de.d.ts +2087 -0
  232. package/dist/locales/de.js +2088 -0
  233. package/dist/locales/en.d.ts +1 -0
  234. package/dist/locales/en.js +1 -0
  235. package/dist/locales/es.d.ts +2087 -0
  236. package/dist/locales/es.js +2087 -0
  237. package/dist/locales/fr.d.ts +2087 -0
  238. package/dist/locales/fr.js +2088 -0
  239. package/dist/locales/tr.d.ts +1 -0
  240. package/dist/locales/tr.js +1 -0
  241. package/dist/media/focal-point.js +1 -1
  242. package/dist/media/gallery.js +1 -1
  243. package/dist/media/image-cropper.js +1 -1
  244. package/dist/media/image-field.js +2 -2
  245. package/dist/media/lightbox.js +4 -3
  246. package/dist/media/link-preview.js +3 -3
  247. package/dist/media/media-library.js +4 -4
  248. package/dist/media/media-picker.js +1 -1
  249. package/dist/media/media-provider.js +1 -1
  250. package/dist/media/video-player.js +4 -4
  251. package/dist/motion/count-up.js +1 -1
  252. package/dist/motion/motion-scope.js +2 -2
  253. package/dist/motion/page-transition.js +1 -1
  254. package/dist/motion/parallax.js +2 -2
  255. package/dist/motion/pointer.js +3 -3
  256. package/dist/motion/reveal.js +3 -3
  257. package/dist/motion/skeleton-swap.js +1 -1
  258. package/dist/motion/text-reveal.d.ts +3 -1
  259. package/dist/motion/text-reveal.js +6 -4
  260. package/dist/motion/ticker.js +1 -1
  261. package/dist/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  262. package/dist/render/block-renderer.js +1 -1
  263. package/dist/scheduler/gantt.js +2 -2
  264. package/dist/scheduler/resource-calendar.js +2 -2
  265. package/dist/scheduler/scheduler.js +3 -3
  266. package/dist/scheduler/time-tracker.js +4 -4
  267. package/dist/sortable/kanban.js +2 -2
  268. package/dist/sortable/sortable-list.js +2 -2
  269. package/dist/sortable/sortable.js +4 -4
  270. package/dist/styles/blocks.css +18 -9
  271. package/dist/styles/editors.css +2 -1
  272. package/dist/styles/media.css +31 -5
  273. package/dist/styles.css +39 -9
  274. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- import { HoverCard as HoverCardPrimitive } from "radix-ui";
4
+ import * as HoverCardPrimitive from "radix-ui/hover-card";
5
5
  import { cva } from "class-variance-authority";
6
6
  import { cn } from "../lib/cn.js";
7
7
  import { usePortalContainer } from "../lib/theme-scope.js";
@@ -16,7 +16,7 @@ export function HoverCard({ openDelay = 500, closeDelay = 150, ...props }) {
16
16
  return _jsx(HoverCardPrimitive.Root, { openDelay: openDelay, closeDelay: closeDelay, ...props });
17
17
  }
18
18
  export const HoverCardTrigger = HoverCardPrimitive.Trigger;
19
- export const hoverCardContentVariants = cva("surface-popover ui-pop z-(--z-popover) rounded-ui-lg p-[calc(var(--gap)*0.85)] outline-none max-w-[calc(100vw-1.5rem)]", {
19
+ export const hoverCardContentVariants = /*#__PURE__*/ cva("surface-popover ui-pop z-(--z-popover) rounded-ui-lg p-[calc(var(--gap)*0.85)] outline-none max-w-[calc(100vw-1.5rem)]", {
20
20
  variants: {
21
21
  size: {
22
22
  sm: "w-64",
@@ -26,7 +26,7 @@ export const hoverCardContentVariants = cva("surface-popover ui-pop z-(--z-popov
26
26
  defaultVariants: { size: "md" },
27
27
  });
28
28
  /** The preview panel. Portals into the nearest `ThemeScope` and follows the layer-depth glass rules. */
29
- export const HoverCardContent = React.forwardRef(function HoverCardContent({ className, size, arrow = false, sideOffset = 8, collisionPadding = 12, children, ...props }, ref) {
29
+ export const HoverCardContent = /*#__PURE__*/ React.forwardRef(function HoverCardContent({ className, size, arrow = false, sideOffset = 8, collisionPadding = 12, children, ...props }, ref) {
30
30
  const container = usePortalContainer();
31
31
  return (_jsx(HoverCardPrimitive.Portal, { container: container, children: _jsx(Layer, { asChild: true, children: _jsxs(HoverCardPrimitive.Content, { ref: ref, "data-slot": "hover-card-content", sideOffset: sideOffset, collisionPadding: collisionPadding, className: cn(hoverCardContentVariants({ size }), className), ...props, children: [children, arrow ? (_jsx(HoverCardPrimitive.Arrow, { asChild: true, width: 14, height: 7, children: _jsx(FloatingArrow, {}) })) : null] }) }) }));
32
32
  });
@@ -40,7 +40,7 @@ const accept = (ch) => /^[0-9A-Za-z]$/.test(ch);
40
40
  * </Field>
41
41
  * ```
42
42
  */
43
- export const IbanInput = React.forwardRef(function IbanInput({ countries, rules = [trIbanRule], showBank = true, value, defaultValue, onValueChange, validateOn = "blur", onValidate, mono = true, labels, name, invalid, trailing, inputClassName, onBlur, onKeyDown, disabled, placeholder, ...rest }, forwardedRef) {
43
+ export const IbanInput = /*#__PURE__*/ React.forwardRef(function IbanInput({ countries, rules = [trIbanRule], showBank = true, value, defaultValue, onValueChange, validateOn = "blur", onValidate, mono = true, labels, name, invalid, trailing, inputClassName, onBlur, onKeyDown, disabled, placeholder, ...rest }, forwardedRef) {
44
44
  const { locale } = useLocale();
45
45
  const t = useLabels("ibanInput", ibanInputLabels, labels);
46
46
  const v = useFormattedValidity(validateOn, onValidate);
@@ -56,7 +56,7 @@ const idInputLabels = {
56
56
  * </Field>
57
57
  * ```
58
58
  */
59
- export const IdInput = React.forwardRef(function IdInput({ kind, masked = false, value, defaultValue, onValueChange, validateOn = "blur", onValidate, mono = true, labels, name, invalid, inputClassName, onBlur, onFocus, onKeyDown, disabled, placeholder, ...rest }, forwardedRef) {
59
+ export const IdInput = /*#__PURE__*/ React.forwardRef(function IdInput({ kind, masked = false, value, defaultValue, onValueChange, validateOn = "blur", onValidate, mono = true, labels, name, invalid, inputClassName, onBlur, onFocus, onKeyDown, disabled, placeholder, ...rest }, forwardedRef) {
60
60
  const rule = typeof kind === "string" ? registry.get(kind) : kind;
61
61
  if (!rule && process.env.NODE_ENV !== "production")
62
62
  console.warn(`IdInput: no rule registered for "${String(kind)}".`);
@@ -121,10 +121,10 @@ export const IdInput = React.forwardRef(function IdInput({ kind, masked = false,
121
121
  } }) }), submitName ? _jsx("input", { type: "hidden", name: submitName, value: engine.raw ?? "", disabled: disabled }) : null] }));
122
122
  });
123
123
  /** `IdInput` preset for personal IDs. Default kind `tr-tckn`. */
124
- export const NationalIdInput = React.forwardRef(function NationalIdInput({ kind = "tr-tckn", ...props }, ref) {
124
+ export const NationalIdInput = /*#__PURE__*/ React.forwardRef(function NationalIdInput({ kind = "tr-tckn", ...props }, ref) {
125
125
  return _jsx(IdInput, { ref: ref, kind: kind, ...props });
126
126
  });
127
127
  /** `IdInput` preset for tax numbers. Default kind `tr-tax-id` (VKN or a sole proprietor's TCKN). */
128
- export const TaxIdInput = React.forwardRef(function TaxIdInput({ kind = "tr-tax-id", ...props }, ref) {
128
+ export const TaxIdInput = /*#__PURE__*/ React.forwardRef(function TaxIdInput({ kind = "tr-tax-id", ...props }, ref) {
129
129
  return _jsx(IdInput, { ref: ref, kind: kind, ...props });
130
130
  });
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  import type { CropRect, ImageLoader, MediaAsset } from "../media/types.js";
4
+ import { type PlaceholderArtPattern } from "./placeholder-art.js";
4
5
  export type ImageAspect = "auto" | "1/1" | "4/3" | "3/2" | "16/9" | "21/9" | "4/5" | "1.91/1" | number;
5
6
  /** Default `srcset` steps. */
6
7
  export declare const IMAGE_WIDTHS: number[];
@@ -57,7 +58,7 @@ declare const imageLabels: {
57
58
  error: string;
58
59
  };
59
60
  export type ImageLabels = typeof imageLabels;
60
- export type ImagePlaceholder = "blur" | "color" | "skeleton" | "none";
61
+ export type ImagePlaceholder = "blur" | "color" | "skeleton" | "art" | "none";
61
62
  export interface ImageBaseProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src" | "placeholder" | "width" | "height" | "alt">, Omit<VariantProps<typeof imageVariants>, "fit"> {
62
63
  width?: number;
63
64
  height?: number;
@@ -77,8 +78,20 @@ export interface ImageBaseProps extends Omit<React.ImgHTMLAttributes<HTMLImageEl
77
78
  quality?: number;
78
79
  /** Above the fold: eager loading + `fetchpriority="high"`. */
79
80
  priority?: boolean;
80
- /** While loading. Default: `blur` with a blur source, `color` with a dominant colour, else `skeleton`. */
81
+ /**
82
+ * While loading. Default: `blur` with a blur source, `color` with a dominant colour, else `skeleton`.
83
+ * `art` shows a seeded token pattern (PlaceholderArt) while loading and on error. Without a `src`
84
+ * the image always renders as art.
85
+ */
81
86
  placeholder?: ImagePlaceholder;
87
+ /** Seed for the art placeholder. Default: `alt`, then the URL. Same seed → same pattern. */
88
+ seed?: string;
89
+ /** Force the art pattern. Default `"auto"` (from the seed). */
90
+ placeholderPattern?: PlaceholderArtPattern | "auto";
91
+ /** Glyph in the art placeholder. `false` hides it. */
92
+ placeholderIcon?: React.ReactNode | false;
93
+ /** Print `alt` (or this node) as a small caption on the art placeholder. */
94
+ placeholderCaption?: boolean | React.ReactNode;
82
95
  /** Tiny blurred preview (LQIP data URL or a small URL). Defaults to `asset.placeholder`. */
83
96
  blurDataURL?: string;
84
97
  /** Placeholder colour. Defaults to `asset.dominantColor`. */
@@ -103,6 +116,9 @@ export type ImageProps = ImageBaseProps & ({
103
116
  } | {
104
117
  src: MediaAsset;
105
118
  alt?: string;
119
+ } | {
120
+ src?: null | "";
121
+ alt: string;
106
122
  });
107
123
  /**
108
124
  * The image primitive: no layout shift (width/height + `aspect-ratio`), focal point →
@@ -9,6 +9,7 @@ import { DefaultImage, useImage, useMediaAdapter } from "../lib/provider.js";
9
9
  import { useComposedRefs } from "../lib/compose-refs.js";
10
10
  import { useIsomorphicLayoutEffect } from "../lib/use-controllable-state.js";
11
11
  import { Spinner } from "./spinner.js";
12
+ import { PlaceholderArt } from "./placeholder-art.js";
12
13
  /** Default `srcset` steps. */
13
14
  export const IMAGE_WIDTHS = [320, 480, 640, 768, 1024, 1280, 1600, 1920];
14
15
  /** `"16/9"` → 1.777…, `1.5` → 1.5, `"auto"` → the intrinsic ratio (or `undefined`). */
@@ -55,7 +56,7 @@ export function getImageSources(source, options = {}) {
55
56
  /* ------------------------------------------------------------------ */
56
57
  /* Loader context */
57
58
  /* ------------------------------------------------------------------ */
58
- const ImageLoaderContext = React.createContext(undefined);
59
+ const ImageLoaderContext = /*#__PURE__*/ React.createContext(undefined);
59
60
  /**
60
61
  * Sets the image loader for every kit `Image` below (CDN URL builder). Same signature as the
61
62
  * Next.js loader. The media adapter's `loader` is used when no provider sets one.
@@ -86,7 +87,7 @@ export function useImageSources(source, options = {}) {
86
87
  /* ------------------------------------------------------------------ */
87
88
  /* Image */
88
89
  /* ------------------------------------------------------------------ */
89
- export const imageVariants = cva("vui-image relative isolate block max-w-full overflow-hidden bg-skeleton", {
90
+ export const imageVariants = /*#__PURE__*/ cva("vui-image relative isolate block max-w-full overflow-hidden bg-skeleton", {
90
91
  variants: {
91
92
  rounded: { none: "", ui: "rounded-ui", "ui-lg": "rounded-ui-lg", full: "rounded-full" },
92
93
  fit: { cover: "", contain: "" },
@@ -107,9 +108,10 @@ const FILENAME_ALT = /(^(img|dsc|pxl|screenshot)[-_ ]?\d+)|\.(jpe?g|png|gif|webp
107
108
  * <Image src={asset} alt="Lobby of the Kadıköy office" aspect="16/9" sizes="(min-width: 1024px) 50vw, 100vw" rounded="ui" />
108
109
  * ```
109
110
  */
110
- export const Image = React.forwardRef(function Image({ src: source, alt: altProp, width: widthProp, height: heightProp, aspect = "auto", fit = "cover", focal: focalProp, crop, sizes, widths, quality, priority, placeholder: placeholderProp, blurDataURL, color: colorProp, loader, fallback, processing: processingProp, rounded, frame, className, imgClassName, style, labels, onLoad, onError, loading, decoding, ...props }, forwardedRef) {
111
+ export const Image = /*#__PURE__*/ React.forwardRef(function Image({ src: source, alt: altProp, width: widthProp, height: heightProp, aspect = "auto", fit = "cover", focal: focalProp, crop, sizes, widths, quality, priority, placeholder: placeholderProp, blurDataURL, seed, placeholderPattern, placeholderIcon, placeholderCaption, color: colorProp, loader, fallback, processing: processingProp, rounded, frame, className, imgClassName, style, labels, onLoad, onError, loading, decoding, ...props }, forwardedRef) {
111
112
  const t = useLabels("image", imageLabels, labels);
112
113
  const Bridge = useImage();
114
+ const empty = !source || (typeof source === "string" && !source.trim());
113
115
  const asset = isAsset(source) ? source : undefined;
114
116
  const alt = altProp ?? asset?.alt ?? "";
115
117
  const width = widthProp ?? asset?.width;
@@ -118,9 +120,10 @@ export const Image = React.forwardRef(function Image({ src: source, alt: altProp
118
120
  const blur = blurDataURL ?? asset?.placeholder;
119
121
  const color = colorProp ?? asset?.dominantColor;
120
122
  const processing = processingProp ?? asset?.status === "processing";
121
- const placeholder = placeholderProp ?? (blur ? "blur" : color ? "color" : "skeleton");
122
- const ratio = aspectRatioOf(aspect, width, height);
123
- const sources = useImageSources(source, { sizes, widths, loader, quality, focal, crop });
123
+ const placeholder = empty ? "art" : placeholderProp ?? (blur ? "blur" : color ? "color" : "skeleton");
124
+ // An empty image has no intrinsic size: fall back to 4:3 so it never collapses.
125
+ const ratio = aspectRatioOf(aspect, width, height) ?? (empty ? 4 / 3 : undefined);
126
+ const sources = useImageSources(source || "", { sizes, widths, loader, quality, focal, crop });
124
127
  const [state, setState] = React.useState("loading");
125
128
  const imgRef = React.useRef(null);
126
129
  const ref = useComposedRefs(forwardedRef, imgRef);
@@ -138,6 +141,10 @@ export const Image = React.forwardRef(function Image({ src: source, alt: altProp
138
141
  if (process.env.NODE_ENV !== "production" && alt && FILENAME_ALT.test(alt.trim())) {
139
142
  console.warn(`Image: alt text "${alt}" looks like a file name. Describe the image instead, or pass alt="" if it is decorative.`);
140
143
  }
144
+ const art = (decorative) => (_jsx(PlaceholderArt, { "data-slot": "image-art", seed: seed ?? (alt || (typeof source === "string" ? source : asset?.id) || ""), pattern: placeholderPattern, icon: placeholderIcon, caption: placeholderCaption === true ? alt || undefined : placeholderCaption, label: decorative ? undefined : alt || undefined, className: "absolute inset-0" }));
145
+ if (empty) {
146
+ return (_jsx("span", { "data-slot": "image", "data-state": "empty", "data-placeholder": "art", className: cn(imageVariants({ rounded, frame }), "bg-transparent", className), style: { aspectRatio: String(ratio), ...style }, children: art(false) }));
147
+ }
141
148
  const objectPosition = focalToObjectPosition(focal);
142
149
  const positioned = ratio !== undefined;
143
150
  const imgClasses = cn("vui-image-img block", positioned ? "absolute inset-0 size-full" : "h-auto w-full", fit === "contain" ? "object-contain" : "object-cover", imgClassName);
@@ -156,13 +163,13 @@ export const Image = React.forwardRef(function Image({ src: source, alt: altProp
156
163
  ...(positioned ? { aspectRatio: String(ratio) } : null),
157
164
  ...(placeholder === "color" && color ? { backgroundColor: color } : null),
158
165
  ...style,
159
- }, children: [placeholder === "blur" && blur && state !== "error" ? (_jsx("img", { "aria-hidden": true, alt: "", src: blur, "data-slot": "image-blur", className: "vui-image-blur pointer-events-none absolute inset-0 size-full object-cover", style: imgStyle })) : null, placeholder === "skeleton" && state === "loading" ? _jsx("span", { "aria-hidden": true, "data-slot": "image-skeleton", className: "ui-shimmer absolute inset-0" }) : null, state === "error" ? (fallback ? (_jsx("span", { "data-slot": "image-fallback", className: cn(positioned ? "absolute inset-0" : "block min-h-24", "flex items-center justify-center"), children: fallback })) : (_jsx("span", { "data-slot": "image-fallback", ...(alt ? { role: "img", "aria-label": alt } : { "aria-hidden": true }), title: t("error"), className: cn(positioned ? "absolute inset-0" : "block min-h-24", "flex items-center justify-center text-fg-subtle [&_svg]:size-6"), children: _jsx(ImageOff, { "aria-hidden": true, strokeWidth: 1.5 }) }))) : (img), processing ? (_jsxs("span", { "data-slot": "image-processing", className: "surface-popover absolute start-2 top-2 z-10 inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[11px] font-medium", children: [_jsx(Spinner, { size: "xs", tone: "accent" }), t("processing")] })) : null] }));
166
+ }, children: [placeholder === "blur" && blur && state !== "error" ? (_jsx("img", { "aria-hidden": true, alt: "", src: blur, "data-slot": "image-blur", className: "vui-image-blur pointer-events-none absolute inset-0 size-full object-cover", style: imgStyle })) : null, placeholder === "skeleton" && state === "loading" ? _jsx("span", { "aria-hidden": true, "data-slot": "image-skeleton", className: "ui-shimmer absolute inset-0" }) : null, placeholder === "art" && state === "loading" ? art(true) : null, state === "error" ? (placeholder === "art" && !fallback ? (_jsx("span", { "data-slot": "image-fallback", title: t("error"), className: cn(positioned ? "absolute inset-0" : "relative block min-h-24"), children: art(false) })) : fallback ? (_jsx("span", { "data-slot": "image-fallback", className: cn(positioned ? "absolute inset-0" : "block min-h-24", "flex items-center justify-center"), children: fallback })) : (_jsx("span", { "data-slot": "image-fallback", ...(alt ? { role: "img", "aria-label": alt } : { "aria-hidden": true }), title: t("error"), className: cn(positioned ? "absolute inset-0" : "block min-h-24", "flex items-center justify-center text-fg-subtle [&_svg]:size-6"), children: _jsx(ImageOff, { "aria-hidden": true, strokeWidth: 1.5 }) }))) : (img), processing ? (_jsxs("span", { "data-slot": "image-processing", className: "surface-popover absolute start-2 top-2 z-10 inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[11px] font-medium", children: [_jsx(Spinner, { size: "xs", tone: "accent" }), t("processing")] })) : null] }));
160
167
  });
161
168
  /** `<figure>` for a captioned image (blocks, galleries, articles). */
162
- export const Figure = React.forwardRef(function Figure({ gap = "sm", className, ...props }, ref) {
169
+ export const Figure = /*#__PURE__*/ React.forwardRef(function Figure({ gap = "sm", className, ...props }, ref) {
163
170
  return _jsx("figure", { ref: ref, "data-slot": "figure", className: cn("m-0 flex flex-col", gap === "sm" ? "gap-2" : "gap-3", className), ...props });
164
171
  });
165
172
  /** `<figcaption>`: caption text plus an optional credit. */
166
- export const FigureCaption = React.forwardRef(function FigureCaption({ credit, className, children, ...props }, ref) {
173
+ export const FigureCaption = /*#__PURE__*/ React.forwardRef(function FigureCaption({ credit, className, children, ...props }, ref) {
167
174
  return (_jsxs("figcaption", { ref: ref, "data-slot": "figure-caption", className: cn("text-[13px] leading-relaxed text-pretty text-fg-muted", className), ...props, children: [children, credit ? _jsx("span", { className: "ms-2 text-[11.5px] tracking-wide text-fg-subtle uppercase", children: credit }) : null] }));
168
175
  });
@@ -16,13 +16,13 @@ const PATTERNS = {
16
16
  digits: "^\\d+$",
17
17
  alphanumeric: "^[a-zA-Z0-9]+$",
18
18
  };
19
- const OTPStyleContext = React.createContext({ size: "md", mask: false, invalid: false });
19
+ const OTPStyleContext = /*#__PURE__*/ React.createContext({ size: "md", mask: false, invalid: false });
20
20
  /**
21
21
  * One real `<input>` (screen readers, SMS autofill, password managers and paste all see one
22
22
  * field) with visual slots drawn over it. Compose `InputOTPGroup` / `InputOTPSlot` /
23
23
  * `InputOTPSeparator`, or use the `InputOTP` shorthand.
24
24
  */
25
- export const InputOTPRoot = React.forwardRef(function InputOTPRoot(rawProps, ref) {
25
+ export const InputOTPRoot = /*#__PURE__*/ React.forwardRef(function InputOTPRoot(rawProps, ref) {
26
26
  const { maxLength, value: valueProp, defaultValue, onValueChange, onComplete, pattern = "digits", size = "md", mask = false, invalid, loading, containerClassName, className, labels, children, ...rest } = rawProps;
27
27
  const t = useLabels("otp", otpLabels, labels);
28
28
  const field = useFieldContext();
@@ -37,11 +37,11 @@ export const InputOTPRoot = React.forwardRef(function InputOTPRoot(rawProps, ref
37
37
  dir: "ltr", children: _jsxs(_Fragment, { children: [children, loading ? (_jsx("span", { className: "ms-1 inline-flex items-center", children: _jsx(Spinner, { size: "sm", tone: "muted", label: t("verifying") }) })) : null] }) }) }));
38
38
  });
39
39
  /** A run of joined slots. */
40
- export const InputOTPGroup = React.forwardRef(function InputOTPGroup({ className, ...props }, ref) {
40
+ export const InputOTPGroup = /*#__PURE__*/ React.forwardRef(function InputOTPGroup({ className, ...props }, ref) {
41
41
  return _jsx("div", { ref: ref, "data-slot": "input-otp-group", className: cn("ui-otp-group flex items-center", className), ...props });
42
42
  });
43
43
  /** One visual character box: active ring, fake caret, filled state. */
44
- export const InputOTPSlot = React.forwardRef(function InputOTPSlot({ index, className, ...props }, ref) {
44
+ export const InputOTPSlot = /*#__PURE__*/ React.forwardRef(function InputOTPSlot({ index, className, ...props }, ref) {
45
45
  const ctx = React.useContext(OTPInputContext);
46
46
  const { size, mask, invalid } = React.useContext(OTPStyleContext);
47
47
  const slot = ctx.slots[index];
@@ -49,7 +49,7 @@ export const InputOTPSlot = React.forwardRef(function InputOTPSlot({ index, clas
49
49
  return (_jsxs("div", { ref: ref, "data-slot": "input-otp-slot", "data-active": slot?.isActive ? "" : undefined, "data-filled": char ? "" : undefined, "aria-hidden": true, className: cn("relative flex items-center justify-center border-y border-e border-field-border bg-field font-medium text-fg tabular", "transition-[border-color,box-shadow,background-color] duration-150", "first:rounded-s-ui first:border-s last:rounded-e-ui", size === "lg" ? "h-[calc(var(--control-h)+1rem)] w-[calc(var(--control-h)+0.25rem)] text-xl" : "h-[calc(var(--control-h)+0.25rem)] w-[calc(var(--control-h)-0.25rem)] text-lg", "group-hover/otp:border-field-border-hover", slot?.isActive && "z-10 border-ring shadow-[0_0_0_3px_var(--accent-soft)]", slot?.isActive && "border-s", invalid && "border-danger", invalid && slot?.isActive && "shadow-[0_0_0_3px_color-mix(in_srgb,var(--danger)_18%,transparent)]", className), ...props, children: [char ? mask ? _jsx("span", { className: "size-2 rounded-full bg-current" }) : char : null, slot?.hasFakeCaret ? (_jsx("span", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: _jsx("span", { className: "ui-otp-caret h-[45%] w-px bg-fg" }) })) : null] }));
50
50
  });
51
51
  /** Visual divider between groups (123–456). */
52
- export const InputOTPSeparator = React.forwardRef(function InputOTPSeparator({ className, ...props }, ref) {
52
+ export const InputOTPSeparator = /*#__PURE__*/ React.forwardRef(function InputOTPSeparator({ className, ...props }, ref) {
53
53
  return (_jsx("div", { ref: ref, role: "separator", "data-slot": "input-otp-separator", className: cn("flex w-3 items-center justify-center text-fg-subtle", className), ...props, children: _jsx("span", { className: "h-px w-2.5 bg-current" }) }));
54
54
  });
55
55
  /**
@@ -62,7 +62,7 @@ export const InputOTPSeparator = React.forwardRef(function InputOTPSeparator({ c
62
62
  * </Field>
63
63
  * ```
64
64
  */
65
- export const InputOTP = React.forwardRef(function InputOTP({ length = 6, groups, ...props }, ref) {
65
+ export const InputOTP = /*#__PURE__*/ React.forwardRef(function InputOTP({ length = 6, groups, ...props }, ref) {
66
66
  const sizes = groups && groups.reduce((a, b) => a + b, 0) === length ? groups : [length];
67
67
  let start = 0;
68
68
  return (_jsx(InputOTPRoot, { ref: ref, maxLength: length, ...props, children: sizes.map((count, gi) => {
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { Label as LabelPrimitive } from "radix-ui";
2
+ import * as LabelPrimitive from "radix-ui/label";
3
3
  /**
4
4
  * The classic field look for a bare `<input>` / `<textarea>`. Kept for compatibility —
5
5
  * new controls should use `controlVariants` from `lib/variants`.
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- import { Label as LabelPrimitive } from "radix-ui";
4
+ import * as LabelPrimitive from "radix-ui/label";
5
5
  import { CircleAlert, X } from "lucide-react";
6
6
  import { cn } from "../lib/cn.js";
7
7
  import { useComposedRefs, mergeIds } from "../lib/compose-refs.js";
@@ -39,7 +39,7 @@ const setNativeValue = (el, value) => {
39
39
  * <Input addonStart="https://" addonEnd=".vamos.ist" defaultValue="northpoint" />
40
40
  * ```
41
41
  */
42
- export const Input = React.forwardRef(function Input(rawProps, forwardedRef) {
42
+ export const Input = /*#__PURE__*/ React.forwardRef(function Input(rawProps, forwardedRef) {
43
43
  const { className, inputClassName, size = "md", variant = "default", leading, trailing, addonStart, addonEnd, clearable, onClear, showCount, invalid, labels, style, ...rest } = rawProps;
44
44
  const props = useFieldControl({ ...rest, "aria-invalid": invalid ? true : rest["aria-invalid"] });
45
45
  const t = useLabels("input", inputLabels, labels);
@@ -92,7 +92,7 @@ export const Input = React.forwardRef(function Input(rawProps, forwardedRef) {
92
92
  * <Field label="Anything we should know first?"><Textarea maxLength={400} showCount /></Field>
93
93
  * ```
94
94
  */
95
- export const Textarea = React.forwardRef(function Textarea({ className, rows = 4, invalid, showCount, labels, ...rest }, ref) {
95
+ export const Textarea = /*#__PURE__*/ React.forwardRef(function Textarea({ className, rows = 4, invalid, showCount, labels, ...rest }, ref) {
96
96
  const props = useFieldControl({ ...rest, "aria-invalid": invalid ? true : rest["aria-invalid"] });
97
97
  const t = useLabels("input", inputLabels, labels);
98
98
  const countId = React.useId();
@@ -114,7 +114,7 @@ export const Textarea = React.forwardRef(function Textarea({ className, rows = 4
114
114
  /* Label */
115
115
  /* ------------------------------------------------------------------ */
116
116
  /** Form label (Radix Label: no text selection on double-click). */
117
- export const Label = React.forwardRef(function Label({ className, ...props }, ref) {
117
+ export const Label = /*#__PURE__*/ React.forwardRef(function Label({ className, ...props }, ref) {
118
118
  return (_jsx(LabelPrimitive.Root, { ref: ref, "data-slot": "label", className: cn("text-[13px] font-medium text-fg", className), ...props }));
119
119
  });
120
120
  /* ------------------------------------------------------------------ */
@@ -175,13 +175,13 @@ export function Field({ label, hint, error, id, name, required = false, optional
175
175
  * </Fieldset>
176
176
  * ```
177
177
  */
178
- export const Fieldset = React.forwardRef(function Fieldset({ legend, hint, error, className, children, "aria-describedby": describedBy, ...props }, ref) {
178
+ export const Fieldset = /*#__PURE__*/ React.forwardRef(function Fieldset({ legend, hint, error, className, children, "aria-describedby": describedBy, ...props }, ref) {
179
179
  const id = React.useId();
180
180
  const hintId = hint && !error ? `${id}-hint` : undefined;
181
181
  const errorId = error ? `${id}-error` : undefined;
182
182
  return (_jsxs("fieldset", { ref: ref, "data-slot": "fieldset", "aria-describedby": mergeIds(hintId, errorId, describedBy), "data-invalid": error ? "" : undefined, className: cn("grid min-w-0 gap-3 border-0 p-0 disabled:opacity-60", className), ...props, children: [legend ? _jsx(Legend, { className: "float-left w-full", children: legend }) : null, hint && !error ? (_jsx("p", { id: hintId, className: "-mt-2 text-xs text-fg-subtle", children: hint })) : null, error ? (_jsxs("p", { id: errorId, className: "-mt-2 flex items-start gap-1.5 text-xs text-danger", children: [_jsx(CircleAlert, { "aria-hidden": true, className: "mt-px size-3.5 shrink-0" }), _jsx("span", { children: error })] })) : null, children] }));
183
183
  });
184
184
  /** Title of a Fieldset. */
185
- export const Legend = React.forwardRef(function Legend({ className, ...props }, ref) {
185
+ export const Legend = /*#__PURE__*/ React.forwardRef(function Legend({ className, ...props }, ref) {
186
186
  return _jsx("legend", { ref: ref, "data-slot": "legend", className: cn("mb-0 p-0 text-sm font-semibold tracking-[-0.005em] text-fg", className), ...props });
187
187
  });
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
- import { Slot } from "radix-ui";
3
+ import * as Slot from "radix-ui/slot";
4
4
  import { Check } from "lucide-react";
5
5
  import { cva } from "class-variance-authority";
6
6
  import { cn } from "../lib/cn.js";
@@ -16,7 +16,7 @@ import { Skeleton } from "./skeleton.js";
16
16
  * </ItemList>
17
17
  * ```
18
18
  */
19
- export const ItemList = React.forwardRef(function ItemList({ divided = true, inset, selectable, value, defaultValue, onValueChange, as = "ul", empty, className, children, ...props }, ref) {
19
+ export const ItemList = /*#__PURE__*/ React.forwardRef(function ItemList({ divided = true, inset, selectable, value, defaultValue, onValueChange, as = "ul", empty, className, children, ...props }, ref) {
20
20
  const count = React.Children.toArray(children).length;
21
21
  const classes = cn("group/list m-0 grid list-none p-0", inset && "-mx-2 gap-0.5",
22
22
  // hairline at the bottom of every row but the last (also through an asChild wrapper)
@@ -34,7 +34,7 @@ export const ItemList = React.forwardRef(function ItemList({ divided = true, ins
34
34
  /* ------------------------------------------------------------------ */
35
35
  /* Item */
36
36
  /* ------------------------------------------------------------------ */
37
- export const itemRowVariants = cva([
37
+ export const itemRowVariants = /*#__PURE__*/ cva([
38
38
  "group/item relative flex w-full min-w-0 gap-3 text-start text-[13px] text-fg outline-none",
39
39
  "px-(--card-p,1.25rem) group-data-inset/list:rounded-ui-sm group-data-inset/list:px-2",
40
40
  // states (also driven by the listbox island via aria-selected / aria-disabled)
@@ -67,7 +67,7 @@ export const itemRowVariants = cva([
67
67
  * </Item>
68
68
  * ```
69
69
  */
70
- export const Item = React.forwardRef(function Item({ value, asChild, interactive, disabled, size, align, as = "li", className, children, ...props }, ref) {
70
+ export const Item = /*#__PURE__*/ React.forwardRef(function Item({ value, asChild, interactive, disabled, size, align, as = "li", className, children, ...props }, ref) {
71
71
  const option = value !== undefined;
72
72
  const rowClass = cn(itemRowVariants({ size, align, interactive: interactive ?? (asChild || option) }), className);
73
73
  const state = {
@@ -5,7 +5,7 @@ import { cva } from "class-variance-authority";
5
5
  import { cn } from "../lib/cn.js";
6
6
  import { formatKey, parseShortcut, shortcutKeys, useIsMac } from "../lib/use-hotkeys.js";
7
7
  import { useLabels } from "../lib/labels.js";
8
- export const kbdVariants = cva("ui-keycap inline-flex shrink-0 select-none items-center justify-center whitespace-nowrap rounded-[calc(var(--radius)*0.42)] font-mono font-medium leading-none tabular", {
8
+ export const kbdVariants = /*#__PURE__*/ cva("ui-keycap inline-flex shrink-0 select-none items-center justify-center whitespace-nowrap rounded-[calc(var(--radius)*0.42)] font-mono font-medium leading-none tabular", {
9
9
  variants: {
10
10
  size: {
11
11
  sm: "h-[1.125rem] min-w-[1.125rem] px-1 text-[10.5px]",
@@ -85,7 +85,7 @@ function spokenKey(token, isMac) {
85
85
  * <Kbd keyName="mod" /> // ⌘ on macOS, Ctrl elsewhere
86
86
  * ```
87
87
  */
88
- export const Kbd = React.forwardRef(function Kbd({ keyName, size, variant, labels, className, children, ...props }, ref) {
88
+ export const Kbd = /*#__PURE__*/ React.forwardRef(function Kbd({ keyName, size, variant, labels, className, children, ...props }, ref) {
89
89
  const isMac = useIsMac();
90
90
  const t = useLabels("kbd", kbdLabels, labels);
91
91
  let content = children;
@@ -112,7 +112,7 @@ export const Kbd = React.forwardRef(function Kbd({ keyName, size, variant, label
112
112
  * <KbdGroup keys={["g", "p"]} separator="then" />
113
113
  * ```
114
114
  */
115
- export const KbdGroup = React.forwardRef(function KbdGroup({ keys, separator, size, variant, labels, className, ...props }, ref) {
115
+ export const KbdGroup = /*#__PURE__*/ React.forwardRef(function KbdGroup({ keys, separator, size, variant, labels, className, ...props }, ref) {
116
116
  const isMac = useIsMac();
117
117
  const tokens = typeof keys === "string" ? shortcutKeys(keys, isMac) : keys;
118
118
  return (_jsx("kbd", { ref: ref, dir: "ltr", "data-slot": "kbd-group", className: cn("inline-flex items-center gap-1 font-sans", className), ...props, children: tokens.map((k, i) => (_jsxs(React.Fragment, { children: [i > 0 && separator != null ? (_jsx("span", { "aria-hidden": typeof separator === "string" && /^[+\-–]$/.test(separator) ? true : undefined, className: "text-[11px] text-fg-subtle", children: separator })) : null, _jsx(Kbd, { keyName: k, size: size, variant: variant, labels: labels })] }, `${k}-${i}`))) }));
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
4
+ import * as ToggleGroupPrimitive from "radix-ui/toggle-group";
5
5
  import { cva } from "class-variance-authority";
6
6
  import { SlidersHorizontal, X } from "lucide-react";
7
7
  import { cn } from "../lib/cn.js";
@@ -35,11 +35,11 @@ const listLabels = {
35
35
  error: "Couldn't load this list",
36
36
  retry: "Try again",
37
37
  };
38
- const ListLayoutContext = React.createContext(null);
38
+ const ListLayoutContext = /*#__PURE__*/ React.createContext(null);
39
39
  /* ------------------------------------------------------------------ */
40
40
  /* ListLayout */
41
41
  /* ------------------------------------------------------------------ */
42
- export const listLayoutVariants = cva("@container/list relative mx-auto flex w-full min-w-0 flex-col", {
42
+ export const listLayoutVariants = /*#__PURE__*/ cva("@container/list relative mx-auto flex w-full min-w-0 flex-col", {
43
43
  variants: {
44
44
  width: {
45
45
  /** Edge to edge of the page area. */
@@ -70,7 +70,7 @@ export const listLayoutVariants = cva("@container/list relative mx-auto flex w-f
70
70
  *
71
71
  * Responds to its own width (container queries), so it behaves the same in a split view.
72
72
  */
73
- export const ListLayout = React.forwardRef(function ListLayout({ width = "full", stickyToolbar = true, stickyTop, className, style, ...props }, ref) {
73
+ export const ListLayout = /*#__PURE__*/ React.forwardRef(function ListLayout({ width = "full", stickyToolbar = true, stickyTop, className, style, ...props }, ref) {
74
74
  const [bulkActive, setBulkActive] = React.useState(false);
75
75
  const toolbarRef = React.useRef(null);
76
76
  const ctx = React.useMemo(() => ({ stickyToolbar, bulkActive, setBulkActive, toolbarRef }), [stickyToolbar, bulkActive]);
@@ -82,7 +82,7 @@ const stickyBar = "sticky top-(--list-sticky-top,var(--topbar-h)) z-(--z-sticky)
82
82
  * The row above the content. Sticky under the top bar on the bar surface; while a selection is
83
83
  * active the `ListBulkBar` takes its place.
84
84
  */
85
- export const ListToolbar = React.forwardRef(function ListToolbar({ search, filters, filterCount, views, viewSwitch, actions, searchLabel, labels, className, children, ...props }, ref) {
85
+ export const ListToolbar = /*#__PURE__*/ React.forwardRef(function ListToolbar({ search, filters, filterCount, views, viewSwitch, actions, searchLabel, labels, className, children, ...props }, ref) {
86
86
  const t = useLabels("list", listLabels, labels);
87
87
  const ctx = React.useContext(ListLayoutContext);
88
88
  const setRefs = React.useCallback((node) => {
@@ -102,7 +102,7 @@ export const ListToolbar = React.forwardRef(function ListToolbar({ search, filte
102
102
  * Table / grid / board switch: a segmented radio group (one tab stop, arrow keys move, Space selects). Labels
103
103
  * collapse to icons below ~640px of list width; the accessible name stays.
104
104
  */
105
- export const ListViewSwitch = React.forwardRef(function ListViewSwitch({ options, value: valueProp, defaultValue, onValueChange, label, labels, className, ...props }, ref) {
105
+ export const ListViewSwitch = /*#__PURE__*/ React.forwardRef(function ListViewSwitch({ options, value: valueProp, defaultValue, onValueChange, label, labels, className, ...props }, ref) {
106
106
  const t = useLabels("list", listLabels, labels);
107
107
  const [inner, setInner] = React.useState(defaultValue ?? options[0]?.value ?? "");
108
108
  const value = valueProp ?? inner;
@@ -118,7 +118,7 @@ export const ListViewSwitch = React.forwardRef(function ListViewSwitch({ options
118
118
  * The selection bar. Presentational: the Data Table (or your list) owns the selection. Announces
119
119
  * "{n} selected" politely; Esc inside the bar clears the selection and focus returns to the toolbar.
120
120
  */
121
- export const ListBulkBar = React.forwardRef(function ListBulkBar({ count, total, onSelectAll, allSelected, onClear, labels, className, children, onKeyDown, ...props }, ref) {
121
+ export const ListBulkBar = /*#__PURE__*/ React.forwardRef(function ListBulkBar({ count, total, onSelectAll, allSelected, onClear, labels, className, children, onKeyDown, ...props }, ref) {
122
122
  const t = useLabels("list", listLabels, labels);
123
123
  const f = useFormat();
124
124
  const ctx = React.useContext(ListLayoutContext);
@@ -155,7 +155,7 @@ export const ListBulkBar = React.forwardRef(function ListBulkBar({ count, total,
155
155
  * The content slot (table, grid or board) with every state. `refreshing` keeps the content and
156
156
  * shows a thin indeterminate bar; all states set `aria-busy` while work is pending.
157
157
  */
158
- export const ListContent = React.forwardRef(function ListContent({ state = "ready", empty, noResults, error, onRetry, onClearFilters, skeleton, skeletonRows = 6, resultCount, labels, className, children, ...props }, ref) {
158
+ export const ListContent = /*#__PURE__*/ React.forwardRef(function ListContent({ state = "ready", empty, noResults, error, onRetry, onClearFilters, skeleton, skeletonRows = 6, resultCount, labels, className, children, ...props }, ref) {
159
159
  const t = useLabels("list", listLabels, labels);
160
160
  const busy = state === "loading" || state === "refreshing";
161
161
  // Announce state changes once (not on every render).
@@ -205,6 +205,6 @@ export const ListContent = React.forwardRef(function ListContent({ state = "read
205
205
  return (_jsxs("div", { ref: ref, "data-slot": "list-content", "data-state": state, "aria-busy": busy || undefined, className: cn("relative min-w-0 flex-1 py-4", className), ...props, children: [state === "refreshing" ? (_jsx(Progress, { "aria-label": t("refreshing"), value: null, size: "xs", className: "absolute inset-x-0 top-0 rounded-none bg-transparent" })) : null, _jsx("div", { className: cn(state === "refreshing" && "opacity-70 transition-opacity motion-reduce:transition-none"), children: body }), _jsx("div", { "aria-live": "polite", role: "status", className: "sr-only", children: announcement })] }));
206
206
  });
207
207
  /** The row under the content: `PaginationBar`, "Load more", a summary line. */
208
- export const ListFooter = React.forwardRef(function ListFooter({ className, ...props }, ref) {
208
+ export const ListFooter = /*#__PURE__*/ React.forwardRef(function ListFooter({ className, ...props }, ref) {
209
209
  return _jsx("div", { ref: ref, "data-slot": "list-footer", className: cn("flex flex-wrap items-center gap-3 border-t border-line pt-3 pb-1", className), ...props });
210
210
  });
@@ -0,0 +1,96 @@
1
+ import * as React from "react";
2
+ import * as MenubarPrimitive from "radix-ui/menubar";
3
+ import { type VariantProps } from "class-variance-authority";
4
+ import type { MenuEntry } from "../lib/variants.js";
5
+ export declare const menubarVariants: (props?: ({
6
+ variant?: "ghost" | "bar" | null | undefined;
7
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
+ /** One top-level menu in the data-driven form. */
9
+ export interface MenubarMenuEntry {
10
+ id: string;
11
+ /** Trigger text ("File", "Edit", "View"…). */
12
+ label: React.ReactNode;
13
+ /** The menu's entries — the same `MenuEntry` model as Dropdown Menu, Context Menu and Command. */
14
+ items: MenuEntry[];
15
+ disabled?: boolean;
16
+ /** Hidden unless `can(permission)` is true (see `useCan`). */
17
+ permission?: string;
18
+ }
19
+ export interface MenubarProps extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>, VariantProps<typeof menubarVariants> {
20
+ /** Data-driven menus. Rendered before `children`. */
21
+ menus?: MenubarMenuEntry[];
22
+ /** Minimum panel width of every menu: `sm` 180px, `md` 220px. Default `md`. */
23
+ size?: "sm" | "md";
24
+ }
25
+ /**
26
+ * A desktop-app menu bar (WAI-ARIA `menubar`): File / Edit / View… One tab stop; ← → move between
27
+ * menus (and keep the open one open), ↓ / Enter / Space open, Esc closes, typeahead inside a menu.
28
+ *
29
+ * ```tsx
30
+ * <Menubar aria-label="Editor" menus={[
31
+ * { id: "file", label: "File", items: [{ id: "new", label: "New document", shortcut: "mod+n", onSelect: create }] },
32
+ * ]} />
33
+ * ```
34
+ */
35
+ export declare const Menubar: React.ForwardRefExoticComponent<MenubarProps & React.RefAttributes<HTMLDivElement>>;
36
+ /** One menu: a `MenubarTrigger` plus its `MenubarContent`. `value` is needed only for a controlled bar. */
37
+ export declare const MenubarMenu: typeof MenubarPrimitive.Menu;
38
+ export declare const MenubarGroup: React.ForwardRefExoticComponent<MenubarPrimitive.MenubarGroupProps & React.RefAttributes<HTMLDivElement>>;
39
+ export declare const MenubarSub: React.FC<MenubarPrimitive.MenubarSubProps>;
40
+ export declare const MenubarRadioGroup: React.ForwardRefExoticComponent<MenubarPrimitive.MenubarRadioGroupProps & React.RefAttributes<HTMLDivElement>>;
41
+ /** The top-level button ("File"). */
42
+ export declare const MenubarTrigger: React.ForwardRefExoticComponent<Omit<MenubarPrimitive.MenubarTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
43
+ export interface MenubarContentProps extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content> {
44
+ /** Overrides the bar's `size` for this menu. */
45
+ size?: "sm" | "md";
46
+ }
47
+ /** A menu panel under its trigger. Portals into the nearest `ThemeScope`; only this first layer blurs in glass mode. */
48
+ export declare const MenubarContent: React.ForwardRefExoticComponent<MenubarContentProps & React.RefAttributes<HTMLDivElement>>;
49
+ export interface MenubarItemProps extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> {
50
+ icon?: React.ReactNode;
51
+ description?: React.ReactNode;
52
+ /** Shortcut hint, e.g. `"mod+s"` (rendered with Kbd). Display only — bind it with `useHotkeys`. */
53
+ shortcut?: string | string[];
54
+ badge?: React.ReactNode;
55
+ tone?: "default" | "danger";
56
+ /** Reserve the indicator gutter so labels align with checkbox/radio items. */
57
+ inset?: boolean;
58
+ }
59
+ /** One command. `onSelect` fires on click, Enter and Space, then the menu closes (`event.preventDefault()` keeps it open). */
60
+ export declare const MenubarItem: React.ForwardRefExoticComponent<MenubarItemProps & React.RefAttributes<HTMLDivElement>>;
61
+ export interface MenubarCheckboxItemProps extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem> {
62
+ shortcut?: string | string[];
63
+ description?: React.ReactNode;
64
+ }
65
+ /** A toggle (`menuitemcheckbox`) — "Show ruler", "Word wrap". */
66
+ export declare const MenubarCheckboxItem: React.ForwardRefExoticComponent<MenubarCheckboxItemProps & React.RefAttributes<HTMLDivElement>>;
67
+ export interface MenubarRadioItemProps extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem> {
68
+ shortcut?: string | string[];
69
+ description?: React.ReactNode;
70
+ }
71
+ /** One choice inside a `MenubarRadioGroup` (`menuitemradio`) — zoom level, sort order. */
72
+ export declare const MenubarRadioItem: React.ForwardRefExoticComponent<MenubarRadioItemProps & React.RefAttributes<HTMLDivElement>>;
73
+ export declare const MenubarLabel: React.ForwardRefExoticComponent<Omit<MenubarPrimitive.MenubarLabelProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
74
+ inset?: boolean;
75
+ } & React.RefAttributes<HTMLDivElement>>;
76
+ export declare const MenubarSeparator: React.ForwardRefExoticComponent<Omit<MenubarPrimitive.MenubarSeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
77
+ /** Trailing text hint (when you don't want keycaps). */
78
+ export declare function MenubarShortcut({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>): React.JSX.Element;
79
+ export interface MenubarSubTriggerProps extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> {
80
+ icon?: React.ReactNode;
81
+ inset?: boolean;
82
+ }
83
+ /** Opens a submenu on hover, Enter, Space or → (← in RTL). */
84
+ export declare const MenubarSubTrigger: React.ForwardRefExoticComponent<MenubarSubTriggerProps & React.RefAttributes<HTMLDivElement>>;
85
+ /** A submenu panel. One layer deeper, so it is opaque in glass mode. */
86
+ export declare const MenubarSubContent: React.ForwardRefExoticComponent<Omit<MenubarPrimitive.MenubarSubContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
87
+ size?: "sm" | "md";
88
+ } & React.RefAttributes<HTMLDivElement>>;
89
+ /** Renders `MenuEntry[]` as menubar items (inside your own `MenubarContent`). */
90
+ export declare function MenubarEntries({ items }: {
91
+ items: MenuEntry[];
92
+ }): React.JSX.Element;
93
+ /** Renders `MenubarMenuEntry[]` (what `Menubar menus` uses). Menus with no visible entries are dropped. */
94
+ export declare function MenubarMenus({ menus }: {
95
+ menus: MenubarMenuEntry[];
96
+ }): React.JSX.Element;