@godxjp/ui 18.15.3 → 19.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/dist/app/date-format-labels.d.ts +1 -1
  2. package/dist/app/time-format-labels.d.ts +1 -1
  3. package/dist/components/data-display/badge.d.ts +1 -1
  4. package/dist/components/data-display/card.d.ts +4 -13
  5. package/dist/components/data-display/card.js +2 -15
  6. package/dist/components/data-display/data-table.d.ts +3 -8
  7. package/dist/components/data-display/data-table.js +106 -68
  8. package/dist/components/data-display/descriptions.js +34 -5
  9. package/dist/components/data-display/empty-state.js +1 -1
  10. package/dist/components/data-display/permission-matrix.js +7 -7
  11. package/dist/components/data-display/popover.js +2 -9
  12. package/dist/components/data-display/qr-code.d.ts +1 -1
  13. package/dist/components/data-display/scroll-area.d.ts +3 -1
  14. package/dist/components/data-display/scroll-area.js +150 -16
  15. package/dist/components/data-display/table.js +12 -3
  16. package/dist/components/data-entry/branch-scope-picker.js +4 -4
  17. package/dist/components/data-entry/calendar.js +15 -24
  18. package/dist/components/data-entry/cascader.js +67 -71
  19. package/dist/components/data-entry/checkbox.js +9 -1
  20. package/dist/components/data-entry/command.d.ts +6 -6
  21. package/dist/components/data-entry/date-picker.js +28 -15
  22. package/dist/components/data-entry/date-range-picker.js +10 -10
  23. package/dist/components/data-entry/form-field.js +7 -3
  24. package/dist/components/data-entry/index.d.ts +2 -1
  25. package/dist/components/data-entry/input.js +8 -19
  26. package/dist/components/data-entry/label.js +4 -2
  27. package/dist/components/data-entry/month-picker.js +16 -15
  28. package/dist/components/data-entry/month-range-picker.js +17 -16
  29. package/dist/components/data-entry/radio.js +6 -1
  30. package/dist/components/data-entry/search-select.js +29 -29
  31. package/dist/components/data-entry/select.js +15 -18
  32. package/dist/components/data-entry/switch.js +7 -1
  33. package/dist/components/data-entry/textarea.d.ts +56 -0
  34. package/dist/components/data-entry/textarea.js +103 -40
  35. package/dist/components/data-entry/time-picker.js +52 -52
  36. package/dist/components/data-entry/toggle-group.d.ts +1 -0
  37. package/dist/components/data-entry/toggle.d.ts +1 -1
  38. package/dist/components/data-entry/transfer.js +14 -15
  39. package/dist/components/data-entry/tree-select.js +16 -22
  40. package/dist/components/data-entry/upload-crop-dialog.js +4 -4
  41. package/dist/components/data-entry/upload.d.ts +1 -1
  42. package/dist/components/data-entry/upload.js +46 -46
  43. package/dist/components/feedback/alert.js +7 -14
  44. package/dist/components/feedback/dialog.d.ts +23 -32
  45. package/dist/components/feedback/dialog.js +16 -13
  46. package/dist/components/feedback/sheet.d.ts +1 -1
  47. package/dist/components/feedback/sheet.js +14 -14
  48. package/dist/components/feedback/skeleton.js +13 -10
  49. package/dist/components/feedback/sonner.d.ts +1 -1
  50. package/dist/components/feedback/sonner.js +17 -8
  51. package/dist/components/feedback/tooltip.js +1 -1
  52. package/dist/components/general/activity.d.ts +44 -0
  53. package/dist/components/general/activity.js +65 -0
  54. package/dist/components/general/button.d.ts +2 -2
  55. package/dist/components/general/button.js +11 -24
  56. package/dist/components/general/index.d.ts +2 -0
  57. package/dist/components/general/index.js +2 -0
  58. package/dist/components/layout/app-shell.js +5 -3
  59. package/dist/components/layout/auth-divider.d.ts +9 -2
  60. package/dist/components/layout/auth-divider.js +7 -11
  61. package/dist/components/layout/index.d.ts +1 -0
  62. package/dist/components/layout/page-container.d.ts +1 -1
  63. package/dist/components/layout/page-container.js +32 -20
  64. package/dist/components/layout/resizable.d.ts +12 -12
  65. package/dist/components/layout/separator.d.ts +1 -0
  66. package/dist/components/layout/service-role-panel.js +47 -42
  67. package/dist/components/layout/sidebar.js +13 -1
  68. package/dist/components/layout/split-pane.d.ts +12 -1
  69. package/dist/components/layout/split-pane.js +13 -4
  70. package/dist/components/navigation/app-setting-picker.js +5 -14
  71. package/dist/components/navigation/dropdown-menu.js +10 -16
  72. package/dist/components/navigation/menubar.d.ts +3 -6
  73. package/dist/components/navigation/pagination-utils.d.ts +15 -2
  74. package/dist/components/navigation/pagination-utils.js +27 -21
  75. package/dist/components/navigation/pagination.d.ts +4 -4
  76. package/dist/components/navigation/pagination.js +2 -2
  77. package/dist/components/navigation/steps.js +31 -67
  78. package/dist/components/navigation/tabs.js +17 -5
  79. package/dist/components/query/infinite-query-state.js +2 -2
  80. package/dist/components/ui/accordion.d.ts +1 -1
  81. package/dist/components/ui/avatar.d.ts +1 -1
  82. package/dist/components/ui/avatar.js +29 -10
  83. package/dist/components/ui/input-otp.d.ts +8 -6
  84. package/dist/components/ui/rating.js +1 -1
  85. package/dist/components/ui/separator.d.ts +27 -2
  86. package/dist/components/ui/separator.js +42 -11
  87. package/dist/components/ui/toggle-group.d.ts +15 -5
  88. package/dist/components/ui/toggle-group.js +43 -18
  89. package/dist/components/ui/toggle.d.ts +66 -5
  90. package/dist/components/ui/toggle.js +64 -9
  91. package/dist/i18n/messages/en.json +8 -0
  92. package/dist/i18n/messages/ja.json +8 -0
  93. package/dist/i18n/messages/vi.json +8 -0
  94. package/dist/lib/control-styles.d.ts +14 -0
  95. package/dist/lib/control-styles.js +2 -0
  96. package/dist/props/components/data-display.prop.d.ts +85 -3
  97. package/dist/props/components/data-entry.prop.d.ts +17 -0
  98. package/dist/props/components/general.prop.d.ts +52 -1
  99. package/dist/props/components/layout.prop.d.ts +137 -2
  100. package/dist/props/registry.d.ts +116 -5
  101. package/dist/props/registry.js +165 -4
  102. package/dist/props/vocabulary/index.d.ts +2 -2
  103. package/dist/props/vocabulary/interaction.prop.d.ts +15 -0
  104. package/dist/props/vocabulary/layout.prop.d.ts +8 -0
  105. package/dist/styles/alert-layout.css +69 -3
  106. package/dist/styles/badge-layout.css +2 -2
  107. package/dist/styles/base.css +6 -0
  108. package/dist/styles/card-layout.css +27 -7
  109. package/dist/styles/control.css +1150 -29
  110. package/dist/styles/data-display-layout.css +185 -11
  111. package/dist/styles/data-entry-layout.css +352 -1
  112. package/dist/styles/density.css +2 -2
  113. package/dist/styles/dialog-layout.css +203 -4
  114. package/dist/styles/focus-ring.css +155 -0
  115. package/dist/styles/form-layout.css +50 -5
  116. package/dist/styles/index.css +1 -0
  117. package/dist/styles/layout.css +412 -23
  118. package/dist/styles/motion.css +178 -0
  119. package/dist/styles/navigation-layout.css +398 -22
  120. package/dist/styles/shell-layout.css +137 -39
  121. package/dist/styles/table-layout.css +153 -22
  122. package/dist/styles/toggle.css +59 -0
  123. package/dist/tokens/base.css +5 -0
  124. package/dist/tokens/components/activity.css +64 -0
  125. package/dist/tokens/components/badge.css +7 -0
  126. package/dist/tokens/components/card.css +14 -10
  127. package/dist/tokens/components/chart.css +1 -1
  128. package/dist/tokens/components/control.css +358 -8
  129. package/dist/tokens/components/data-display.css +75 -0
  130. package/dist/tokens/components/data-entry.css +25 -0
  131. package/dist/tokens/components/descriptions.css +22 -0
  132. package/dist/tokens/components/feedback.css +143 -4
  133. package/dist/tokens/components/form.css +16 -0
  134. package/dist/tokens/components/legal-document.css +5 -1
  135. package/dist/tokens/components/navigation.css +109 -0
  136. package/dist/tokens/components/scroll-area.css +21 -0
  137. package/dist/tokens/components/separator.css +52 -0
  138. package/dist/tokens/components/shell.css +132 -20
  139. package/dist/tokens/components/table.css +52 -3
  140. package/dist/tokens/components/toggle.css +82 -0
  141. package/dist/tokens/components/upload.css +107 -0
  142. package/dist/tokens/foundation.css +171 -10
  143. package/dist/tokens/semantic/layout.css +120 -1
  144. package/package.json +84 -68
  145. package/scripts/ui-audit.mjs +51 -2
@@ -189,14 +189,14 @@ function TreeSelectRoot({
189
189
  disabled,
190
190
  className: cn(
191
191
  "w-full justify-between font-normal",
192
- allowClear && displayKeys.length > 0 && !disabled && "pe-10",
192
+ allowClear && displayKeys.length > 0 && !disabled && "ui-tree-select-trigger-affixed",
193
193
  controlOpenRingClass,
194
194
  !displayKeys.length && "text-muted-foreground",
195
195
  className
196
196
  ),
197
197
  children: [
198
198
  /* @__PURE__ */ jsx("span", { className: "truncate", children: displayKeys.length ? displayLabel : resolvedPlaceholder }),
199
- /* @__PURE__ */ jsx("span", { className: "ms-2 flex shrink-0 items-center", children: !(allowClear && displayKeys.length > 0 && !disabled) && /* @__PURE__ */ jsx(ChevronsUpDown, { className: "size-4 opacity-50", "aria-hidden": "true" }) })
199
+ /* @__PURE__ */ jsx("span", { className: "ms-2 flex shrink-0 items-center", children: !(allowClear && displayKeys.length > 0 && !disabled) && /* @__PURE__ */ jsx(ChevronsUpDown, { className: "ui-tree-select-chevron", "aria-hidden": "true" }) })
200
200
  ]
201
201
  }
202
202
  ) }),
@@ -205,13 +205,13 @@ function TreeSelectRoot({
205
205
  {
206
206
  type: "button",
207
207
  "aria-label": t("dataEntry.treeSelect.clear"),
208
- className: "absolute end-3 top-1/2 z-10 flex size-6 -translate-y-1/2 items-center justify-center rounded-sm opacity-50 hover:opacity-100 focus-visible:opacity-100",
208
+ className: "ui-tree-select-clear",
209
209
  onClick: clearValue,
210
- children: /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" })
210
+ children: /* @__PURE__ */ jsx(X, { className: "ui-control-affix-icon", "aria-hidden": "true" })
211
211
  }
212
212
  )
213
213
  ] }),
214
- /* @__PURE__ */ jsxs(PopoverContent, { className: "w-[var(--radix-popover-trigger-width)] p-0", align: "start", children: [
214
+ /* @__PURE__ */ jsxs(PopoverContent, { className: "ui-tree-select-popover", align: "start", children: [
215
215
  showSearch && /* @__PURE__ */ jsx(Command, { shouldFilter: false, children: /* @__PURE__ */ jsx(
216
216
  CommandInput,
217
217
  {
@@ -220,14 +220,14 @@ function TreeSelectRoot({
220
220
  onValueChange: setSearch
221
221
  }
222
222
  ) }),
223
- /* @__PURE__ */ jsx(ScrollArea, { className: "max-h-[min(300px,50vh)]", children: /* @__PURE__ */ jsx(
223
+ /* @__PURE__ */ jsx(ScrollArea, { className: "ui-tree-select-list", children: /* @__PURE__ */ jsx(
224
224
  "div",
225
225
  {
226
226
  id: treeId,
227
227
  role: "tree",
228
228
  "aria-multiselectable": Boolean(checkable) || Boolean(multiple),
229
- className: "p-1",
230
- children: visible.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground py-6 text-center text-sm", children: t("dataEntry.treeSelect.empty") }) : visible.map(({ node, depth, hasChildren }) => {
229
+ className: "ui-tree-select-panel",
230
+ children: visible.length === 0 ? /* @__PURE__ */ jsx("p", { className: "ui-tree-select-empty", children: t("dataEntry.treeSelect.empty") }) : visible.map(({ node, depth, hasChildren }) => {
231
231
  const expanded = expandedKeys.has(node.value);
232
232
  const isSelected = selected.includes(node.value);
233
233
  return /* @__PURE__ */ jsxs(
@@ -242,14 +242,10 @@ function TreeSelectRoot({
242
242
  "aria-selected": isSelected,
243
243
  onFocus: () => setActiveKey(node.value),
244
244
  onKeyDown: (event) => onTreeItemKeyDown(event, node, hasChildren, expanded),
245
- className: cn(
246
- "flex items-center rounded-sm py-1.5 pe-2 text-sm outline-none",
247
- "hover:bg-accent hover:text-accent-foreground",
248
- "focus-visible:ring-ring focus-visible:ring-2 focus-visible:ring-offset-1",
249
- isSelected && "bg-accent/60",
250
- node.disabled && "pointer-events-none opacity-50"
251
- ),
252
- style: { paddingInlineStart: `${depth * 1.25 + 0.5}rem` },
245
+ "data-selected": isSelected ? "true" : "false",
246
+ "data-disabled": node.disabled ? "" : void 0,
247
+ className: "ui-tree-select-row ui-focus-ring",
248
+ style: { "--tree-select-depth": depth },
253
249
  children: [
254
250
  /* @__PURE__ */ jsx(
255
251
  "button",
@@ -257,15 +253,13 @@ function TreeSelectRoot({
257
253
  type: "button",
258
254
  tabIndex: -1,
259
255
  "aria-label": expanded ? t("dataEntry.treeSelect.collapse") : t("dataEntry.treeSelect.expand"),
260
- className: cn(
261
- "me-1 flex size-5 shrink-0 items-center justify-center rounded-sm",
262
- !hasChildren && "invisible"
263
- ),
256
+ "data-leaf": hasChildren ? void 0 : "",
257
+ className: "ui-tree-select-toggle",
264
258
  onClick: () => toggleExpand(node.value),
265
- children: expanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "size-4", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "size-4", "aria-hidden": "true" })
259
+ children: expanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "ui-tree-select-toggle-icon", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "ui-tree-select-toggle-icon", "aria-hidden": "true" })
266
260
  }
267
261
  ),
268
- checkable ? /* @__PURE__ */ jsxs("label", { className: "flex flex-1 cursor-pointer items-center gap-2", children: [
262
+ checkable ? /* @__PURE__ */ jsxs("label", { className: "ui-tree-select-label", children: [
269
263
  /* @__PURE__ */ jsx(
270
264
  Checkbox,
271
265
  {
@@ -52,7 +52,7 @@ function UploadCropDialog({ open, onOpenChange, file, onConfirm }) {
52
52
  onConfirm(cropped);
53
53
  onOpenChange(false);
54
54
  };
55
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-sm", children: [
55
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-[var(--upload-crop-dialog-max-width)]", children: [
56
56
  /* @__PURE__ */ jsxs(DialogHeader, { children: [
57
57
  /* @__PURE__ */ jsx(DialogTitle, { children: t("dataEntry.upload.cropTitle") }),
58
58
  /* @__PURE__ */ jsx(DialogDescription, { children: t("dataEntry.upload.cropDescription") })
@@ -62,7 +62,7 @@ function UploadCropDialog({ open, onOpenChange, file, onConfirm }) {
62
62
  "div",
63
63
  {
64
64
  className: cn(
65
- "bg-muted relative mx-auto size-48 overflow-hidden rounded-full border",
65
+ "bg-muted relative mx-auto size-[var(--upload-crop-preview-size)] overflow-hidden rounded-[var(--upload-crop-preview-radius)] border",
66
66
  "flex items-center justify-center"
67
67
  ),
68
68
  children: src ? /* @__PURE__ */ jsx(
@@ -71,13 +71,13 @@ function UploadCropDialog({ open, onOpenChange, file, onConfirm }) {
71
71
  ref: imgRef,
72
72
  src,
73
73
  alt: "",
74
- className: "size-full object-cover transition-transform duration-150",
74
+ className: "size-full object-cover transition-transform duration-[var(--duration-fast)]",
75
75
  style: { transform: `scale(${scale})` }
76
76
  }
77
77
  ) : null
78
78
  }
79
79
  ),
80
- /* @__PURE__ */ jsxs("div", { className: "ui-stack-xs px-2", children: [
80
+ /* @__PURE__ */ jsxs("div", { className: "ui-stack-xs px-[var(--upload-crop-zoom-space-inline)]", children: [
81
81
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs", children: t("dataEntry.upload.cropZoom") }),
82
82
  /* @__PURE__ */ jsx(
83
83
  Slider,
@@ -4,4 +4,4 @@ export type { UploadProp, UploadProp as UploadProps, UploadFileItemProp, UploadV
4
4
  export type { UploadFileItem, UploadVariant, UploadCommitAction } from "./upload-types.js";
5
5
  export { collectUploadCommitActions, createUploadItem } from "./upload-types.js";
6
6
  export { useUploadDraft } from "./use-upload-draft.js";
7
- export declare function Upload({ variant, triggerSize, value, defaultValue, onValueChange, accept: acceptProp, multiple: multipleProp, maxCount: maxCountProp, maxSizeBytes, disabled, removable, onUpload, id, className, children, ...ariaProps }: UploadProp): React.JSX.Element;
7
+ export declare function Upload({ variant, triggerSize, triggerVariant, value, defaultValue, onValueChange, accept: acceptProp, multiple: multipleProp, maxCount: maxCountProp, maxSizeBytes, disabled, removable, onUpload, id, className, children, ...ariaProps }: UploadProp): React.JSX.Element;
@@ -76,6 +76,7 @@ async function runUpload(file, item, onUpload, setItems) {
76
76
  function Upload({
77
77
  variant = "dropzone",
78
78
  triggerSize,
79
+ triggerVariant = "outline",
79
80
  value,
80
81
  defaultValue,
81
82
  onValueChange,
@@ -197,15 +198,13 @@ function Upload({
197
198
  setDragActive(false);
198
199
  pickFiles(e.dataTransfer.files);
199
200
  },
200
- className: cn(
201
- "cursor-pointer rounded-lg border-2 border-dashed p-10 text-center transition-colors",
202
- dragActive ? "border-primary bg-primary/5" : "border-border hover:border-primary/50",
203
- disabled && "pointer-events-none opacity-50"
204
- ),
201
+ "data-drag-active": dragActive ? "" : void 0,
202
+ "data-disabled": disabled ? "" : void 0,
203
+ className: "ui-upload-dropzone",
205
204
  children: [
206
- /* @__PURE__ */ jsx(UploadIcon, { className: "text-muted-foreground mx-auto size-10", "aria-hidden": "true" }),
207
- /* @__PURE__ */ jsx("p", { className: "mt-3 text-sm", children: t("dataEntry.upload.dropzoneHint") }),
208
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1 text-xs", children: t("dataEntry.upload.dropzoneMeta") })
205
+ /* @__PURE__ */ jsx(UploadIcon, { className: "ui-upload-dropzone-icon", "aria-hidden": "true" }),
206
+ /* @__PURE__ */ jsx("p", { className: "ui-upload-dropzone-hint", children: t("dataEntry.upload.dropzoneHint") }),
207
+ /* @__PURE__ */ jsx("p", { className: "ui-upload-dropzone-meta", children: t("dataEntry.upload.dropzoneMeta") })
209
208
  ]
210
209
  }
211
210
  ),
@@ -222,13 +221,20 @@ function Upload({
222
221
  Button,
223
222
  {
224
223
  type: "button",
225
- variant: "outline",
224
+ variant: triggerVariant,
226
225
  size: triggerSize,
227
226
  disabled,
228
227
  onClick: openPicker,
229
228
  "aria-label": iconOnly ? typeof label === "string" ? label : void 0 : void 0,
230
229
  children: [
231
- /* @__PURE__ */ jsx(UploadIcon, { className: iconOnly ? "size-4" : "me-2 size-4", "aria-hidden": "true" }),
230
+ /* @__PURE__ */ jsx(
231
+ UploadIcon,
232
+ {
233
+ className: "ui-upload-trigger-icon",
234
+ "data-with-label": iconOnly ? void 0 : "",
235
+ "aria-hidden": "true"
236
+ }
237
+ ),
232
238
  iconOnly ? null : label
233
239
  ]
234
240
  }
@@ -238,7 +244,7 @@ function Upload({
238
244
  }
239
245
  if (variant === "picture-card") {
240
246
  const canAdd = maxCount == null || items.length < maxCount;
241
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-wrap gap-3", className), children: [
247
+ return /* @__PURE__ */ jsxs("div", { className: cn("ui-upload-grid", className), children: [
242
248
  hiddenInput,
243
249
  liveRegion,
244
250
  items.map((item2) => /* @__PURE__ */ jsx(
@@ -255,15 +261,12 @@ function Upload({
255
261
  type: "button",
256
262
  disabled,
257
263
  onClick: openPicker,
258
- className: cn(
259
- "flex size-24 flex-col items-center justify-center rounded-md border border-dashed",
260
- "text-muted-foreground hover:border-primary hover:text-primary transition-colors",
261
- disabled && "pointer-events-none opacity-50"
262
- ),
264
+ "data-disabled": disabled ? "" : void 0,
265
+ className: "ui-upload-tile-add",
263
266
  "aria-label": t("dataEntry.upload.addImage"),
264
267
  children: [
265
- /* @__PURE__ */ jsx(ImagePlus, { className: "size-6", "aria-hidden": "true" }),
266
- /* @__PURE__ */ jsx("span", { className: "mt-1 text-xs", children: t("dataEntry.upload.addImage") })
268
+ /* @__PURE__ */ jsx(ImagePlus, { className: "ui-upload-tile-add-icon", "aria-hidden": "true" }),
269
+ /* @__PURE__ */ jsx("span", { className: "ui-upload-tile-add-label", children: t("dataEntry.upload.addImage") })
267
270
  ]
268
271
  }
269
272
  )
@@ -271,23 +274,23 @@ function Upload({
271
274
  }
272
275
  if (variant === "picture") {
273
276
  const item2 = draft.state.display;
274
- return /* @__PURE__ */ jsxs("div", { className: cn("ui-stack-sm max-w-xs", className), children: [
277
+ return /* @__PURE__ */ jsxs("div", { className: cn("ui-stack-sm ui-upload-picture", className), children: [
275
278
  hiddenInput,
276
279
  liveRegion,
277
- item2?.previewUrl && !item2.pendingDelete ? /* @__PURE__ */ jsxs("div", { className: "relative overflow-hidden rounded-md border", children: [
278
- /* @__PURE__ */ jsx("img", { src: item2.previewUrl, alt: "", className: "max-h-48 w-full object-cover" }),
279
- item2.status === "uploading" && /* @__PURE__ */ jsx("div", { className: "bg-background/70 absolute inset-0 flex items-center justify-center text-sm", children: t("dataEntry.upload.uploading") }),
280
- item2.pendingReplace && /* @__PURE__ */ jsx("div", { className: "bg-warning text-warning-foreground absolute start-2 top-2 rounded px-2 py-0.5 text-xs", children: t("dataEntry.upload.pendingReplace") })
280
+ item2?.previewUrl && !item2.pendingDelete ? /* @__PURE__ */ jsxs("div", { className: "ui-upload-picture-frame", children: [
281
+ /* @__PURE__ */ jsx("img", { src: item2.previewUrl, alt: "", className: "ui-upload-picture-img" }),
282
+ item2.status === "uploading" && /* @__PURE__ */ jsx("div", { className: "ui-upload-overlay ui-upload-picture-overlay", children: t("dataEntry.upload.uploading") }),
283
+ item2.pendingReplace && /* @__PURE__ */ jsx("div", { className: "ui-upload-picture-badge", children: t("dataEntry.upload.pendingReplace") })
281
284
  ] }) : /* @__PURE__ */ jsxs(
282
285
  "button",
283
286
  {
284
287
  type: "button",
285
288
  disabled,
286
289
  onClick: openPicker,
287
- className: "text-muted-foreground hover:border-primary flex h-32 w-full flex-col items-center justify-center rounded-md border border-dashed",
290
+ className: "ui-upload-picture-empty",
288
291
  children: [
289
292
  /* @__PURE__ */ jsx(ImagePlus, { className: controlIconClass, "aria-hidden": "true" }),
290
- /* @__PURE__ */ jsx("span", { className: "mt-2 text-sm", children: t("dataEntry.upload.addImage") })
293
+ /* @__PURE__ */ jsx("span", { className: "ui-upload-picture-empty-label", children: t("dataEntry.upload.addImage") })
291
294
  ]
292
295
  }
293
296
  ),
@@ -324,16 +327,13 @@ function Upload({
324
327
  type: "button",
325
328
  disabled,
326
329
  onClick: openPicker,
327
- className: cn(
328
- "border-border bg-muted relative size-24 overflow-hidden rounded-full border-2",
329
- "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none",
330
- item?.pendingDelete && "opacity-40",
331
- disabled && "pointer-events-none opacity-50"
332
- ),
330
+ "data-pending-delete": item?.pendingDelete ? "" : void 0,
331
+ "data-disabled": disabled ? "" : void 0,
332
+ className: "ui-upload-avatar ui-focus-ring",
333
333
  "aria-label": t("dataEntry.upload.avatarLabel"),
334
334
  children: [
335
- !showPlaceholder && item?.previewUrl ? /* @__PURE__ */ jsx("img", { src: item.previewUrl, alt: "", className: "size-full object-cover" }) : /* @__PURE__ */ jsx("span", { className: "text-muted-foreground flex size-full items-center justify-center", children: /* @__PURE__ */ jsx(Camera, { className: controlIconClass, "aria-hidden": "true" }) }),
336
- !disabled && /* @__PURE__ */ jsx("span", { className: "text-2xs absolute inset-x-0 bottom-0 bg-black/70 py-1 text-center text-white", children: t("dataEntry.upload.change") })
335
+ !showPlaceholder && item?.previewUrl ? /* @__PURE__ */ jsx("img", { src: item.previewUrl, alt: "", className: "ui-upload-avatar-image" }) : /* @__PURE__ */ jsx("span", { className: "ui-upload-avatar-placeholder", children: /* @__PURE__ */ jsx(Camera, { className: controlIconClass, "aria-hidden": "true" }) }),
336
+ !disabled && /* @__PURE__ */ jsx("span", { className: "ui-upload-avatar-change", children: t("dataEntry.upload.change") })
337
337
  ]
338
338
  }
339
339
  ),
@@ -343,9 +343,9 @@ function Upload({
343
343
  type: "button",
344
344
  disabled,
345
345
  onClick: () => draft.markRemove(),
346
- className: "bg-background hover:bg-destructive hover:text-destructive-foreground absolute -end-1 -top-1 rounded-full border p-1 shadow-sm",
346
+ className: "ui-upload-avatar-remove",
347
347
  "aria-label": t("dataEntry.upload.removeAvatar"),
348
- children: /* @__PURE__ */ jsx(Trash2, { className: "size-3.5", "aria-hidden": "true" })
348
+ children: /* @__PURE__ */ jsx(Trash2, { className: "ui-upload-remove-icon", "aria-hidden": "true" })
349
349
  }
350
350
  )
351
351
  ] }),
@@ -360,16 +360,16 @@ function UploadDraftActions({
360
360
  const { t } = useTranslation();
361
361
  const { state, undoRemove, undoReplace } = draft;
362
362
  if (state.canUndoRemove) {
363
- return /* @__PURE__ */ jsxs("div", { className: "border-destructive/40 bg-destructive/5 flex flex-wrap items-center gap-2 rounded-md border border-dashed px-3 py-2 text-sm", children: [
363
+ return /* @__PURE__ */ jsxs("div", { className: "ui-upload-draft-undo", children: [
364
364
  /* @__PURE__ */ jsx("span", { className: "text-destructive", children: t("dataEntry.upload.markedForDelete") }),
365
365
  /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", variant: "outline", disabled, onClick: undoRemove, children: [
366
- /* @__PURE__ */ jsx(RotateCcw, { className: "me-1 size-3.5", "aria-hidden": "true" }),
366
+ /* @__PURE__ */ jsx(RotateCcw, { className: "ui-upload-draft-icon", "aria-hidden": "true" }),
367
367
  t("dataEntry.upload.undo")
368
368
  ] })
369
369
  ] });
370
370
  }
371
371
  if (state.canUndoReplace) {
372
- return /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground flex flex-wrap items-center gap-2 text-sm", children: [
372
+ return /* @__PURE__ */ jsxs("div", { className: "ui-upload-draft-hint", children: [
373
373
  /* @__PURE__ */ jsx("span", { children: t("dataEntry.upload.pendingReplaceHint") }),
374
374
  /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", disabled, onClick: undoReplace, children: t("dataEntry.upload.undo") }),
375
375
  /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "outline", disabled, onClick: onPick, children: t("dataEntry.upload.change") })
@@ -379,17 +379,17 @@ function UploadDraftActions({
379
379
  }
380
380
  function UploadPictureCard({ item, onRemove }) {
381
381
  const { t } = useTranslation();
382
- return /* @__PURE__ */ jsxs("div", { className: "bg-muted relative size-24 overflow-hidden rounded-md border", children: [
383
- item.previewUrl ? /* @__PURE__ */ jsx("img", { src: item.previewUrl, alt: "", className: "size-full object-cover" }) : /* @__PURE__ */ jsx("div", { className: "text-muted-foreground flex size-full items-center justify-center text-xs", children: "\u2026" }),
384
- item.status === "uploading" && /* @__PURE__ */ jsx("div", { className: "bg-background/70 absolute inset-0 flex items-center justify-center text-xs", children: "\u2026" }),
382
+ return /* @__PURE__ */ jsxs("div", { className: "ui-upload-tile", children: [
383
+ item.previewUrl ? /* @__PURE__ */ jsx("img", { src: item.previewUrl, alt: "", className: "ui-upload-avatar-image" }) : /* @__PURE__ */ jsx("div", { className: "ui-upload-tile-placeholder", children: "\u2026" }),
384
+ item.status === "uploading" && /* @__PURE__ */ jsx("div", { className: "ui-upload-overlay", children: "\u2026" }),
385
385
  onRemove && /* @__PURE__ */ jsx(
386
386
  "button",
387
387
  {
388
388
  type: "button",
389
389
  onClick: onRemove,
390
- className: "bg-background/90 hover:bg-destructive hover:text-destructive-foreground absolute end-1 top-1 rounded-full p-0.5 shadow",
390
+ className: "ui-upload-tile-remove",
391
391
  "aria-label": t("dataEntry.upload.removeImage"),
392
- children: /* @__PURE__ */ jsx(X, { className: "size-3.5", "aria-hidden": "true" })
392
+ children: /* @__PURE__ */ jsx(X, { className: "ui-upload-remove-icon", "aria-hidden": "true" })
393
393
  }
394
394
  )
395
395
  ] });
@@ -399,8 +399,8 @@ function UploadFileList({
399
399
  onRemove
400
400
  }) {
401
401
  const { t } = useTranslation();
402
- return /* @__PURE__ */ jsx("ul", { className: "ui-stack-xs", children: items.map((item) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-3 rounded-md border px-3 py-2 text-sm", children: [
403
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
402
+ return /* @__PURE__ */ jsx("ul", { className: "ui-stack-xs", children: items.map((item) => /* @__PURE__ */ jsxs("li", { className: "ui-upload-row", children: [
403
+ /* @__PURE__ */ jsxs("div", { className: "ui-upload-row-main", children: [
404
404
  /* @__PURE__ */ jsx("div", { className: "truncate font-medium", children: item.name }),
405
405
  /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground text-xs", children: [
406
406
  formatBytes(item.size),
@@ -424,7 +424,7 @@ function UploadFileList({
424
424
  variant: "ghost",
425
425
  "aria-label": t("dataEntry.upload.removeFile", { name: item.name }),
426
426
  onClick: () => onRemove(item.uid),
427
- children: /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" })
427
+ children: /* @__PURE__ */ jsx(X, { className: "ui-upload-row-icon", "aria-hidden": "true" })
428
428
  }
429
429
  )
430
430
  ] }, item.uid)) });
@@ -12,7 +12,6 @@ import {
12
12
  } from "lucide-react";
13
13
  import { useTranslation } from "../../i18n/use-translation.js";
14
14
  import { humanError } from "../../lib/format.js";
15
- import { cn } from "../../lib/utils.js";
16
15
  import { Flex } from "../layout/flex.js";
17
16
  import { Button } from "../general/button.js";
18
17
  const AlertContext = React.createContext("default");
@@ -52,9 +51,9 @@ const AlertBase = React.forwardRef(
52
51
  void onDismiss();
53
52
  },
54
53
  "data-slot": "alert-dismiss",
55
- className: "ring-offset-background focus-visible:ring-ring transition-opacity hover:opacity-100 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none",
54
+ className: "ui-focus-ring",
56
55
  "aria-label": t("feedback.alert.dismiss"),
57
- children: /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" })
56
+ children: /* @__PURE__ */ jsx(X, { className: "ui-alert-dismiss-icon", "aria-hidden": "true" })
58
57
  }
59
58
  )
60
59
  ]
@@ -71,15 +70,9 @@ const AlertTitle = React.forwardRef(
71
70
  );
72
71
  AlertTitle.displayName = "AlertTitle";
73
72
  const AlertContent = React.forwardRef(
74
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
75
- "div",
76
- {
77
- ref,
78
- "data-slot": "alert-content",
79
- className: cn("min-w-0 flex-1", className),
80
- ...props
81
- }
82
- )
73
+ // `min-w-0 flex-1` moved to alert-layout.css [data-slot="alert-content"] same box, but a
74
+ // consumer className now overrides it from the utilities layer instead of tying with it.
75
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, "data-slot": "alert-content", className, ...props })
83
76
  );
84
77
  AlertContent.displayName = "AlertContent";
85
78
  const AlertDescription = React.forwardRef(
@@ -110,7 +103,7 @@ function RetryButton({ onRetry }) {
110
103
  void onRetry();
111
104
  },
112
105
  children: /* @__PURE__ */ jsxs(Flex, { direction: "row", wrap: true, align: "center", gap: "xs", children: [
113
- /* @__PURE__ */ jsx(RefreshCw, { className: "size-4", "aria-hidden": "true" }),
106
+ /* @__PURE__ */ jsx(RefreshCw, { "aria-hidden": "true" }),
114
107
  t("common.retry")
115
108
  ] })
116
109
  }
@@ -144,7 +137,7 @@ function AlertQueryError({
144
137
  void onAuthAction();
145
138
  },
146
139
  children: /* @__PURE__ */ jsxs(Flex, { direction: "row", wrap: true, align: "center", gap: "xs", children: [
147
- /* @__PURE__ */ jsx(LogIn, { className: "size-4", "aria-hidden": "true" }),
140
+ /* @__PURE__ */ jsx(LogIn, { "aria-hidden": "true" }),
148
141
  t("query.error.action.signIn")
149
142
  ] })
150
143
  }
@@ -21,18 +21,18 @@ interface DialogHeaderProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "
21
21
  extra?: React.ReactNode;
22
22
  tone?: ToneProp;
23
23
  }
24
- declare const DialogHeader: {
25
- ({ className, title, subtitle, extra, tone, children, ...props }: DialogHeaderProps): React.JSX.Element;
26
- displayName: string;
27
- };
28
- declare const DialogBody: {
29
- ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
30
- displayName: string;
31
- };
32
- declare const DialogFooter: {
33
- ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
34
- displayName: string;
35
- };
24
+ declare function DialogHeader({ className, title, subtitle, extra, tone, children, ...props }: DialogHeaderProps): React.JSX.Element;
25
+ declare namespace DialogHeader {
26
+ var displayName: string;
27
+ }
28
+ declare function DialogBody({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
29
+ declare namespace DialogBody {
30
+ var displayName: string;
31
+ }
32
+ declare function DialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
33
+ declare namespace DialogFooter {
34
+ var displayName: string;
35
+ }
36
36
  declare const DialogTitle: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
37
37
  declare const DialogDescription: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
38
38
  type AlertDialogRootProps = React.ComponentProps<typeof AlertDialogPrimitive.Root> & {};
@@ -55,14 +55,14 @@ declare const AlertDialogContent: React.ForwardRefExoticComponent<Omit<AlertDial
55
55
  showClose?: boolean;
56
56
  showCloseButton?: boolean;
57
57
  } & React.RefAttributes<HTMLDivElement>>;
58
- declare const AlertDialogHeader: {
59
- ({ className, title, subtitle, extra, tone, children, ...props }: DialogHeaderProps): React.JSX.Element;
60
- displayName: string;
61
- };
62
- declare const AlertDialogFooter: {
63
- ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
64
- displayName: string;
65
- };
58
+ declare function AlertDialogHeader({ className, title, subtitle, extra, tone, children, ...props }: DialogHeaderProps): React.JSX.Element;
59
+ declare namespace AlertDialogHeader {
60
+ var displayName: string;
61
+ }
62
+ declare function AlertDialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
63
+ declare namespace AlertDialogFooter {
64
+ var displayName: string;
65
+ }
66
66
  declare const AlertDialogTitle: React.ForwardRefExoticComponent<Omit<AlertDialogPrimitive.AlertDialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
67
67
  declare const AlertDialogDescription: React.ForwardRefExoticComponent<Omit<AlertDialogPrimitive.AlertDialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
68
68
  /** Confirm mode — primary action (maps to Radix AlertDialogAction). */
@@ -89,18 +89,9 @@ export declare const Dialog: typeof DialogRoot & {
89
89
  showCloseButton?: boolean;
90
90
  overlayClassName?: string;
91
91
  } & React.RefAttributes<HTMLDivElement>>;
92
- Header: {
93
- ({ className, title, subtitle, extra, tone, children, ...props }: DialogHeaderProps): React.JSX.Element;
94
- displayName: string;
95
- };
96
- Body: {
97
- ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
98
- displayName: string;
99
- };
100
- Footer: {
101
- ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
102
- displayName: string;
103
- };
92
+ Header: typeof DialogHeader;
93
+ Body: typeof DialogBody;
94
+ Footer: typeof DialogFooter;
104
95
  Title: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
105
96
  Description: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
106
97
  Close: typeof DialogClose;
@@ -65,9 +65,9 @@ const DialogContent = React.forwardRef(
65
65
  DialogPrimitive.Close,
66
66
  {
67
67
  "data-slot": "dialog-close",
68
- className: "ring-offset-background focus:ring-ring transition-opacity focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none",
68
+ className: "ui-focus-ring transition-opacity focus:outline-hidden disabled:pointer-events-none",
69
69
  children: [
70
- /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" }),
70
+ /* @__PURE__ */ jsx(X, { className: "ui-dialog-close-icon", "aria-hidden": "true" }),
71
71
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("feedback.alert.dismiss") })
72
72
  ]
73
73
  }
@@ -95,12 +95,14 @@ const DialogHeader = ({
95
95
  "data-tone": tone,
96
96
  className: cn(overlayHeaderToneClass[tone], className),
97
97
  ...props,
98
- children: children ?? /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-[var(--space-3)] pe-[var(--space-8)]", children: [
99
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
98
+ children: children ?? // Chrome rhythm lives in dialog-layout.css (`.ui-dialog-*`, mirroring `.ui-sheet-*`), so
99
+ // the two overlay siblings retune from one --dialog-*/--sheet-* set instead of literals.
100
+ /* @__PURE__ */ jsxs("div", { className: "ui-dialog-title-row", children: [
101
+ /* @__PURE__ */ jsxs("div", { className: "ui-dialog-title-block", children: [
100
102
  title != null && /* @__PURE__ */ jsx(DialogTitle, { children: title }),
101
103
  subtitle != null && /* @__PURE__ */ jsx(DialogDescription, { children: subtitle })
102
104
  ] }),
103
- extra != null && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-[var(--space-2)] whitespace-nowrap", children: extra })
105
+ extra != null && /* @__PURE__ */ jsx("div", { className: "ui-dialog-extra", children: extra })
104
106
  ] })
105
107
  }
106
108
  );
@@ -169,9 +171,10 @@ const AlertDialogContent = React.forwardRef(({ className, children, showClose, s
169
171
  "button",
170
172
  {
171
173
  type: "button",
172
- className: "ring-offset-background focus:ring-ring transition-opacity focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none",
174
+ "data-slot": "dialog-close",
175
+ className: "ui-focus-ring transition-opacity focus:outline-hidden disabled:pointer-events-none",
173
176
  "aria-label": t("feedback.alert.dismiss"),
174
- children: /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" })
177
+ children: /* @__PURE__ */ jsx(X, { className: "ui-dialog-close-icon", "aria-hidden": "true" })
175
178
  }
176
179
  ) }) : null
177
180
  ]
@@ -195,12 +198,12 @@ const AlertDialogHeader = ({
195
198
  "data-tone": tone,
196
199
  className: cn(overlayHeaderToneClass[tone], className),
197
200
  ...props,
198
- children: children ?? /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-[var(--space-3)] pe-[var(--space-8)]", children: [
199
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
201
+ children: children ?? /* @__PURE__ */ jsxs("div", { className: "ui-dialog-title-row", children: [
202
+ /* @__PURE__ */ jsxs("div", { className: "ui-dialog-title-block", children: [
200
203
  title != null && /* @__PURE__ */ jsx(AlertDialogTitle, { children: title }),
201
204
  subtitle != null && /* @__PURE__ */ jsx(AlertDialogDescription, { children: subtitle })
202
205
  ] }),
203
- extra != null && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-[var(--space-2)] whitespace-nowrap", children: extra })
206
+ extra != null && /* @__PURE__ */ jsx("div", { className: "ui-dialog-extra", children: extra })
204
207
  ] })
205
208
  }
206
209
  );
@@ -289,7 +292,7 @@ function AlertDialog({
289
292
  if (stepUp) {
290
293
  setStepUpFailed(false);
291
294
  setVerifying(true);
292
- let ok = false;
295
+ let ok;
293
296
  try {
294
297
  ok = await stepUp();
295
298
  } catch {
@@ -324,7 +327,7 @@ function AlertDialog({
324
327
  description ? /* @__PURE__ */ jsx(AlertDialogPrimitive.Description, { "data-slot": "dialog-description", children: description }) : null
325
328
  ] }),
326
329
  needsPhrase && /* @__PURE__ */ jsxs("div", { className: "ui-stack-xs", children: [
327
- /* @__PURE__ */ jsx(Label, { htmlFor: inputId, className: "text-sm", children: t("common.typeToConfirm", { phrase }) }),
330
+ /* @__PURE__ */ jsx(Label, { htmlFor: inputId, children: t("common.typeToConfirm", { phrase }) }),
328
331
  /* @__PURE__ */ jsx(
329
332
  Input,
330
333
  {
@@ -341,7 +344,7 @@ function AlertDialog({
341
344
  }
342
345
  )
343
346
  ] }),
344
- stepUpFailed && /* @__PURE__ */ jsx("p", { id: stepErrorId, role: "alert", className: "text-destructive text-sm", children: t("feedback.alert.stepUpFailed") }),
347
+ stepUpFailed && /* @__PURE__ */ jsx("p", { id: stepErrorId, role: "alert", className: "ui-dialog-step-up-error", children: t("feedback.alert.stepUpFailed") }),
345
348
  /* @__PURE__ */ jsxs(DialogFooter, { children: [
346
349
  /* @__PURE__ */ jsx(DialogCancel, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "ghost", disabled: busy, children: resolvedCancel }) }),
347
350
  /* @__PURE__ */ jsx(
@@ -21,7 +21,7 @@ export declare function SheetClose(props: React.ComponentProps<typeof DialogPrim
21
21
  export declare function SheetPortal(props: React.ComponentProps<typeof DialogPrimitive.Portal>): React.JSX.Element;
22
22
  export declare const SheetOverlay: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
23
23
  declare const sheetVariants: (props?: ({
24
- side?: "left" | "right" | "bottom" | "top" | null | undefined;
24
+ side?: "bottom" | "left" | "right" | "top" | null | undefined;
25
25
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
26
26
  export interface SheetContentProps extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>, VariantProps<typeof sheetVariants> {
27
27
  showCloseButton?: boolean;