@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
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { type AppDateFormat, type AppLocale, type AppTimeFormat, type AppTimezone } from "./types.js";
3
3
  import type { AppContextValue, AppProviderProp } from "../props/components/app.prop.js";
4
4
  export type { AppProviderProp, AppContextValue } from "../props/components/app.prop.js";
5
- export declare function AppProvider({ children, defaultLocale, fallbackLocale, defaultTimezone, systemTimezone, defaultTimeFormat, defaultDateFormat, timezoneOptions, storageKey, persist, theme: initialTheme, brand: initialBrand, density: initialDensity, fontSize: initialFontSize, scaling: initialScaling, onLocaleChange, onTimezoneChange, onTimeFormatChange, onDateFormatChange, onThemeChange, onBrandChange, onDensityChange, onFontSizeChange, onScalingChange, }: AppProviderProp): React.JSX.Element;
5
+ export declare function AppProvider({ children, defaultLocale, fallbackLocale, defaultTimezone, systemTimezone, defaultTimeFormat, defaultDateFormat, timezoneOptions, storageKey, persist, theme: initialTheme, brand: initialBrand, density: initialDensity, fontSize: initialFontSize, scaling: initialScaling, emitFieldNames, onLocaleChange, onTimezoneChange, onTimeFormatChange, onDateFormatChange, onThemeChange, onBrandChange, onDensityChange, onFontSizeChange, onScalingChange, }: AppProviderProp): React.JSX.Element;
6
6
  export declare function useAppContext(): AppContextValue;
7
7
  /** Returns null outside AppProvider — used by pickers for optional context. */
8
8
  export declare function useOptionalAppContext(): AppContextValue | null;
@@ -65,6 +65,7 @@ function AppProvider({
65
65
  density: initialDensity = "default",
66
66
  fontSize: initialFontSize = "default",
67
67
  scaling: initialScaling = null,
68
+ emitFieldNames = false,
68
69
  onLocaleChange,
69
70
  onTimezoneChange,
70
71
  onTimeFormatChange,
@@ -299,6 +300,7 @@ function AppProvider({
299
300
  density,
300
301
  fontSize,
301
302
  scaling,
303
+ emitFieldNames,
302
304
  setLocale,
303
305
  setTimezone,
304
306
  setTimeFormat,
@@ -323,6 +325,7 @@ function AppProvider({
323
325
  density,
324
326
  fontSize,
325
327
  scaling,
328
+ emitFieldNames,
326
329
  setLocale,
327
330
  setTimezone,
328
331
  setTimeFormat,
@@ -1,7 +1,7 @@
1
1
  import type { AppLocale } from "./types.js";
2
2
  import type { AppDateFormat } from "./date-formats.js";
3
3
  export declare const APP_DATE_FORMAT_OPTIONS: {
4
- value: "iso" | "dmy" | "mdy";
4
+ value: "dmy" | "iso" | "mdy";
5
5
  }[];
6
6
  export declare function getDateFormatLabel(dateFormat: AppDateFormat, locale: AppLocale, fallbackLocale?: AppLocale): string;
7
7
  /** Suggested default per locale — vi → dmy, ja → iso, en → mdy. */
@@ -1,7 +1,7 @@
1
1
  import type { AppLocale } from "./types.js";
2
2
  import type { AppTimeFormat } from "./time-formats.js";
3
3
  export declare const APP_TIME_FORMAT_OPTIONS: {
4
- value: "24h" | "12h";
4
+ value: "12h" | "24h";
5
5
  }[];
6
6
  export declare function getTimeFormatLabel(timeFormat: AppTimeFormat, locale: AppLocale, fallbackLocale?: AppLocale): string;
7
7
  /** Suggested default per locale — vi/ja → 24h, en → 12h. */
@@ -16,7 +16,7 @@ export type BadgeTone = ToneProp | "primary";
16
16
  * old `text-xs` rendering exactly.
17
17
  */
18
18
  declare const badgeVariants: (props?: ({
19
- variant?: "default" | "outline" | "dashed" | "secondary" | null | undefined;
19
+ variant?: "dashed" | "default" | "outline" | "secondary" | null | undefined;
20
20
  shape?: "default" | "pill" | "sharp" | null | undefined;
21
21
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
22
22
  export interface BadgeProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children">, Omit<VariantProps<typeof badgeVariants>, "variant" | "shape"> {
@@ -1,8 +1,6 @@
1
1
  import * as React from "react";
2
- import { type VariantProps } from "class-variance-authority";
3
2
  import type { LucideIcon } from "lucide-react";
4
3
  import type { HeadingLevelProp } from "../../props/vocabulary/index.js";
5
- type CardSize = "md" | "compact";
6
4
  /** Semantic accent tone. `accentPlacement` decides WHERE it is drawn — a leading-edge
7
5
  * stripe (default) or the full perimeter. */
8
6
  type CardAccent = "primary" | "success" | "warning" | "info" | "attention" | "destructive";
@@ -22,11 +20,7 @@ type CardAccentPlacement = "edge" | "perimeter";
22
20
  type CardVariant = "default" | "muted" | "outline" | "featured";
23
21
  /** Padding density — base 16px · tight 12px · cozy 20px. */
24
22
  type CardDensity = "tight" | "cozy";
25
- declare const cardVariants: (props?: ({
26
- size?: "compact" | "md" | null | undefined;
27
- } & import("class-variance-authority/types").ClassProp) | undefined) => string;
28
- export type CardProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof cardVariants> & {
29
- size?: CardSize;
23
+ export type CardProps = React.HTMLAttributes<HTMLDivElement> & {
30
24
  accent?: CardAccent;
31
25
  /**
32
26
  * Where `accent` is drawn — `"edge"` (default, the leading-edge stripe) or `"perimeter"`
@@ -36,10 +30,7 @@ export type CardProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<type
36
30
  variant?: CardVariant;
37
31
  density?: CardDensity;
38
32
  };
39
- export declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
40
- size?: "compact" | "md" | null | undefined;
41
- } & import("class-variance-authority/types").ClassProp) | undefined) => string> & {
42
- size?: CardSize;
33
+ export declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
43
34
  accent?: CardAccent;
44
35
  /**
45
36
  * Where `accent` is drawn — `"edge"` (default, the leading-edge stripe) or `"perimeter"`
@@ -141,7 +132,7 @@ export declare const CardBar: React.ForwardRefExoticComponent<React.HTMLAttribut
141
132
  /** Right-aligned actions slot (settings/save), Ant `tabBarExtraContent`-style. */
142
133
  extra?: React.ReactNode;
143
134
  } & React.RefAttributes<HTMLDivElement>>;
144
- export type StatCardProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof cardVariants> & {
135
+ export type StatCardProps = React.HTMLAttributes<HTMLDivElement> & {
145
136
  label: React.ReactNode;
146
137
  value: React.ReactNode;
147
138
  hint?: React.ReactNode;
@@ -162,7 +153,7 @@ export type StatCardProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<
162
153
  accentPlacement?: CardAccentPlacement;
163
154
  };
164
155
  /** KPI / stat tile — token-driven layout aligned to dashboard KPI cards. */
165
- export declare function StatCard({ label, value, hint, icon: Icon, delta, layout, align, inverse, accent, accentPlacement, className, size, ...props }: StatCardProps): React.JSX.Element;
156
+ export declare function StatCard({ label, value, hint, icon: Icon, delta, layout, align, inverse, accent, accentPlacement, className, ...props }: StatCardProps): React.JSX.Element;
166
157
  /** Header actions slot — pair with `CardHeader className="flex flex-row …"`. */
167
158
  export declare const CardAction: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
168
159
  export {};
@@ -1,24 +1,13 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
- import { cva } from "class-variance-authority";
4
3
  import { cn } from "../../lib/utils.js";
5
- const cardVariants = cva("group/card", {
6
- variants: {
7
- size: {
8
- md: "",
9
- compact: ""
10
- }
11
- },
12
- defaultVariants: { size: "md" }
13
- });
14
4
  const Card = React.forwardRef(
15
- ({ className, size = "md", accent, accentPlacement, variant, density, ...props }, ref) => /* @__PURE__ */ jsx(
5
+ ({ className, accent, accentPlacement, variant, density, ...props }, ref) => /* @__PURE__ */ jsx(
16
6
  "div",
17
7
  {
18
8
  ref,
19
- className: cn(cardVariants({ size }), className),
9
+ className: cn("group/card", className),
20
10
  "data-slot": "card",
21
- "data-size": size === "compact" ? "compact" : void 0,
22
11
  "data-accent": accent,
23
12
  "data-accent-placement": accentPlacement === "perimeter" ? "perimeter" : void 0,
24
13
  "data-variant": variant && variant !== "default" ? variant : void 0,
@@ -111,14 +100,12 @@ function StatCard({
111
100
  accent,
112
101
  accentPlacement,
113
102
  className,
114
- size = "compact",
115
103
  ...props
116
104
  }) {
117
105
  const deltaTone = getDeltaTone(delta, inverse);
118
106
  return /* @__PURE__ */ jsxs(
119
107
  Card,
120
108
  {
121
- size: size ?? "compact",
122
109
  accent,
123
110
  accentPlacement,
124
111
  className: cn("ui-stat-card", className),
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { flexRender, type OnChangeFn, type PaginationState, type RowData, type VisibilityState } from "@tanstack/react-table";
2
+ import { flexRender, type ColumnVisibilityState, type OnChangeFn, type PaginationState } from "@tanstack/react-table";
3
3
  import type { BreakpointProp, ColumnDefProp, DensityProp, SortStateProp, TablePresetProp } from "../../props/vocabulary/index.js";
4
4
  export type Density = DensityProp;
5
5
  /**
@@ -9,11 +9,6 @@ export type Density = DensityProp;
9
9
  * lists the column in DataTable.ViewOptions. Adapted to a TanStack column internally.
10
10
  */
11
11
  export type ColumnDef<T> = ColumnDefProp<T>;
12
- declare module "@tanstack/react-table" {
13
- interface ColumnMeta<TData extends RowData, TValue> {
14
- lean?: ColumnDef<TData>;
15
- }
16
- }
17
12
  interface DataTableProps<T> {
18
13
  data: T[];
19
14
  columns: ColumnDef<T>[];
@@ -37,8 +32,8 @@ interface DataTableProps<T> {
37
32
  /** Total server row count (manual pagination) — drives the page count. */
38
33
  rowCount?: number;
39
34
  /** Column show/hide state, surfaced by DataTable.ViewOptions. */
40
- columnVisibility?: VisibilityState;
41
- onColumnVisibilityChange?: OnChangeFn<VisibilityState>;
35
+ columnVisibility?: ColumnVisibilityState;
36
+ onColumnVisibilityChange?: OnChangeFn<ColumnVisibilityState>;
42
37
  /**
43
38
  * Manual (server) flags. Default `false` so the simple `data`+`columns` case
44
39
  * sorts / filters in-browser with no extra wiring. Client pagination slices
@@ -2,12 +2,19 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import {
5
+ columnFilteringFeature,
6
+ columnVisibilityFeature,
7
+ createCoreRowModel,
8
+ createFilteredRowModel,
9
+ createPaginatedRowModel,
10
+ createSortedRowModel,
5
11
  flexRender,
6
- getCoreRowModel,
7
- getFilteredRowModel,
8
- getPaginationRowModel,
9
- getSortedRowModel,
10
- useReactTable
12
+ globalFilteringFeature,
13
+ rowPaginationFeature,
14
+ rowSelectionFeature,
15
+ rowSortingFeature,
16
+ tableFeatures,
17
+ useTable
11
18
  } from "@tanstack/react-table";
12
19
  import {
13
20
  AlertCircle,
@@ -59,6 +66,21 @@ import {
59
66
  tableCellPaddingClass,
60
67
  tableRowHeightClass
61
68
  } from "../../lib/control-styles.js";
69
+ function dataTableFeatures() {
70
+ return tableFeatures({
71
+ rowSortingFeature,
72
+ columnFilteringFeature,
73
+ globalFilteringFeature,
74
+ rowPaginationFeature,
75
+ rowSelectionFeature,
76
+ columnVisibilityFeature,
77
+ coreRowModel: createCoreRowModel(),
78
+ filteredRowModel: createFilteredRowModel(),
79
+ sortedRowModel: createSortedRowModel(),
80
+ paginatedRowModel: createPaginatedRowModel(),
81
+ columnMeta: {}
82
+ });
83
+ }
62
84
  function toTanstackColumns(columns) {
63
85
  return columns.map((col) => ({
64
86
  id: col.key,
@@ -182,17 +204,18 @@ function DataTable({
182
204
  (c) => React.isValidElement(c) && c.type.displayName === "DataTable.Pagination" && typeof c.props.onChange !== "function"
183
205
  );
184
206
  const paginationEngaged = manualPagination || controlledPagination !== void 0 || onPaginationChange !== void 0 || hasNumberedPager;
185
- const table = useReactTable({
207
+ const features = React.useMemo(() => dataTableFeatures(), []);
208
+ const table = useTable({
209
+ features,
186
210
  data,
187
211
  columns: tanstackColumns,
188
212
  getRowId,
189
- getCoreRowModel: getCoreRowModel(),
190
- ...manualSorting ? {} : { getSortedRowModel: getSortedRowModel() },
191
- ...manualFiltering ? {} : { getFilteredRowModel: getFilteredRowModel() },
192
- ...manualPagination || !paginationEngaged ? {} : { getPaginationRowModel: getPaginationRowModel() },
193
213
  manualSorting,
194
214
  manualFiltering,
195
- manualPagination,
215
+ // v8 disengaged pagination by withholding the row model; v9 has one static feature set, so
216
+ // "no pager on this table" is expressed the same way as "the server paginates" — leave the
217
+ // rows unsliced. Page count still derives from `rowCount`/the pre-paginated model either way.
218
+ manualPagination: manualPagination || !paginationEngaged,
196
219
  rowCount,
197
220
  enableRowSelection: selectable,
198
221
  state: {
@@ -261,7 +284,7 @@ DataTable.Search = function DataTableSearch({
261
284
  }) {
262
285
  const { table } = useDataTableContext();
263
286
  const { t } = useTranslation();
264
- const value = table.getState().globalFilter ?? "";
287
+ const value = table.state.globalFilter ?? "";
265
288
  return /* @__PURE__ */ jsx(
266
289
  SearchInput,
267
290
  {
@@ -285,7 +308,7 @@ DataTable.ViewOptions = function DataTableViewOptions({
285
308
  if (hideable.length === 0) return null;
286
309
  return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
287
310
  /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className, children: [
288
- /* @__PURE__ */ jsx(SlidersHorizontal, { className: "size-4 shrink-0", "aria-hidden": "true" }),
311
+ /* @__PURE__ */ jsx(SlidersHorizontal, { className: "ui-data-table-toolbar-icon", "aria-hidden": "true" }),
289
312
  label ?? t("dataGrid.view")
290
313
  ] }) }),
291
314
  /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", children: [
@@ -389,7 +412,7 @@ DataTable.DensityToggle = function DataTableDensityToggle() {
389
412
  },
390
413
  "aria-label": t("dataTable.densitySwitch", { density: nextLabel }),
391
414
  children: /* @__PURE__ */ jsxs(Flex, { direction: "row", wrap: true, align: "center", gap: "xs", children: [
392
- /* @__PURE__ */ jsx(Icon, { className: "size-4", "aria-hidden": "true" }),
415
+ /* @__PURE__ */ jsx(Icon, { className: "ui-data-table-toolbar-icon", "aria-hidden": "true" }),
393
416
  density === "compact" ? t("dataTable.densityCompact") : t("dataTable.densityComfortable")
394
417
  ] })
395
418
  }
@@ -453,7 +476,7 @@ DataTable.Content = function DataTableContent() {
453
476
  observer.disconnect();
454
477
  };
455
478
  }, []);
456
- const activeSort = sort ?? sortingStateToSort(table.getState().sorting);
479
+ const activeSort = sort ?? sortingStateToSort(table.state.sorting);
457
480
  const isControlledSort = sort !== void 0 || !!onSortChange;
458
481
  const onHeaderClick = (col) => {
459
482
  if (!col.sortable) return;
@@ -490,64 +513,78 @@ DataTable.Content = function DataTableContent() {
490
513
  "data-striped": striped ? "" : void 0,
491
514
  "data-hoverable": hoverable ? "" : void 0,
492
515
  children: /* @__PURE__ */ jsxs(Table, { scrollable: preset !== "default", preset, collapseBelow, children: [
493
- /* @__PURE__ */ jsx(TableHeader, { className: cn("bg-secondary", stickyHeader && "sticky top-0 z-10"), children: /* @__PURE__ */ jsxs(TableRow, { children: [
494
- selectable && /* @__PURE__ */ jsx(TableHead, { className: "w-10", children: /* @__PURE__ */ jsx(DataTable.SelectAll, {}) }),
495
- visibleColumns.map((col) => {
496
- const isSortable = !!col.sortable;
497
- const isActiveSort = isSortable && activeSort?.key === col.key;
498
- const sortIndicator = isSortable ? isActiveSort ? activeSort?.direction === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ArrowDown, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ChevronsUpDown, { className: "text-muted-foreground size-3", "aria-hidden": "true" }) : null;
499
- const headerEmpty = isEmptyHeader(col.header);
500
- const headerContent = headerEmpty && col.ariaLabel ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: col.ariaLabel }) : col.header;
501
- const label = /* @__PURE__ */ jsxs("span", { className: "ui-data-table-sort-label", children: [
502
- headerContent,
503
- sortIndicator
504
- ] });
505
- return /* @__PURE__ */ jsx(
506
- TableHead,
507
- {
508
- priority: col.priority,
509
- "data-empty": headerEmpty || void 0,
510
- "aria-sort": isSortable ? isActiveSort ? activeSort?.direction === "asc" ? "ascending" : "descending" : "none" : void 0,
511
- style: columnWidth(col.width).style,
512
- className: cn(
513
- columnWidth(col.width).className,
514
- // `headerAlign` when the heading differs from the rows,
515
- // `align` otherwise. A table wanting centred headings
516
- // over start-aligned text could not say so before, and
517
- // consumers reached for `[&_th_button]:justify-center`.
518
- (col.headerAlign ?? col.align) === "right" && "text-end",
519
- (col.headerAlign ?? col.align) === "center" && "text-center",
520
- col.hiddenOnMobile && "hidden md:table-cell",
521
- isSortable && "select-none",
522
- col.pin === "end" && "ui-data-table-pin-end"
523
- ),
524
- children: isSortable ? /* @__PURE__ */ jsx(
525
- "button",
516
+ /* @__PURE__ */ jsx(
517
+ TableHeader,
518
+ {
519
+ className: cn("bg-secondary", stickyHeader && "ui-data-table-sticky-header"),
520
+ children: /* @__PURE__ */ jsxs(TableRow, { children: [
521
+ selectable && /* @__PURE__ */ jsx(TableHead, { className: "ui-data-table-select-column", children: /* @__PURE__ */ jsx(DataTable.SelectAll, {}) }),
522
+ visibleColumns.map((col) => {
523
+ const isSortable = !!col.sortable;
524
+ const isActiveSort = isSortable && activeSort?.key === col.key;
525
+ const sortIndicator = isSortable ? isActiveSort ? activeSort?.direction === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "ui-data-table-sort-icon", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ArrowDown, { className: "ui-data-table-sort-icon", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(
526
+ ChevronsUpDown,
526
527
  {
527
- type: "button",
528
- className: "ui-data-table-sort-button focus-visible:ring-ring rounded-sm focus-visible:ring-2",
529
- onClick: () => {
530
- onHeaderClick(col);
531
- },
532
- children: label
528
+ className: "ui-data-table-sort-icon text-muted-foreground",
529
+ "aria-hidden": "true"
533
530
  }
534
- ) : label
535
- },
536
- col.key
537
- );
538
- })
539
- ] }) }),
531
+ ) : null;
532
+ const headerEmpty = isEmptyHeader(col.header);
533
+ const headerContent = headerEmpty && col.ariaLabel ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: col.ariaLabel }) : col.header;
534
+ const label = /* @__PURE__ */ jsxs("span", { className: "ui-data-table-sort-label", children: [
535
+ headerContent,
536
+ sortIndicator
537
+ ] });
538
+ return /* @__PURE__ */ jsx(
539
+ TableHead,
540
+ {
541
+ priority: col.priority,
542
+ "data-empty": headerEmpty || void 0,
543
+ "data-align": col.headerAlign ?? col.align,
544
+ "aria-sort": isSortable ? isActiveSort ? activeSort?.direction === "asc" ? "ascending" : "descending" : "none" : void 0,
545
+ style: columnWidth(col.width).style,
546
+ className: cn(
547
+ columnWidth(col.width).className,
548
+ // `headerAlign` when the heading differs from the rows,
549
+ // `align` otherwise. A table wanting centred headings
550
+ // over start-aligned text could not say so before, and
551
+ // consumers reached for `[&_th_button]:justify-center`.
552
+ (col.headerAlign ?? col.align) === "right" && "text-end",
553
+ (col.headerAlign ?? col.align) === "center" && "text-center",
554
+ col.hiddenOnMobile && "hidden md:table-cell",
555
+ isSortable && "select-none",
556
+ col.pin === "end" && "ui-data-table-pin-end"
557
+ ),
558
+ children: isSortable ? /* @__PURE__ */ jsx(
559
+ "button",
560
+ {
561
+ type: "button",
562
+ className: "ui-data-table-sort-button ui-focus-ring",
563
+ onClick: () => {
564
+ onHeaderClick(col);
565
+ },
566
+ children: label
567
+ }
568
+ ) : label
569
+ },
570
+ col.key
571
+ );
572
+ })
573
+ ] })
574
+ }
575
+ ),
540
576
  /* @__PURE__ */ jsx(TableBody, { children: loading ? (
541
577
  // Shaped skeleton rows rendered INSIDE the real table grid so they
542
578
  // share its borders + column widths — no second framed container
543
579
  // (which double-borders when the table sits in a Card). Count is
544
580
  // bounded to the previous page so the height barely shifts.
545
581
  Array.from({ length: Math.min(Math.max(rowCount, 6), 10) }).map((_, i) => /* @__PURE__ */ jsxs(TableRow, { className: cn(rowPadding, "hover:bg-transparent"), children: [
546
- selectable && /* @__PURE__ */ jsx(TableCell, { className: cellPadding, children: /* @__PURE__ */ jsx("div", { className: "ui-skeleton-block size-4 rounded-sm" }) }),
582
+ selectable && /* @__PURE__ */ jsx(TableCell, { className: cellPadding, children: /* @__PURE__ */ jsx("div", { className: "ui-skeleton-block ui-data-table-skeleton-check" }) }),
547
583
  visibleColumns.map((col, j) => /* @__PURE__ */ jsx(
548
584
  TableCell,
549
585
  {
550
586
  priority: col.priority,
587
+ "data-align": col.align,
551
588
  style: columnWidth(col.width).style,
552
589
  className: cn(
553
590
  cellPadding,
@@ -561,7 +598,7 @@ DataTable.Content = function DataTableContent() {
561
598
  "div",
562
599
  {
563
600
  className: cn(
564
- "ui-skeleton-block h-4",
601
+ "ui-skeleton-block ui-data-table-skeleton-line",
565
602
  j === 0 ? "w-1/2" : "w-3/4",
566
603
  col.align === "right" && "ms-auto",
567
604
  col.align === "center" && "mx-auto"
@@ -671,6 +708,7 @@ DataTable.Content = function DataTableContent() {
671
708
  TableCell,
672
709
  {
673
710
  priority: col.priority,
711
+ "data-align": col.align,
674
712
  style: columnWidth(col.width).style,
675
713
  className: cn(
676
714
  cellPadding,
@@ -742,7 +780,7 @@ function NumberedPagination({
742
780
  }) {
743
781
  const { table } = useDataTableContext();
744
782
  const { t } = useTranslation();
745
- const { pageIndex, pageSize } = table.getState().pagination;
783
+ const { pageIndex, pageSize } = table.state.pagination;
746
784
  const pageCount = table.getPageCount();
747
785
  return /* @__PURE__ */ jsxs(
748
786
  Flex,
@@ -755,7 +793,7 @@ function NumberedPagination({
755
793
  className: cn("ui-data-table-pagination ui-data-table-pagination--numbered", className),
756
794
  children: [
757
795
  /* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", gap: "sm", className: "ui-data-table-page-size", children: [
758
- /* @__PURE__ */ jsx("span", { className: "ui-data-table-page-size-label text-muted-foreground text-sm", children: t("dataGrid.rowsPerPage") }),
796
+ /* @__PURE__ */ jsx("span", { className: "ui-data-table-page-size-label ui-data-table-pagination-text", children: t("dataGrid.rowsPerPage") }),
759
797
  /* @__PURE__ */ jsxs(
760
798
  Select,
761
799
  {
@@ -777,7 +815,7 @@ function NumberedPagination({
777
815
  )
778
816
  ] }),
779
817
  /* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", gap: "sm", className: "ui-data-table-page-nav", children: [
780
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm tabular-nums", children: t("dataGrid.pageOf", { page: pageIndex + 1, total: Math.max(1, pageCount) }) }),
818
+ /* @__PURE__ */ jsx("span", { className: "ui-data-table-pagination-text tabular-nums", children: t("dataGrid.pageOf", { page: pageIndex + 1, total: Math.max(1, pageCount) }) }),
781
819
  /* @__PURE__ */ jsx(
782
820
  Button,
783
821
  {
@@ -786,7 +824,7 @@ function NumberedPagination({
786
824
  disabled: !table.getCanPreviousPage(),
787
825
  onClick: () => table.previousPage(),
788
826
  "aria-label": t("common.previous") ?? "Previous",
789
- children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4", "aria-hidden": "true" })
827
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "ui-data-table-pagination-icon", "aria-hidden": "true" })
790
828
  }
791
829
  ),
792
830
  /* @__PURE__ */ jsx(
@@ -797,7 +835,7 @@ function NumberedPagination({
797
835
  disabled: !table.getCanNextPage(),
798
836
  onClick: () => table.nextPage(),
799
837
  "aria-label": t("common.next") ?? "Next",
800
- children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4", "aria-hidden": "true" })
838
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "ui-data-table-pagination-icon", "aria-hidden": "true" })
801
839
  }
802
840
  )
803
841
  ] })
@@ -815,7 +853,7 @@ DataTable.RowActions = function DataTableRowActions({ ariaLabel, children }) {
815
853
  "aria-label": ariaLabel ?? t("dataTable.rowActions"),
816
854
  className: controlIconSmClass,
817
855
  children: [
818
- /* @__PURE__ */ jsx(MoreHorizontal, { className: "size-4", "aria-hidden": "true" }),
856
+ /* @__PURE__ */ jsx(MoreHorizontal, { className: "ui-data-table-toolbar-icon", "aria-hidden": "true" }),
819
857
  children
820
858
  ]
821
859
  }
@@ -15,7 +15,19 @@ function Descriptions({
15
15
  }) {
16
16
  const colsClass = columns === 1 ? "grid-cols-1" : columns === 3 ? "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3" : "grid-cols-1 sm:grid-cols-2";
17
17
  const context = React.useMemo(() => ({ layout, labelAlign }), [layout, labelAlign]);
18
- return /* @__PURE__ */ jsx(DescriptionsLayoutContext.Provider, { value: context, children: /* @__PURE__ */ jsx("dl", { className: cn("grid gap-x-6 gap-y-[var(--descriptions-row-gap)]", colsClass, className), children }) });
18
+ return /* @__PURE__ */ jsx(DescriptionsLayoutContext.Provider, { value: context, children: /* @__PURE__ */ jsx(
19
+ "dl",
20
+ {
21
+ "data-slot": "descriptions",
22
+ "data-columns": columns,
23
+ className: cn(
24
+ "grid gap-x-[var(--descriptions-column-gap)] gap-y-[var(--descriptions-row-gap)]",
25
+ colsClass,
26
+ className
27
+ ),
28
+ children
29
+ }
30
+ ) });
19
31
  }
20
32
  Descriptions.Item = function DescriptionsItem({
21
33
  label,
@@ -26,14 +38,18 @@ Descriptions.Item = function DescriptionsItem({
26
38
  }) {
27
39
  const { layout, labelAlign } = React.useContext(DescriptionsLayoutContext);
28
40
  const spanClass = span === 2 ? "sm:col-span-2" : span === 3 ? "sm:col-span-2 lg:col-span-3" : "";
41
+ const endAlignedLabel = layout === "horizontal" && labelAlign === "end";
29
42
  return /* @__PURE__ */ jsxs(
30
43
  "div",
31
44
  {
45
+ "data-slot": "descriptions-item",
32
46
  className: cn(
33
47
  layout === "horizontal" ? (
34
48
  // Label beside value — a token-aligned label column so the values line up. The
35
- // `--descriptions-label-width` knob aligns labels (rule #44/#45).
36
- "grid grid-cols-[var(--descriptions-label-width)_minmax(0,1fr)] items-baseline gap-x-3"
49
+ // `--descriptions-label-width` / `--descriptions-label-gap` knobs align labels and set
50
+ // the label→value gap (rule #44/#45); a service that narrows the column usually wants
51
+ // to close the gap in the same step.
52
+ "grid grid-cols-[var(--descriptions-label-width)_minmax(0,1fr)] items-baseline gap-x-[var(--descriptions-label-gap)]"
37
53
  ) : (
38
54
  // Vertical (default): label over value. The shared --field-label-gap matches
39
55
  // FormField / Form so the label→value gap is consistent everywhere.
@@ -46,16 +62,29 @@ Descriptions.Item = function DescriptionsItem({
46
62
  /* @__PURE__ */ jsx(
47
63
  "dt",
48
64
  {
65
+ "data-slot": "descriptions-label",
66
+ "data-label-align": endAlignedLabel ? "end" : void 0,
49
67
  className: cn(
50
68
  "text-muted-foreground text-xs",
51
69
  // `end`-align only ever applies in horizontal layout — same guard `Form` uses, so a
52
70
  // vertical label (already above its value) never mistakenly end-aligns (gh#294).
53
- layout === "horizontal" && labelAlign === "end" && "text-end"
71
+ endAlignedLabel && "text-end"
54
72
  ),
55
73
  children: label
56
74
  }
57
75
  ),
58
- /* @__PURE__ */ jsx("dd", { className: cn("text-sm break-all", mono && "font-mono"), children })
76
+ /* @__PURE__ */ jsx(
77
+ "dd",
78
+ {
79
+ "data-slot": "descriptions-value",
80
+ "data-mono": mono ? "" : void 0,
81
+ className: cn(
82
+ "text-[length:var(--descriptions-value-font-size)] leading-[var(--descriptions-value-line-height)] break-all",
83
+ mono && "font-mono"
84
+ ),
85
+ children
86
+ }
87
+ )
59
88
  ]
60
89
  }
61
90
  );
@@ -22,7 +22,7 @@ function EmptyState({
22
22
  role: "status",
23
23
  className: cn("ui-empty-state", className),
24
24
  children: [
25
- Icon && variant !== "compact" && /* @__PURE__ */ jsx("div", { className: "ui-empty-state-icon", children: /* @__PURE__ */ jsx(Icon, { className: "size-6", "aria-hidden": "true" }) }),
25
+ Icon && variant !== "compact" && /* @__PURE__ */ jsx("div", { className: "ui-empty-state-icon", children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }) }),
26
26
  createElement(TitleTag, { className: "ui-empty-state-title" }, title),
27
27
  description && /* @__PURE__ */ jsx("p", { className: "ui-empty-state-description", children: description }),
28
28
  action && /* @__PURE__ */ jsx("div", { children: action })
@@ -25,7 +25,7 @@ function toGrantSet(grants) {
25
25
  )
26
26
  );
27
27
  }
28
- const PIN_START = "sticky start-0 z-20 bg-inherit border-e border-border";
28
+ const PIN_START = "ui-permission-matrix-pin";
29
29
  const PermissionMatrix = React.forwardRef(
30
30
  function PermissionMatrix2({
31
31
  roles,
@@ -133,9 +133,9 @@ const PermissionMatrix = React.forwardRef(
133
133
  "data-slot": "permission-matrix",
134
134
  "data-editable": editable || void 0,
135
135
  className: cn("ui-permission-matrix overflow-x-auto", className),
136
- children: /* @__PURE__ */ jsxs(Table, { className: "min-w-[48rem]", "aria-label": accessibleName, children: [
136
+ children: /* @__PURE__ */ jsxs(Table, { className: "ui-permission-matrix-table", "aria-label": accessibleName, children: [
137
137
  /* @__PURE__ */ jsx(TableHeader, { className: "bg-secondary [&_tr]:bg-secondary", children: /* @__PURE__ */ jsxs(TableRow, { className: "bg-secondary hover:bg-secondary", children: [
138
- /* @__PURE__ */ jsx(TableHead, { className: cn(PIN_START, "w-64 min-w-64"), children: t("dataDisplay.permissionMatrix.permissionColumn") }),
138
+ /* @__PURE__ */ jsx(TableHead, { className: PIN_START, children: t("dataDisplay.permissionMatrix.permissionColumn") }),
139
139
  roles.map((role) => {
140
140
  const isCompared = compared.has(role.id);
141
141
  return /* @__PURE__ */ jsx(
@@ -143,7 +143,7 @@ const PermissionMatrix = React.forwardRef(
143
143
  {
144
144
  className: cn("text-center", isCompared && "bg-primary/[0.06]"),
145
145
  children: /* @__PURE__ */ jsxs("span", { className: "inline-flex flex-col items-center leading-tight", children: [
146
- /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
146
+ /* @__PURE__ */ jsxs("span", { className: "ui-permission-matrix-role", children: [
147
147
  /* @__PURE__ */ jsx(Text, { weight: "medium", children: role.name }),
148
148
  role.locked && /* @__PURE__ */ jsxs(Badge, { tone: "default", variant: "outline", children: [
149
149
  /* @__PURE__ */ jsx(Lock, { "aria-hidden": "true" }),
@@ -164,8 +164,8 @@ const PermissionMatrix = React.forwardRef(
164
164
  {
165
165
  className: cn(isDiffRow && "bg-warning/[0.07] hover:bg-warning/10"),
166
166
  children: [
167
- /* @__PURE__ */ jsx(TableCell, { className: cn(PIN_START, "w-64 min-w-64 align-middle"), children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col leading-tight", children: [
168
- /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5", children: [
167
+ /* @__PURE__ */ jsx(TableCell, { className: cn(PIN_START, "align-middle"), children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col leading-tight", children: [
168
+ /* @__PURE__ */ jsxs("span", { className: "ui-permission-matrix-name", children: [
169
169
  /* @__PURE__ */ jsx(Text, { weight: "medium", children: permission.name }),
170
170
  isDiffRow && /* @__PURE__ */ jsx(Badge, { tone: "warning", variant: "outline", children: t("dataDisplay.permissionMatrix.difference") })
171
171
  ] }),
@@ -196,7 +196,7 @@ const PermissionMatrix = React.forwardRef(
196
196
  /* @__PURE__ */ jsx(Check, { "aria-hidden": "true" }),
197
197
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("dataDisplay.permissionMatrix.granted") })
198
198
  ] }) : /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground inline-flex items-center justify-center", children: [
199
- /* @__PURE__ */ jsx(Minus, { "aria-hidden": "true", className: "size-4" }),
199
+ /* @__PURE__ */ jsx(Minus, { "aria-hidden": "true", className: "ui-permission-matrix-cell-icon" }),
200
200
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("dataDisplay.permissionMatrix.notGranted") })
201
201
  ] })
202
202
  },