@godxjp/ui 18.15.4 → 19.1.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 (154) hide show
  1. package/dist/app/app-provider.d.ts +1 -1
  2. package/dist/app/app-provider.js +3 -0
  3. package/dist/app/date-format-labels.d.ts +1 -1
  4. package/dist/app/time-format-labels.d.ts +1 -1
  5. package/dist/components/data-display/badge.d.ts +1 -1
  6. package/dist/components/data-display/card.d.ts +4 -13
  7. package/dist/components/data-display/card.js +2 -15
  8. package/dist/components/data-display/data-table.d.ts +3 -8
  9. package/dist/components/data-display/data-table.js +106 -68
  10. package/dist/components/data-display/descriptions.js +34 -5
  11. package/dist/components/data-display/empty-state.js +1 -1
  12. package/dist/components/data-display/permission-matrix.js +7 -7
  13. package/dist/components/data-display/popover.js +2 -9
  14. package/dist/components/data-display/qr-code.d.ts +1 -1
  15. package/dist/components/data-display/scroll-area.d.ts +3 -1
  16. package/dist/components/data-display/scroll-area.js +150 -16
  17. package/dist/components/data-display/table.js +12 -3
  18. package/dist/components/data-entry/branch-scope-picker.js +4 -4
  19. package/dist/components/data-entry/calendar.js +15 -24
  20. package/dist/components/data-entry/cascader.js +70 -72
  21. package/dist/components/data-entry/checkbox-group.js +12 -5
  22. package/dist/components/data-entry/checkbox.js +30 -13
  23. package/dist/components/data-entry/command.d.ts +6 -6
  24. package/dist/components/data-entry/date-picker.js +34 -17
  25. package/dist/components/data-entry/date-range-picker.js +19 -13
  26. package/dist/components/data-entry/form-field.d.ts +1 -1
  27. package/dist/components/data-entry/form-field.js +22 -5
  28. package/dist/components/data-entry/index.d.ts +2 -1
  29. package/dist/components/data-entry/input.js +18 -22
  30. package/dist/components/data-entry/label.js +4 -2
  31. package/dist/components/data-entry/month-picker.js +20 -17
  32. package/dist/components/data-entry/month-range-picker.js +26 -19
  33. package/dist/components/data-entry/radio.js +25 -6
  34. package/dist/components/data-entry/search-select.d.ts +1 -1
  35. package/dist/components/data-entry/search-select.js +37 -31
  36. package/dist/components/data-entry/select.d.ts +8 -0
  37. package/dist/components/data-entry/select.js +68 -26
  38. package/dist/components/data-entry/switch.js +16 -2
  39. package/dist/components/data-entry/textarea.d.ts +56 -0
  40. package/dist/components/data-entry/textarea.js +110 -40
  41. package/dist/components/data-entry/time-picker.js +52 -52
  42. package/dist/components/data-entry/toggle-group.d.ts +1 -0
  43. package/dist/components/data-entry/toggle.d.ts +1 -1
  44. package/dist/components/data-entry/transfer.js +14 -15
  45. package/dist/components/data-entry/tree-select.js +19 -23
  46. package/dist/components/data-entry/upload-crop-dialog.js +4 -4
  47. package/dist/components/data-entry/upload.d.ts +1 -1
  48. package/dist/components/data-entry/upload.js +46 -46
  49. package/dist/components/feedback/alert.js +7 -14
  50. package/dist/components/feedback/dialog.d.ts +23 -32
  51. package/dist/components/feedback/dialog.js +16 -13
  52. package/dist/components/feedback/sheet.d.ts +1 -1
  53. package/dist/components/feedback/sheet.js +14 -14
  54. package/dist/components/feedback/skeleton.js +13 -10
  55. package/dist/components/feedback/sonner.d.ts +1 -1
  56. package/dist/components/feedback/sonner.js +17 -8
  57. package/dist/components/feedback/tooltip.js +1 -1
  58. package/dist/components/general/activity.d.ts +44 -0
  59. package/dist/components/general/activity.js +65 -0
  60. package/dist/components/general/button.d.ts +2 -2
  61. package/dist/components/general/button.js +11 -24
  62. package/dist/components/general/index.d.ts +2 -0
  63. package/dist/components/general/index.js +2 -0
  64. package/dist/components/layout/app-shell.js +5 -3
  65. package/dist/components/layout/auth-divider.d.ts +9 -2
  66. package/dist/components/layout/auth-divider.js +7 -11
  67. package/dist/components/layout/index.d.ts +1 -0
  68. package/dist/components/layout/page-container.d.ts +1 -1
  69. package/dist/components/layout/page-container.js +32 -20
  70. package/dist/components/layout/resizable.d.ts +12 -12
  71. package/dist/components/layout/separator.d.ts +1 -0
  72. package/dist/components/layout/service-role-panel.js +47 -42
  73. package/dist/components/layout/sidebar.js +13 -1
  74. package/dist/components/layout/split-pane.d.ts +12 -1
  75. package/dist/components/layout/split-pane.js +13 -4
  76. package/dist/components/navigation/app-setting-picker.js +5 -14
  77. package/dist/components/navigation/dropdown-menu.js +10 -16
  78. package/dist/components/navigation/menubar.d.ts +3 -6
  79. package/dist/components/navigation/pagination-utils.d.ts +15 -2
  80. package/dist/components/navigation/pagination-utils.js +27 -21
  81. package/dist/components/navigation/pagination.d.ts +4 -4
  82. package/dist/components/navigation/pagination.js +2 -2
  83. package/dist/components/navigation/steps.js +31 -67
  84. package/dist/components/navigation/tabs.js +17 -5
  85. package/dist/components/query/infinite-query-state.js +2 -2
  86. package/dist/components/ui/accordion.d.ts +1 -1
  87. package/dist/components/ui/avatar.d.ts +1 -1
  88. package/dist/components/ui/avatar.js +29 -10
  89. package/dist/components/ui/input-otp.d.ts +8 -6
  90. package/dist/components/ui/rating.js +1 -1
  91. package/dist/components/ui/separator.d.ts +27 -2
  92. package/dist/components/ui/separator.js +42 -11
  93. package/dist/components/ui/toggle-group.d.ts +15 -5
  94. package/dist/components/ui/toggle-group.js +43 -18
  95. package/dist/components/ui/toggle.d.ts +66 -5
  96. package/dist/components/ui/toggle.js +64 -9
  97. package/dist/i18n/messages/en.json +8 -0
  98. package/dist/i18n/messages/ja.json +8 -0
  99. package/dist/i18n/messages/vi.json +8 -0
  100. package/dist/lib/control-styles.d.ts +14 -0
  101. package/dist/lib/control-styles.js +2 -0
  102. package/dist/lib/field-a11y.d.ts +52 -0
  103. package/dist/lib/field-a11y.js +17 -2
  104. package/dist/props/components/app.prop.d.ts +15 -0
  105. package/dist/props/components/data-display.prop.d.ts +85 -3
  106. package/dist/props/components/data-entry.prop.d.ts +35 -2
  107. package/dist/props/components/general.prop.d.ts +52 -1
  108. package/dist/props/components/layout.prop.d.ts +137 -2
  109. package/dist/props/registry.d.ts +116 -5
  110. package/dist/props/registry.js +165 -4
  111. package/dist/props/vocabulary/index.d.ts +2 -2
  112. package/dist/props/vocabulary/interaction.prop.d.ts +15 -0
  113. package/dist/props/vocabulary/layout.prop.d.ts +8 -0
  114. package/dist/styles/alert-layout.css +69 -3
  115. package/dist/styles/badge-layout.css +2 -2
  116. package/dist/styles/base.css +6 -0
  117. package/dist/styles/card-layout.css +25 -8
  118. package/dist/styles/control.css +1150 -29
  119. package/dist/styles/data-display-layout.css +185 -11
  120. package/dist/styles/data-entry-layout.css +352 -1
  121. package/dist/styles/density.css +2 -2
  122. package/dist/styles/dialog-layout.css +203 -4
  123. package/dist/styles/focus-ring.css +155 -0
  124. package/dist/styles/form-layout.css +50 -5
  125. package/dist/styles/index.css +1 -0
  126. package/dist/styles/layout.css +412 -23
  127. package/dist/styles/motion.css +178 -0
  128. package/dist/styles/navigation-layout.css +398 -22
  129. package/dist/styles/shell-layout.css +137 -39
  130. package/dist/styles/table-layout.css +153 -22
  131. package/dist/styles/toggle.css +59 -0
  132. package/dist/tokens/base.css +5 -0
  133. package/dist/tokens/components/activity.css +64 -0
  134. package/dist/tokens/components/badge.css +7 -0
  135. package/dist/tokens/components/card.css +14 -10
  136. package/dist/tokens/components/chart.css +1 -1
  137. package/dist/tokens/components/control.css +358 -8
  138. package/dist/tokens/components/data-display.css +75 -0
  139. package/dist/tokens/components/data-entry.css +25 -0
  140. package/dist/tokens/components/descriptions.css +22 -0
  141. package/dist/tokens/components/feedback.css +143 -4
  142. package/dist/tokens/components/form.css +16 -0
  143. package/dist/tokens/components/legal-document.css +5 -1
  144. package/dist/tokens/components/navigation.css +109 -0
  145. package/dist/tokens/components/scroll-area.css +21 -0
  146. package/dist/tokens/components/separator.css +52 -0
  147. package/dist/tokens/components/shell.css +132 -20
  148. package/dist/tokens/components/table.css +52 -3
  149. package/dist/tokens/components/toggle.css +82 -0
  150. package/dist/tokens/components/upload.css +107 -0
  151. package/dist/tokens/foundation.css +171 -10
  152. package/dist/tokens/semantic/layout.css +120 -1
  153. package/package.json +85 -68
  154. package/scripts/ui-audit.mjs +51 -2
@@ -29,7 +29,7 @@ const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...pr
29
29
  "data-slot": "dropdown-menu-content",
30
30
  sideOffset,
31
31
  className: cn(
32
- "bg-popover text-popover-foreground data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-32 origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
32
+ "ui-dropdown-menu-content data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 origin-[var(--radix-dropdown-menu-content-transform-origin)]",
33
33
  className
34
34
  ),
35
35
  ...props
@@ -44,7 +44,7 @@ const DropdownMenuItem = React.forwardRef(({ className, inset, variant = "defaul
44
44
  "data-inset": inset,
45
45
  "data-variant": variant,
46
46
  className: cn(
47
- "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset=true]:ps-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
47
+ "ui-dropdown-menu-item [&_svg:not([class*='text-'])]:text-muted-foreground",
48
48
  className
49
49
  ),
50
50
  ...props
@@ -57,7 +57,7 @@ const DropdownMenuLabel = React.forwardRef(({ className, inset, ...props }, ref)
57
57
  ref,
58
58
  "data-slot": "dropdown-menu-label",
59
59
  "data-inset": inset,
60
- className: cn("px-2 py-1.5 text-sm font-medium data-[inset=true]:ps-8", className),
60
+ className: cn("ui-dropdown-menu-label", className),
61
61
  ...props
62
62
  }
63
63
  ));
@@ -67,7 +67,7 @@ const DropdownMenuSeparator = React.forwardRef(({ className, ...props }, ref) =>
67
67
  {
68
68
  ref,
69
69
  "data-slot": "dropdown-menu-separator",
70
- className: cn("bg-border -mx-1 my-1 h-px", className),
70
+ className: cn("ui-dropdown-menu-separator", className),
71
71
  ...props
72
72
  }
73
73
  ));
@@ -77,14 +77,11 @@ const DropdownMenuCheckboxItem = React.forwardRef(({ className, children, checke
77
77
  {
78
78
  ref,
79
79
  "data-slot": "dropdown-menu-checkbox-item",
80
- className: cn(
81
- "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 ps-8 pe-2 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
82
- className
83
- ),
80
+ className: cn("ui-dropdown-menu-checkbox-item", className),
84
81
  checked,
85
82
  ...props,
86
83
  children: [
87
- /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute start-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "size-4", "aria-hidden": "true" }) }) }),
84
+ /* @__PURE__ */ jsx("span", { className: "ui-dropdown-menu-indicator-slot", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "ui-dropdown-menu-check", "aria-hidden": "true" }) }) }),
88
85
  children
89
86
  ]
90
87
  }
@@ -95,10 +92,7 @@ const DropdownMenuRadioItem = React.forwardRef(({ className, children, ...props
95
92
  {
96
93
  ref,
97
94
  "data-slot": "dropdown-menu-radio-item",
98
- className: cn(
99
- "focus:bg-accent focus:text-accent-foreground data-[state=checked]:bg-primary/10 data-[state=checked]:text-primary relative flex cursor-default items-center gap-2 rounded-sm px-2.5 py-1.5 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[state=checked]:font-medium [&_svg]:pointer-events-none [&_svg]:shrink-0",
100
- className
101
- ),
95
+ className: cn("ui-dropdown-menu-radio-item", className),
102
96
  ...props,
103
97
  children
104
98
  }
@@ -111,13 +105,13 @@ const DropdownMenuSubTrigger = React.forwardRef(({ className, inset, children, .
111
105
  "data-slot": "dropdown-menu-sub-trigger",
112
106
  "data-inset": inset,
113
107
  className: cn(
114
- "focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none select-none data-[inset=true]:ps-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
108
+ "ui-dropdown-menu-sub-trigger [&_svg:not([class*='text-'])]:text-muted-foreground",
115
109
  className
116
110
  ),
117
111
  ...props,
118
112
  children: [
119
113
  children,
120
- /* @__PURE__ */ jsx(ChevronRight, { className: "ms-auto size-4", "aria-hidden": "true" })
114
+ /* @__PURE__ */ jsx(ChevronRight, { className: "ui-dropdown-menu-sub-trigger-icon", "aria-hidden": "true" })
121
115
  ]
122
116
  }
123
117
  ));
@@ -128,7 +122,7 @@ const DropdownMenuSubContent = React.forwardRef(({ className, ...props }, ref) =
128
122
  ref,
129
123
  "data-slot": "dropdown-menu-sub-content",
130
124
  className: cn(
131
- "bg-popover text-popover-foreground data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 z-50 min-w-32 origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-hidden rounded-md border p-1 shadow-lg",
125
+ "ui-dropdown-menu-sub-content data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 origin-[var(--radix-dropdown-menu-content-transform-origin)]",
132
126
  className
133
127
  ),
134
128
  ...props
@@ -1,12 +1,9 @@
1
1
  import * as React from "react";
2
2
  import * as MenubarPrimitive from "@radix-ui/react-menubar";
3
3
  export declare const Menubar: React.ForwardRefExoticComponent<MenubarPrimitive.MenubarProps & React.RefAttributes<HTMLDivElement>>;
4
- export declare const MenubarMenu: {
5
- (props: MenubarPrimitive.MenubarMenuProps & {
6
- __scopeMenubar?: import("@radix-ui/react-context").Scope;
7
- }): React.JSX.Element;
8
- displayName: string;
9
- };
4
+ export declare const MenubarMenu: (props: MenubarPrimitive.MenubarMenuProps & {
5
+ __scopeMenubar?: import("@radix-ui/react-context").Scope;
6
+ }) => React.JSX.Element;
10
7
  export declare function MenubarTrigger(props: React.ComponentProps<typeof MenubarPrimitive.Trigger>): React.JSX.Element;
11
8
  export declare const MenubarContent: React.ForwardRefExoticComponent<Omit<MenubarPrimitive.MenubarContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
12
9
  export declare const MenubarItem: React.ForwardRefExoticComponent<Omit<MenubarPrimitive.MenubarItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
@@ -1,2 +1,15 @@
1
- /** Build visible page numbers with ellipsis — Ant Design pagination style. */
2
- export declare function buildPageRange(current: number, totalPages: number, siblingCount?: number): (number | "ellipsis")[];
1
+ /**
2
+ * Build visible page numbers with ellipsis Ant Design / MUI pagination style.
3
+ *
4
+ * The item count is CONSTANT wherever the current page sits. The earlier version
5
+ * derived the window straight from `current ± siblingCount` and let it collapse
6
+ * against the edges, so a 1,060-page list opened as `1 2 … 1060` — four controls
7
+ * with a wide empty gap, and both a bad target size and a bad sense of scale
8
+ * (reported 2026-08-24). Ant Design and MUI both solve this by CLAMPING the
9
+ * window instead of shrinking it: near an edge the window slides inward so the
10
+ * strip keeps its full width. Same list now opens as `1 2 3 4 5 … 1060`.
11
+ *
12
+ * Slots = `boundaryCount * 2` edges + `siblingCount * 2 + 1` around current + 2
13
+ * ellipsis positions. With the defaults that is 7 controls.
14
+ */
15
+ export declare function buildPageRange(current: number, totalPages: number, siblingCount?: number, boundaryCount?: number): (number | "ellipsis")[];
@@ -1,24 +1,30 @@
1
- function buildPageRange(current, totalPages, siblingCount = 1) {
2
- if (totalPages <= 1) return totalPages === 1 ? [1] : [];
3
- const totalNumbers = siblingCount * 2 + 5;
4
- if (totalPages <= totalNumbers) {
5
- return Array.from({ length: totalPages }, (_, i) => i + 1);
6
- }
7
- const left = Math.max(current - siblingCount, 1);
8
- const right = Math.min(current + siblingCount, totalPages);
9
- const showLeftEllipsis = left > 2;
10
- const showRightEllipsis = right < totalPages - 1;
11
- const range = [];
12
- range.push(1);
13
- if (showLeftEllipsis) range.push("ellipsis");
14
- else for (let i = 2; i < left; i++) range.push(i);
15
- for (let i = left; i <= right; i++) {
16
- if (i !== 1 && i !== totalPages) range.push(i);
17
- }
18
- if (showRightEllipsis) range.push("ellipsis");
19
- else for (let i = right + 1; i < totalPages; i++) range.push(i);
20
- if (totalPages > 1) range.push(totalPages);
21
- return range;
1
+ function range(start, end) {
2
+ return end < start ? [] : Array.from({ length: end - start + 1 }, (_, i) => start + i);
3
+ }
4
+ function buildPageRange(current, totalPages, siblingCount = 1, boundaryCount = 1) {
5
+ if (totalPages <= 0) return [];
6
+ if (totalPages === 1) return [1];
7
+ const totalNumbers = boundaryCount * 2 + siblingCount * 2 + 3;
8
+ if (totalPages <= totalNumbers) return range(1, totalPages);
9
+ const startPages = range(1, Math.min(boundaryCount, totalPages));
10
+ const endPages = range(Math.max(totalPages - boundaryCount + 1, boundaryCount + 1), totalPages);
11
+ const siblingsStart = Math.max(
12
+ Math.min(current - siblingCount, totalPages - boundaryCount - siblingCount * 2 - 1),
13
+ boundaryCount + 2
14
+ );
15
+ const siblingsEnd = Math.min(
16
+ Math.max(current + siblingCount, boundaryCount + siblingCount * 2 + 2),
17
+ endPages.length > 0 ? endPages[0] - 2 : totalPages - 1
18
+ );
19
+ return [
20
+ ...startPages,
21
+ // An ellipsis that would hide exactly ONE page is pointless — spell that page out
22
+ // instead (Ant/MUI do the same), which is also what keeps the count constant.
23
+ ...siblingsStart > boundaryCount + 2 ? ["ellipsis"] : boundaryCount + 1 < totalPages - boundaryCount ? [boundaryCount + 1] : [],
24
+ ...range(siblingsStart, siblingsEnd),
25
+ ...siblingsEnd < totalPages - boundaryCount - 1 ? ["ellipsis"] : totalPages - boundaryCount > boundaryCount ? [totalPages - boundaryCount] : [],
26
+ ...endPages
27
+ ];
22
28
  }
23
29
  export {
24
30
  buildPageRange
@@ -8,10 +8,10 @@ declare const PaginationLink: React.ForwardRefExoticComponent<Omit<Omit<React.De
8
8
  disabled?: boolean;
9
9
  href?: string;
10
10
  } & React.RefAttributes<HTMLButtonElement>>;
11
- declare const PaginationEllipsis: {
12
- ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>): React.JSX.Element;
13
- displayName: string;
14
- };
11
+ declare function PaginationEllipsis({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>): React.JSX.Element;
12
+ declare namespace PaginationEllipsis {
13
+ var displayName: string;
14
+ }
15
15
  declare const PaginationPrevious: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref">, "type"> & {
16
16
  isActive?: boolean;
17
17
  disabled?: boolean;
@@ -142,7 +142,7 @@ function Pagination({
142
142
  disabled: Boolean(disabled) || safeCurrent <= 1,
143
143
  "aria-label": t("navigation.pagination.prev"),
144
144
  onClick: () => go(safeCurrent - 1),
145
- children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4", "aria-hidden": "true" })
145
+ children: /* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": "true" })
146
146
  }
147
147
  ),
148
148
  /* @__PURE__ */ jsxs("span", { className: "ui-pagination-count", children: [
@@ -159,7 +159,7 @@ function Pagination({
159
159
  disabled: Boolean(disabled) || safeCurrent >= totalPages,
160
160
  "aria-label": t("navigation.pagination.next"),
161
161
  onClick: () => go(safeCurrent + 1),
162
- children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4", "aria-hidden": "true" })
162
+ children: /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true" })
163
163
  }
164
164
  )
165
165
  ] });
@@ -18,36 +18,18 @@ function StepIcon({
18
18
  if (icon)
19
19
  return /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", controlIconClass), children: icon });
20
20
  if (type === "dot") {
21
- return /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", controlIconClass), children: /* @__PURE__ */ jsx(
22
- "span",
23
- {
24
- className: cn(
25
- "block size-2.5 rounded-full",
26
- status === "finish" && "bg-primary",
27
- status === "process" && "bg-primary ring-primary/20 ring-4",
28
- status === "error" && "bg-destructive",
29
- status === "wait" && "bg-muted-foreground/30"
30
- )
31
- }
32
- ) });
21
+ return /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", controlIconClass), children: /* @__PURE__ */ jsx("span", { className: "ui-steps-dot", "data-status": status }) });
33
22
  }
34
23
  return /* @__PURE__ */ jsxs(
35
24
  "span",
36
25
  {
37
- className: cn(
38
- "flex items-center justify-center",
39
- controlIconClass,
40
- "rounded-full border-2 text-sm font-medium",
41
- status === "finish" && "border-primary bg-primary text-primary-foreground",
42
- status === "process" && "border-primary text-primary",
43
- status === "error" && "border-destructive bg-destructive text-destructive-foreground",
44
- status === "wait" && "border-muted-foreground/30 text-muted-foreground"
45
- ),
26
+ "data-status": status,
27
+ className: cn("flex items-center justify-center", controlIconClass, "ui-steps-marker"),
46
28
  children: [
47
- status === "finish" && /* @__PURE__ */ jsx(Check, { className: "size-4", "aria-hidden": "true" }),
48
- status === "process" && /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin", "aria-hidden": "true" }),
49
- status === "error" && /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" }),
50
- status === "wait" && /* @__PURE__ */ jsx(Circle, { className: "size-3 fill-current", "aria-hidden": "true" })
29
+ status === "finish" && /* @__PURE__ */ jsx(Check, { className: "ui-steps-marker-icon", "aria-hidden": "true" }),
30
+ status === "process" && /* @__PURE__ */ jsx(Loader2, { className: "ui-steps-marker-icon animate-spin", "aria-hidden": "true" }),
31
+ status === "error" && /* @__PURE__ */ jsx(X, { className: "ui-steps-marker-icon", "aria-hidden": "true" }),
32
+ status === "wait" && /* @__PURE__ */ jsx(Circle, { className: "ui-steps-wait-icon", "aria-hidden": "true" })
51
33
  ]
52
34
  }
53
35
  );
@@ -74,11 +56,8 @@ function Steps({
74
56
  return /* @__PURE__ */ jsx(
75
57
  "ol",
76
58
  {
77
- className: cn(
78
- "flex w-full",
79
- inline ? "ui-steps-inline" : isVertical ? "flex-col gap-0" : "flex-row items-start",
80
- className
81
- ),
59
+ "data-direction": inline ? void 0 : isVertical ? "vertical" : "horizontal",
60
+ className: cn("flex w-full", inline ? "ui-steps-inline" : "ui-steps-list", className),
82
61
  "aria-label": t("navigation.steps.ariaLabel"),
83
62
  children: items.map((item, index) => {
84
63
  const absoluteIndex = base + index;
@@ -90,9 +69,10 @@ function Steps({
90
69
  const statusLabel = t(
91
70
  stepStatus === "finish" ? "navigation.steps.status.finish" : stepStatus === "process" ? "navigation.steps.status.process" : stepStatus === "error" ? "navigation.steps.status.error" : "navigation.steps.status.wait"
92
71
  );
72
+ const stepDirection = inline ? void 0 : isVertical ? "vertical" : "horizontal";
93
73
  const stepClassName = cn(
94
- "group flex min-w-0",
95
- inline ? "ui-steps-inline-control" : isVertical ? "flex-row items-start gap-3" : "flex-col items-center",
74
+ "group",
75
+ inline ? "ui-steps-inline-control" : "ui-steps-control",
96
76
  clickable ? "cursor-pointer" : "cursor-default"
97
77
  );
98
78
  const stepInner = inline ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -101,45 +81,28 @@ function Steps({
101
81
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: statusLabel })
102
82
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
103
83
  /* @__PURE__ */ jsx(StepIcon, { status: stepStatus, icon: item.icon, type }),
104
- /* @__PURE__ */ jsxs(
105
- "div",
106
- {
107
- className: cn(
108
- "min-w-0",
109
- isVertical ? "pt-1 text-start" : "mt-2 px-2",
110
- titlePlacement === "vertical" && !isVertical && "mt-1"
111
- ),
112
- children: [
113
- /* @__PURE__ */ jsx(
114
- "div",
115
- {
116
- className: cn(
117
- "font-medium",
118
- compact ? "text-xs" : "text-sm",
119
- stepStatus === "process" && "text-foreground",
120
- stepStatus === "wait" && "text-muted-foreground",
121
- stepStatus === "error" && "text-destructive"
122
- ),
123
- children: item.title
124
- }
125
- ),
126
- item.subtitle && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground text-xs", children: item.subtitle }),
127
- description && /* @__PURE__ */ jsx("div", { className: cn("text-muted-foreground", compact ? "text-xs" : "text-sm"), children: description })
128
- ]
129
- }
130
- )
84
+ /* @__PURE__ */ jsxs("div", { className: "ui-steps-text", children: [
85
+ /* @__PURE__ */ jsx(
86
+ "div",
87
+ {
88
+ className: "ui-steps-title",
89
+ "data-status": stepStatus,
90
+ "data-compact": compact ? "" : void 0,
91
+ children: item.title
92
+ }
93
+ ),
94
+ item.subtitle && /* @__PURE__ */ jsx("div", { className: "ui-steps-subtitle", children: item.subtitle }),
95
+ description && /* @__PURE__ */ jsx("div", { className: "ui-steps-description", "data-compact": compact ? "" : void 0, children: description })
96
+ ] })
131
97
  ] });
132
98
  return /* @__PURE__ */ jsxs(
133
99
  "li",
134
100
  {
135
101
  "aria-current": isCurrent ? "step" : void 0,
136
- className: cn(
137
- "relative flex min-w-0",
138
- !inline && "flex-1",
139
- inline ? "ui-steps-inline-item" : isVertical ? "flex-row gap-3 pb-8 last:pb-0" : "flex-col items-center text-center",
140
- !isVertical && !inline && index < items.length - 1 && "after:bg-border after:absolute after:top-4 after:h-px",
141
- !isVertical && !inline && index < items.length - 1 && "after:left-[calc(50%+1.25rem)] after:w-[calc(100%-2.5rem)]"
142
- ),
102
+ "data-direction": inline ? void 0 : isVertical ? "vertical" : "horizontal",
103
+ "data-title-placement": titlePlacement,
104
+ "data-connector": !isVertical && !inline && index < items.length - 1 ? "" : void 0,
105
+ className: cn(!inline && "flex-1", inline ? "ui-steps-inline-item" : "ui-steps-item"),
143
106
  "data-status": stepStatus,
144
107
  children: [
145
108
  interactive ? /* @__PURE__ */ jsx(
@@ -148,10 +111,11 @@ function Steps({
148
111
  type: "button",
149
112
  disabled: !clickable,
150
113
  onClick: clickable ? () => onValueChange?.(absoluteIndex) : void 0,
114
+ "data-direction": stepDirection,
151
115
  className: stepClassName,
152
116
  children: stepInner
153
117
  }
154
- ) : /* @__PURE__ */ jsx("span", { className: stepClassName, children: stepInner }),
118
+ ) : /* @__PURE__ */ jsx("span", { "data-direction": stepDirection, className: stepClassName, children: stepInner }),
155
119
  inline && index < items.length - 1 ? /* @__PURE__ */ jsx(
156
120
  SeparatorIcon,
157
121
  {
@@ -29,11 +29,15 @@ function Tabs({
29
29
  {
30
30
  "data-slot": "tabs",
31
31
  "data-orientation": orientation,
32
+ "data-variant": variant,
32
33
  orientation,
33
34
  value,
34
35
  defaultValue: value === void 0 ? resolvedDefault : void 0,
35
36
  className: cn(
36
- "group/tabs flex min-w-0 gap-2 data-[orientation=horizontal]:flex-col",
37
+ // Structure only. The shrink floor (`min-inline-size: 0`, gh#175) and the strip↔panel gap
38
+ // live in src/styles/navigation-layout.css so the gap reads --tabs-root-gap and a service
39
+ // can retune the tab rhythm without forking this file (#319).
40
+ "group/tabs flex data-[orientation=horizontal]:flex-col",
37
41
  className
38
42
  ),
39
43
  ...props,
@@ -44,7 +48,10 @@ function Tabs({
44
48
  "data-slot": "tabs-list",
45
49
  variant: variant === "line" ? "line" : "default",
46
50
  className: cn(
47
- variant === "line" && "h-auto w-full justify-start border-b p-0",
51
+ // The padding override is an arbitrary value reading the knob (never `p-0`): it must
52
+ // stay a UTILITY so tailwind-merge still drops the strip's own padding step, and a
53
+ // components-layer rule could not beat that utility anyway (#319).
54
+ variant === "line" && "h-auto w-full justify-start border-b p-[var(--tabs-list-line-space-inset)]",
48
55
  variant === "card" && "w-full justify-start",
49
56
  listClassName
50
57
  ),
@@ -56,8 +63,13 @@ function Tabs({
56
63
  className: cn(
57
64
  // Geometry only — the active underline is the token-owned `::after` bar the
58
65
  // line variant already owns (never a second, hand-rolled border-b indicator).
59
- variant === "line" && "rounded-none px-4 py-2",
60
- variant === "card" && "data-[state=active]:shadow-sm"
66
+ // Token-reading arbitrary values, not Tailwind steps (#319): they have to stay
67
+ // utilities so tailwind-merge keeps dropping the pill trigger's own radius /
68
+ // padding steps from the base class list.
69
+ // `card` adds NOTHING here — its list is forwarded as data-variant="default", so
70
+ // the active lift already comes from the base trigger's
71
+ // `group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm`.
72
+ variant === "line" && "rounded-[var(--tabs-trigger-line-radius)] px-[var(--tabs-trigger-line-padding-x)] py-[var(--tabs-trigger-line-padding-y)]"
61
73
  ),
62
74
  children: item.label
63
75
  },
@@ -70,7 +82,7 @@ function Tabs({
70
82
  {
71
83
  value: item.value,
72
84
  "data-slot": "tabs-panel",
73
- className: cn(variant === "line" && "mt-0", contentClassName),
85
+ className: contentClassName,
74
86
  children: item.content
75
87
  },
76
88
  item.value
@@ -56,7 +56,7 @@ function InfiniteQueryState({
56
56
  if (!data) return /* @__PURE__ */ jsx(Fragment, { children: skeleton });
57
57
  const flat = flatten(data);
58
58
  if (empty && isEmpty(flat)) return /* @__PURE__ */ jsx(Fragment, { children: empty });
59
- const footer = showLoadMore && query.hasNextPage ? loadMore ?? /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-4", children: /* @__PURE__ */ jsx(
59
+ const footer = showLoadMore && query.hasNextPage ? loadMore ?? /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-[var(--query-load-more-space-block-start)]", children: /* @__PURE__ */ jsx(
60
60
  Button,
61
61
  {
62
62
  type: "button",
@@ -73,7 +73,7 @@ function InfiniteQueryState({
73
73
  hasNextPage: !!query.hasNextPage,
74
74
  isFetchingNextPage: query.isFetchingNextPage
75
75
  }),
76
- query.isFetchingNextPage && (loadingMore ?? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground pt-2 text-center text-xs", children: t("common.working") })),
76
+ query.isFetchingNextPage && (loadingMore ?? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground pt-[var(--query-loading-more-space-block-start)] text-center text-xs", children: t("common.working") })),
77
77
  footer
78
78
  ] });
79
79
  }
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import * as AccordionPrimitive from "@radix-ui/react-accordion";
3
- export declare const Accordion: React.ForwardRefExoticComponent<(AccordionPrimitive.AccordionSingleProps | AccordionPrimitive.AccordionMultipleProps) & React.RefAttributes<HTMLDivElement>>;
3
+ export declare const Accordion: React.ForwardRefExoticComponent<(AccordionPrimitive.AccordionMultipleProps | AccordionPrimitive.AccordionSingleProps) & React.RefAttributes<HTMLDivElement>>;
4
4
  export declare const AccordionItem: React.ForwardRefExoticComponent<Omit<AccordionPrimitive.AccordionItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
5
5
  export declare const AccordionTrigger: React.ForwardRefExoticComponent<Omit<AccordionPrimitive.AccordionTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
6
6
  export declare const AccordionContent: React.ForwardRefExoticComponent<Omit<AccordionPrimitive.AccordionContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import * as AvatarPrimitive from "@radix-ui/react-avatar";
3
3
  import type { AvatarProp } from "../../props/components/data-display.prop.js";
4
- export declare const Avatar: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & Pick<AvatarProp, "shape" | "appearance"> & React.RefAttributes<HTMLSpanElement>>;
4
+ export declare const Avatar: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & Pick<AvatarProp, "appearance" | "presence" | "presenceLabel" | "shape"> & React.RefAttributes<HTMLSpanElement>>;
5
5
  export declare const AvatarImage: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps & React.RefAttributes<HTMLImageElement>, "ref"> & React.RefAttributes<HTMLImageElement>>;
6
6
  export declare const AvatarFallback: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarFallbackProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
@@ -1,19 +1,38 @@
1
1
  "use client";
2
- import { jsx } from "react/jsx-runtime";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as AvatarPrimitive from "@radix-ui/react-avatar";
5
+ import { useTranslation } from "../../i18n/use-translation.js";
5
6
  import { cn } from "../../lib/utils.js";
6
- const Avatar = React.forwardRef(({ className, shape = "circle", appearance = "default", ...props }, ref) => /* @__PURE__ */ jsx(
7
- AvatarPrimitive.Root,
8
- {
9
- ref,
10
- "data-slot": "avatar",
11
- "data-shape": shape === "square" ? "square" : void 0,
12
- "data-appearance": appearance === "tinted" ? "tinted" : void 0,
13
- className: cn("ui-avatar", className),
7
+ const Avatar = React.forwardRef(
8
+ ({
9
+ className,
10
+ shape = "circle",
11
+ appearance = "default",
12
+ presence,
13
+ presenceLabel,
14
+ children,
14
15
  ...props
16
+ }, ref) => {
17
+ const { t } = useTranslation();
18
+ return /* @__PURE__ */ jsxs(
19
+ AvatarPrimitive.Root,
20
+ {
21
+ ref,
22
+ "data-slot": "avatar",
23
+ "data-shape": shape === "square" ? "square" : void 0,
24
+ "data-appearance": appearance === "tinted" ? "tinted" : void 0,
25
+ "data-presence": presence,
26
+ className: cn("ui-avatar", className),
27
+ ...props,
28
+ children: [
29
+ children,
30
+ presence !== void 0 ? /* @__PURE__ */ jsx("span", { "data-slot": "avatar-presence", "data-presence": presence, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: presenceLabel ?? t(`dataDisplay.avatar.presence.${presence}`) }) }) : null
31
+ ]
32
+ }
33
+ );
15
34
  }
16
- ));
35
+ );
17
36
  Avatar.displayName = AvatarPrimitive.Root.displayName;
18
37
  const AvatarImage = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
19
38
  AvatarPrimitive.Image,
@@ -9,29 +9,31 @@ import type { InputOTPAlignProp } from "../../props/components/data-entry.prop.j
9
9
  * through `:has()`, exactly as it already does for the invalid and disabled states. A service that
10
10
  * wants every code field centred sets `--otp-container-align` once instead.
11
11
  */
12
- export declare const InputOTP: React.ForwardRefExoticComponent<((Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
12
+ export declare const InputOTP: React.ForwardRefExoticComponent<((Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "containerClassName" | "maxLength" | "noScriptCSSFallback" | "nonce" | "onChange" | "onComplete" | "pasteTransformer" | "pushPasswordManagerStrategy" | "textAlign" | "value"> & {
13
13
  value?: string;
14
14
  onChange?: (newValue: string) => unknown;
15
15
  maxLength: number;
16
- textAlign?: "left" | "center" | "right";
16
+ textAlign?: 'left' | 'center' | 'right';
17
17
  onComplete?: (...args: any[]) => unknown;
18
- pushPasswordManagerStrategy?: "increase-width" | "none";
18
+ pushPasswordManagerStrategy?: 'increase-width' | 'none';
19
19
  pasteTransformer?: (pasted: string) => string;
20
20
  containerClassName?: string;
21
21
  noScriptCSSFallback?: string | null;
22
+ nonce?: string;
22
23
  } & {
23
24
  render: (props: import("input-otp").RenderProps) => React.ReactNode;
24
25
  children?: never;
25
- } & React.RefAttributes<HTMLInputElement>, "ref"> | Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
26
+ } & React.RefAttributes<HTMLInputElement>, "ref"> | Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "containerClassName" | "maxLength" | "noScriptCSSFallback" | "nonce" | "onChange" | "onComplete" | "pasteTransformer" | "pushPasswordManagerStrategy" | "textAlign" | "value"> & {
26
27
  value?: string;
27
28
  onChange?: (newValue: string) => unknown;
28
29
  maxLength: number;
29
- textAlign?: "left" | "center" | "right";
30
+ textAlign?: 'left' | 'center' | 'right';
30
31
  onComplete?: (...args: any[]) => unknown;
31
- pushPasswordManagerStrategy?: "increase-width" | "none";
32
+ pushPasswordManagerStrategy?: 'increase-width' | 'none';
32
33
  pasteTransformer?: (pasted: string) => string;
33
34
  containerClassName?: string;
34
35
  noScriptCSSFallback?: string | null;
36
+ nonce?: string;
35
37
  } & {
36
38
  render?: never;
37
39
  children: React.ReactNode;
@@ -30,7 +30,7 @@ const Rating = React.forwardRef(
30
30
  const focusableStar = current > 0 ? current : 1;
31
31
  const onKeyDown = (e, star) => {
32
32
  if (!interactive) return;
33
- let next = null;
33
+ let next;
34
34
  switch (e.key) {
35
35
  case "ArrowRight":
36
36
  case "ArrowUp":
@@ -1,3 +1,28 @@
1
1
  import * as React from "react";
2
- import * as SeparatorPrimitive from "@radix-ui/react-separator";
3
- export declare const Separator: React.ForwardRefExoticComponent<Omit<SeparatorPrimitive.SeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
2
+ export type { SeparatorProp, SeparatorProp as SeparatorProps, } from "../../props/components/layout.prop.js";
3
+ /**
4
+ * Separator — a tokenized horizontal/vertical rule, optionally INTERRUPTED by a localized label
5
+ * (gh#308): a message stream's day divider, a "new messages" unread watermark, an auth
6
+ * conjunction. Before #308 the only labelled rule in the library was the auth-scoped
7
+ * `AuthDivider`, so a chat stream had to either misuse it (inheriting the `--auth-shell-divider-*`
8
+ * type ramp) or hand-roll a `<div>` grid; `AuthDivider` is now a thin preset over this.
9
+ *
10
+ * ACCESSIBILITY — the whole point of the labelled form is that the label is ANNOUNCED, exactly
11
+ * ONCE. Without a label the rule stays `decorative` (Radix emits `role="none"`), which is right:
12
+ * a section rule carries no information. With a label the default flips to `decorative={false}`,
13
+ * so Radix emits a real `role="separator"` (plus `aria-orientation` when vertical, which is what
14
+ * the ARIA default already implies for horizontal), the label string becomes the separator's
15
+ * accessible NAME via `aria-label`, and the visible label node is `aria-hidden` — otherwise the
16
+ * same string would be announced twice, once as the name and again as the content. A consumer who
17
+ * explicitly passes `decorative` still wins; when they force `decorative` on a labelled rule the
18
+ * name is dropped (a `role="none"` element may not carry one) and the visible text is left in the
19
+ * tree instead, so it is still read once and never as a nameless blank rule.
20
+ */
21
+ export declare const Separator: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
22
+ orientation?: import("../../props/index.js").OrientationProp;
23
+ label?: string;
24
+ labelAlign?: import("../../props/index.js").TextAlignProp;
25
+ tone?: import("../../props/index.js").TextToneProp;
26
+ decorative?: boolean;
27
+ className?: import("../../props/index.js").ClassNameProp;
28
+ } & React.RefAttributes<HTMLDivElement>>;