@godxjp/ui 14.0.1 → 15.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.
@@ -4,12 +4,12 @@ export type { TopbarProp, TopbarProp as TopbarProps } from "../../props/componen
4
4
  * Topbar — a PURE SLOT bar. It positions three clusters (`start` / `center` / `end`) and owns the
5
5
  * bar's flex layout; it does NOT bake any chrome. There is no built-in product switcher, search
6
6
  * box, notification bell, or language picker — the CONSUMER composes those from real primitives
7
- * (brand `Logo`, a `Button` search trigger, `AppSettingPicker` for locale/theme, a `DropdownMenu`
8
- * user menu) and drops them into a slot. Whether a control is icon-only, labelled, bordered, etc.
9
- * is that control's OWN configuration — never the shell's to dictate.
7
+ * (a brand mark `Avatar`, a `Button` search trigger, `AppSettingPicker` for locale/theme, a
8
+ * `DropdownMenu` user menu) and drops them into a slot. Whether a control is icon-only, labelled,
9
+ * bordered, etc. is that control's OWN configuration — never the shell's to dictate.
10
10
  *
11
11
  * <Topbar
12
- * start={<><SidebarToggle /><Logo label="" /></>}
12
+ * start={<><SidebarToggle /><Avatar className="rounded-md"><AvatarFallback>C</AvatarFallback></Avatar></>}
13
13
  * center={<Button variant="outline" onClick={openSearch}><Search />検索</Button>}
14
14
  * end={<><AppSettingPicker kind="locale" /><UserMenu /></>}
15
15
  * />
@@ -105,13 +105,13 @@ export type SidebarProp = {
105
105
  };
106
106
  /**
107
107
  * @see Topbar — a PURE SLOT bar (no baked chrome). The library only positions three clusters; the
108
- * CONSUMER decides what goes in each (brand `Logo`, sidebar toggle, nav, a search trigger, settings
108
+ * CONSUMER decides what goes in each (a brand mark `Avatar`, sidebar toggle, nav, a search trigger, settings
109
109
  * pickers like `AppSettingPicker`, a notification button, a user menu). The shell never forces a
110
110
  * product switcher, a search box, or a language picker — those are the consumer's components,
111
111
  * configured via THEIR own props and dropped into a slot.
112
112
  */
113
113
  export type TopbarProp = Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
114
- /** Inline-start cluster — typically the sidebar toggle + brand `Logo` + primary nav. */
114
+ /** Inline-start cluster — typically the sidebar toggle + a brand mark (`Avatar`) + primary nav. */
115
115
  start?: ReactNode;
116
116
  /** Center cluster — optional (e.g. a search trigger or a page/entity switcher). */
117
117
  center?: ReactNode;
@@ -18,6 +18,12 @@ export type ColumnDefProp<T> = {
18
18
  width?: string;
19
19
  align?: ColumnAlignProp;
20
20
  hiddenOnMobile?: boolean;
21
+ /**
22
+ * List this column in DataTable.ViewOptions (the column show/hide "set view"
23
+ * menu). Defaults to true; set false to keep a column always visible (e.g. a
24
+ * primary key or a pinned actions column).
25
+ */
26
+ enableHiding?: boolean;
21
27
  /**
22
28
  * Pin the column to the inline-end edge so it stays visible while the rest of
23
29
  * the table scrolls horizontally — the standard home for a row-actions column.
@@ -15,6 +15,5 @@
15
15
  @import "./components/navigation.css";
16
16
  @import "./components/data-display.css";
17
17
  @import "./components/list-row.css";
18
- @import "./components/logo.css";
19
18
  @import "./components/data-entry.css";
20
19
  @import "./components/shell.css";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@godxjp/ui",
3
- "version": "14.0.1",
3
+ "version": "15.0.0",
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@10.29.1",
6
6
  "sideEffects": false,
@@ -54,10 +54,6 @@
54
54
  "types": "./dist/components/query/index.d.ts",
55
55
  "import": "./dist/components/query/index.js"
56
56
  },
57
- "./data-grid": {
58
- "types": "./dist/components/data-grid/index.d.ts",
59
- "import": "./dist/components/data-grid/index.js"
60
- },
61
57
  "./charts": {
62
58
  "types": "./dist/components/charts/index.d.ts",
63
59
  "import": "./dist/components/charts/index.js"
@@ -269,6 +265,7 @@
269
265
  },
270
266
  "scripts": {
271
267
  "typecheck": "tsc --noEmit -p tsconfig.json",
268
+ "typecheck:docs": "tsc --noEmit -p tsconfig.docs.json",
272
269
  "lint": "eslint .",
273
270
  "lint:fix": "eslint . --fix",
274
271
  "format": "prettier --check .",
@@ -278,7 +275,7 @@
278
275
  "test:coverage": "vitest run --coverage",
279
276
  "check:example-imports": "node scripts/check-example-imports.mjs",
280
277
  "verify": "pnpm typecheck && pnpm lint && pnpm format && pnpm build && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-token-sync && pnpm check:mcp-sync && pnpm check:mcp-orphans && pnpm check:audit-sync && pnpm test",
281
- "verify:release": "pnpm typecheck && pnpm lint && pnpm build && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-token-sync && pnpm check:mcp-sync && pnpm check:mcp-orphans && pnpm check:audit-sync && pnpm check:mcp-prop-sync && pnpm test",
278
+ "verify:release": "pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm build && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-token-sync && pnpm check:mcp-sync && pnpm check:mcp-orphans && pnpm check:audit-sync && pnpm check:mcp-prop-sync && pnpm test",
282
279
  "check:mcp-sync": "node scripts/check-mcp-sync.mjs",
283
280
  "check:mcp-orphans": "node scripts/check-mcp-orphans.mjs",
284
281
  "check:mcp-prop-sync": "node scripts/check-mcp-prop-sync.mjs",
@@ -307,7 +304,6 @@
307
304
  "peerDependencies": {
308
305
  "@hookform/resolvers": "^5.2.0",
309
306
  "@tanstack/react-query": ">=5.0.0",
310
- "@tanstack/react-table": ">=8.0.0",
311
307
  "react": ">=19.0.0",
312
308
  "react-dom": ">=19.0.0",
313
309
  "react-hook-form": "^7.76.0",
@@ -320,9 +316,6 @@
320
316
  "axe-core": "*"
321
317
  },
322
318
  "peerDependenciesMeta": {
323
- "@tanstack/react-table": {
324
- "optional": true
325
- },
326
319
  "recharts": {
327
320
  "optional": true
328
321
  },
@@ -338,6 +331,7 @@
338
331
  },
339
332
  "dependencies": {
340
333
  "@date-fns/tz": "^1.5.0",
334
+ "@tanstack/react-table": "^8.21.3",
341
335
  "@fontsource/m-plus-2": "^5.2.9",
342
336
  "@radix-ui/react-accordion": "^1.2.12",
343
337
  "@radix-ui/react-alert-dialog": "^1.1.15",
@@ -385,7 +379,6 @@
385
379
  "@hookform/resolvers": "^5.2.2",
386
380
  "@tailwindcss/vite": "^4.2.4",
387
381
  "@tanstack/react-query": "^5.100.9",
388
- "@tanstack/react-table": "^8.21.3",
389
382
  "@testing-library/jest-dom": "^6.9.1",
390
383
  "@testing-library/react": "^16.3.2",
391
384
  "@testing-library/user-event": "^14.6.1",
@@ -387,8 +387,13 @@ function walk(dir, acc = []) {
387
387
  const full = join(dir, name);
388
388
  const st = statSync(full);
389
389
  if (st.isDirectory()) {
390
+ // Test/story dirs are not product UI — never hold them to the UI-standardization rules.
391
+ if (name === "__tests__" || name === "node_modules") continue;
390
392
  walk(full, acc);
391
- } else if (name.endsWith(".tsx") || name.endsWith(".ts")) {
393
+ } else if (
394
+ (name.endsWith(".tsx") || name.endsWith(".ts")) &&
395
+ !/\.(test|spec|stories)\.tsx?$/.test(name)
396
+ ) {
392
397
  acc.push(full);
393
398
  }
394
399
  }
@@ -1,67 +0,0 @@
1
- import * as React from "react";
2
- import { type ColumnDef, type ColumnFiltersState, type OnChangeFn, type PaginationState, type RowSelectionState, type RowData, type SortingState, type VisibilityState } from "@tanstack/react-table";
3
- import type { TableDensityProp } from "../../props/vocabulary";
4
- export type DataGridDensity = TableDensityProp;
5
- export type { ColumnDef } from "@tanstack/react-table";
6
- declare module "@tanstack/react-table" {
7
- interface ColumnMeta<TData extends RowData, TValue> {
8
- label?: React.ReactNode;
9
- }
10
- }
11
- export interface DataGridProps<T> {
12
- columns: ColumnDef<T, unknown>[];
13
- data: T[];
14
- getRowId?: (row: T) => string;
15
- /** Stable id key when getRowId is omitted (defaults to "id"). */
16
- rowIdKey?: keyof T & string;
17
- sorting?: SortingState;
18
- onSortingChange?: OnChangeFn<SortingState>;
19
- columnFilters?: ColumnFiltersState;
20
- onColumnFiltersChange?: OnChangeFn<ColumnFiltersState>;
21
- globalFilter?: string;
22
- onGlobalFilterChange?: OnChangeFn<string>;
23
- pagination?: PaginationState;
24
- onPaginationChange?: OnChangeFn<PaginationState>;
25
- /** Total server row count (manual pagination) — drives the page count. */
26
- rowCount?: number;
27
- rowSelection?: RowSelectionState;
28
- onRowSelectionChange?: OnChangeFn<RowSelectionState>;
29
- enableRowSelection?: boolean;
30
- columnVisibility?: VisibilityState;
31
- onColumnVisibilityChange?: OnChangeFn<VisibilityState>;
32
- manualSorting?: boolean;
33
- manualFiltering?: boolean;
34
- manualPagination?: boolean;
35
- density?: DataGridDensity;
36
- onDensityChange?: (d: DataGridDensity) => void;
37
- loading?: boolean;
38
- empty?: React.ReactNode;
39
- onRowClick?: (row: T) => void;
40
- className?: string;
41
- children?: React.ReactNode;
42
- }
43
- interface DataGridComponent {
44
- <T>(props: DataGridProps<T>): React.ReactElement;
45
- Toolbar: React.FC<{
46
- children?: React.ReactNode;
47
- className?: string;
48
- }>;
49
- Search: React.FC<{
50
- placeholder?: string;
51
- className?: string;
52
- }>;
53
- ViewOptions: React.FC<{
54
- className?: string;
55
- }>;
56
- BulkActions: React.FC<{
57
- children: (count: number) => React.ReactNode;
58
- }>;
59
- DensityToggle: React.FC;
60
- Content: React.FC;
61
- Pagination: React.FC<{
62
- pageSizeOptions?: number[];
63
- className?: string;
64
- }>;
65
- displayName?: string;
66
- }
67
- export declare const DataGrid: DataGridComponent;
@@ -1,402 +0,0 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import * as React from "react";
3
- import {
4
- flexRender,
5
- getCoreRowModel,
6
- getFilteredRowModel,
7
- getPaginationRowModel,
8
- getSortedRowModel,
9
- useReactTable
10
- } from "@tanstack/react-table";
11
- import {
12
- ArrowDown,
13
- ArrowUp,
14
- ChevronLeft,
15
- ChevronRight,
16
- ChevronsUpDown,
17
- Layers,
18
- Layers2,
19
- SlidersHorizontal
20
- } from "lucide-react";
21
- import { useTranslation } from "../../i18n/use-translation";
22
- import { cn } from "../../lib/utils";
23
- import { densityClass } from "../../lib/variants";
24
- import { tableCellPaddingClass, tableRowHeightClass } from "../../lib/control-styles";
25
- import { Flex } from "../layout/flex";
26
- import { Button } from "../general/button";
27
- import { Checkbox } from "../data-entry/checkbox";
28
- import { SearchInput } from "../data-entry/search-input";
29
- import {
30
- Select,
31
- SelectContent,
32
- SelectItem,
33
- SelectTrigger,
34
- SelectValue
35
- } from "../data-entry/select";
36
- import {
37
- DropdownMenu,
38
- DropdownMenuCheckboxItem,
39
- DropdownMenuContent,
40
- DropdownMenuLabel,
41
- DropdownMenuSeparator,
42
- DropdownMenuTrigger
43
- } from "../navigation/dropdown-menu";
44
- import { EmptyState } from "../data-display/empty-state";
45
- import {
46
- Table,
47
- TableBody,
48
- TableCell,
49
- TableHead,
50
- TableHeader,
51
- TableRow
52
- } from "../data-display/table";
53
- const DataGridContext = React.createContext(null);
54
- function useDataGrid() {
55
- const ctx = React.useContext(DataGridContext);
56
- if (!ctx) throw new Error("DataGrid.* must be used inside <DataGrid>");
57
- return ctx;
58
- }
59
- const DataGrid = function DataGridRoot({
60
- columns,
61
- data,
62
- getRowId,
63
- rowIdKey = "id",
64
- sorting,
65
- onSortingChange,
66
- columnFilters,
67
- onColumnFiltersChange,
68
- globalFilter,
69
- onGlobalFilterChange,
70
- pagination,
71
- onPaginationChange,
72
- rowCount,
73
- rowSelection,
74
- onRowSelectionChange,
75
- enableRowSelection = false,
76
- columnVisibility: columnVisibilityProp,
77
- onColumnVisibilityChange,
78
- manualSorting = true,
79
- manualFiltering = true,
80
- manualPagination = true,
81
- density: densityProp,
82
- onDensityChange,
83
- loading = false,
84
- empty,
85
- onRowClick,
86
- className,
87
- children
88
- }) {
89
- const [internalDensity, setInternalDensity] = React.useState("comfortable");
90
- const density = densityProp ?? internalDensity;
91
- const setDensity = (d) => {
92
- if (!densityProp) setInternalDensity(d);
93
- onDensityChange?.(d);
94
- };
95
- const [internalSorting, setInternalSorting] = React.useState([]);
96
- const [internalFilters, setInternalFilters] = React.useState([]);
97
- const [internalGlobal, setInternalGlobal] = React.useState("");
98
- const [internalPagination, setInternalPagination] = React.useState({
99
- pageIndex: 0,
100
- pageSize: 10
101
- });
102
- const [internalSelection, setInternalSelection] = React.useState({});
103
- const [internalVisibility, setInternalVisibility] = React.useState({});
104
- const resolveRowId = React.useCallback(
105
- (row) => getRowId ? getRowId(row) : String(row[rowIdKey]),
106
- [getRowId, rowIdKey]
107
- );
108
- const table = useReactTable({
109
- data,
110
- columns,
111
- getRowId: resolveRowId,
112
- getCoreRowModel: getCoreRowModel(),
113
- ...manualSorting ? {} : { getSortedRowModel: getSortedRowModel() },
114
- ...manualFiltering ? {} : { getFilteredRowModel: getFilteredRowModel() },
115
- ...manualPagination ? {} : { getPaginationRowModel: getPaginationRowModel() },
116
- manualSorting,
117
- manualFiltering,
118
- manualPagination,
119
- rowCount,
120
- enableRowSelection,
121
- state: {
122
- sorting: sorting ?? internalSorting,
123
- columnFilters: columnFilters ?? internalFilters,
124
- globalFilter: globalFilter ?? internalGlobal,
125
- pagination: pagination ?? internalPagination,
126
- rowSelection: rowSelection ?? internalSelection,
127
- columnVisibility: columnVisibilityProp ?? internalVisibility
128
- },
129
- onSortingChange: onSortingChange ?? setInternalSorting,
130
- onColumnFiltersChange: onColumnFiltersChange ?? setInternalFilters,
131
- onGlobalFilterChange: onGlobalFilterChange ?? setInternalGlobal,
132
- onPaginationChange: onPaginationChange ?? setInternalPagination,
133
- onRowSelectionChange: onRowSelectionChange ?? setInternalSelection,
134
- onColumnVisibilityChange: onColumnVisibilityChange ?? setInternalVisibility
135
- });
136
- const ctx = {
137
- table,
138
- density,
139
- setDensity,
140
- loading,
141
- empty,
142
- onRowClick
143
- };
144
- return /* @__PURE__ */ jsx(DataGridContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
145
- "div",
146
- {
147
- className: cn(
148
- "ui-data-table-root",
149
- densityClass[density === "compact" ? "compact" : "comfortable"],
150
- className
151
- ),
152
- children: children ?? /* @__PURE__ */ jsx(DataGrid.Content, {})
153
- }
154
- ) });
155
- };
156
- DataGrid.displayName = "DataGrid";
157
- DataGrid.Toolbar = function DataGridToolbar({ children, className }) {
158
- return /* @__PURE__ */ jsx(
159
- Flex,
160
- {
161
- direction: "row",
162
- align: "center",
163
- justify: "between",
164
- gap: "sm",
165
- wrap: true,
166
- className: cn("ui-data-table-toolbar", className),
167
- children
168
- }
169
- );
170
- };
171
- DataGrid.Toolbar.displayName = "DataGrid.Toolbar";
172
- DataGrid.Search = function DataGridSearch({ placeholder, className }) {
173
- const { table } = useDataGrid();
174
- const { t } = useTranslation();
175
- const value = table.getState().globalFilter ?? "";
176
- return /* @__PURE__ */ jsx(
177
- SearchInput,
178
- {
179
- value,
180
- onValueChange: (q) => table.setGlobalFilter(q),
181
- onSearch: (q) => table.setGlobalFilter(q),
182
- placeholder: placeholder ?? t("dataGrid.searchPlaceholder"),
183
- ariaLabel: t("dataGrid.search"),
184
- className
185
- }
186
- );
187
- };
188
- DataGrid.Search.displayName = "DataGrid.Search";
189
- DataGrid.ViewOptions = function DataGridViewOptions({ className }) {
190
- const { table } = useDataGrid();
191
- const { t } = useTranslation();
192
- const hideable = table.getAllLeafColumns().filter((c) => c.getCanHide());
193
- if (hideable.length === 0) return null;
194
- return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
195
- /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className, children: [
196
- /* @__PURE__ */ jsx(SlidersHorizontal, { className: "size-4 shrink-0", "aria-hidden": "true" }),
197
- t("dataGrid.view")
198
- ] }) }),
199
- /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", children: [
200
- /* @__PURE__ */ jsx(DropdownMenuLabel, { children: t("dataGrid.toggleColumns") }),
201
- /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
202
- hideable.map((column) => /* @__PURE__ */ jsx(
203
- DropdownMenuCheckboxItem,
204
- {
205
- checked: column.getIsVisible(),
206
- onCheckedChange: (v) => column.toggleVisibility(!!v),
207
- children: columnLabel(column)
208
- },
209
- column.id
210
- ))
211
- ] })
212
- ] });
213
- };
214
- DataGrid.ViewOptions.displayName = "DataGrid.ViewOptions";
215
- function columnLabel(column) {
216
- const meta = column.columnDef.meta;
217
- if (meta?.label) return meta.label;
218
- if (typeof column.columnDef.header === "string") return column.columnDef.header;
219
- return column.id;
220
- }
221
- DataGrid.BulkActions = function DataGridBulkActions({ children }) {
222
- const { table } = useDataGrid();
223
- const count = table.getSelectedRowModel().rows.length;
224
- if (count === 0) return null;
225
- return /* @__PURE__ */ jsx(Flex, { direction: "row", align: "center", gap: "sm", children: children(count) });
226
- };
227
- DataGrid.BulkActions.displayName = "DataGrid.BulkActions";
228
- DataGrid.DensityToggle = function DataGridDensityToggle() {
229
- const { density, setDensity } = useDataGrid();
230
- const { t } = useTranslation();
231
- const next = density === "compact" ? "comfortable" : "compact";
232
- const Icon = density === "compact" ? Layers : Layers2;
233
- const nextLabel = next === "compact" ? t("dataTable.densityCompact") : t("dataTable.densityComfortable");
234
- return /* @__PURE__ */ jsxs(
235
- Button,
236
- {
237
- variant: "outline",
238
- size: "sm",
239
- onClick: () => setDensity(next),
240
- "aria-label": t("dataTable.densitySwitch", { density: nextLabel }),
241
- children: [
242
- /* @__PURE__ */ jsx(Icon, { className: "size-4 shrink-0", "aria-hidden": "true" }),
243
- density === "compact" ? t("dataTable.densityCompact") : t("dataTable.densityComfortable")
244
- ]
245
- }
246
- );
247
- };
248
- DataGrid.DensityToggle.displayName = "DataGrid.DensityToggle";
249
- DataGrid.Content = function DataGridContent() {
250
- const { table, loading, empty, onRowClick } = useDataGrid();
251
- const { t } = useTranslation();
252
- const leafCount = table.getVisibleLeafColumns().length;
253
- const enableSelection = table.options.enableRowSelection;
254
- const colSpan = leafCount + (enableSelection ? 1 : 0);
255
- const isInteractive = (target) => !!target.closest("button, a, input, select, textarea, [role=menuitem], [role=checkbox]");
256
- return /* @__PURE__ */ jsx("div", { className: "ui-data-table-scroll", "aria-busy": loading, children: /* @__PURE__ */ jsx("div", { className: "ui-data-table-surface min-w-[640px] sm:min-w-0", children: /* @__PURE__ */ jsxs(Table, { children: [
257
- /* @__PURE__ */ jsx(TableHeader, { className: "bg-secondary sticky top-0 z-10", children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsxs(TableRow, { children: [
258
- enableSelection && /* @__PURE__ */ jsx(TableHead, { className: "w-10", children: /* @__PURE__ */ jsx(
259
- Checkbox,
260
- {
261
- checked: table.getIsAllPageRowsSelected() ? true : table.getIsSomePageRowsSelected() ? "indeterminate" : false,
262
- onCheckedChange: (v) => table.toggleAllPageRowsSelected(!!v),
263
- "aria-label": t("dataTable.selectAll")
264
- }
265
- ) }),
266
- hg.headers.map((header) => {
267
- const canSort = header.column.getCanSort();
268
- const sorted = header.column.getIsSorted();
269
- return /* @__PURE__ */ jsx(
270
- TableHead,
271
- {
272
- "aria-sort": canSort ? sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : "none" : void 0,
273
- className: cn(canSort && "select-none"),
274
- children: header.isPlaceholder ? null : canSort ? /* @__PURE__ */ jsxs(
275
- "button",
276
- {
277
- type: "button",
278
- className: "ui-data-table-sort-button focus-visible:ring-ring inline-flex items-center gap-1 rounded-sm focus-visible:ring-2",
279
- onClick: header.column.getToggleSortingHandler(),
280
- children: [
281
- flexRender(header.column.columnDef.header, header.getContext()),
282
- sorted === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "size-3", "aria-hidden": "true" }) : sorted === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(
283
- ChevronsUpDown,
284
- {
285
- className: "text-muted-foreground size-3",
286
- "aria-hidden": "true"
287
- }
288
- )
289
- ]
290
- }
291
- ) : flexRender(header.column.columnDef.header, header.getContext())
292
- },
293
- header.id
294
- );
295
- })
296
- ] }, hg.id)) }),
297
- /* @__PURE__ */ jsx(TableBody, { children: loading ? /* @__PURE__ */ jsx(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ jsx(TableCell, { colSpan, className: "h-32 text-center", "aria-live": "polite", children: /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: t("dataTable.loading") }) }) }) : table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ jsx(TableCell, { colSpan, className: "ui-data-table-empty", "aria-live": "polite", children: empty ?? /* @__PURE__ */ jsx(EmptyState, { title: t("dataTable.empty") }) }) }) : table.getRowModel().rows.map((row) => {
298
- const selected = row.getIsSelected();
299
- return /* @__PURE__ */ jsxs(
300
- TableRow,
301
- {
302
- "data-state": selected ? "selected" : void 0,
303
- tabIndex: onRowClick ? 0 : void 0,
304
- onClick: (e) => {
305
- if (isInteractive(e.target)) return;
306
- onRowClick?.(row.original);
307
- },
308
- onKeyDown: onRowClick ? (e) => {
309
- if (e.key !== "Enter" && e.key !== " ") return;
310
- if (e.target !== e.currentTarget) return;
311
- e.preventDefault();
312
- onRowClick(row.original);
313
- } : void 0,
314
- className: cn(
315
- tableRowHeightClass,
316
- onRowClick && "hover:bg-muted/50 focus-visible:ring-ring cursor-pointer focus-visible:ring-2 focus-visible:outline-none focus-visible:ring-inset",
317
- selected && "bg-muted/30"
318
- ),
319
- children: [
320
- enableSelection && /* @__PURE__ */ jsx(TableCell, { className: tableCellPaddingClass, children: /* @__PURE__ */ jsx(
321
- Checkbox,
322
- {
323
- checked: selected,
324
- onCheckedChange: (v) => row.toggleSelected(!!v),
325
- "aria-label": t("dataTable.selectRow", { id: row.id }),
326
- onClick: (e) => e.stopPropagation()
327
- }
328
- ) }),
329
- row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(TableCell, { className: tableCellPaddingClass, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
330
- ]
331
- },
332
- row.id
333
- );
334
- }) })
335
- ] }) }) });
336
- };
337
- DataGrid.Content.displayName = "DataGrid.Content";
338
- DataGrid.Pagination = function DataGridPagination({
339
- pageSizeOptions = [10, 20, 50, 100],
340
- className
341
- }) {
342
- const { table } = useDataGrid();
343
- const { t } = useTranslation();
344
- const { pageIndex, pageSize } = table.getState().pagination;
345
- const pageCount = table.getPageCount();
346
- return /* @__PURE__ */ jsxs(
347
- Flex,
348
- {
349
- direction: "row",
350
- align: "center",
351
- justify: "between",
352
- gap: "md",
353
- wrap: true,
354
- className: cn("ui-data-table-pagination", className),
355
- children: [
356
- /* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", gap: "sm", children: [
357
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: t("dataGrid.rowsPerPage") }),
358
- /* @__PURE__ */ jsxs(
359
- Select,
360
- {
361
- value: String(pageSize),
362
- onValueChange: (v) => table.setPageSize(Number(v)),
363
- children: [
364
- /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", "aria-label": t("dataGrid.rowsPerPage"), className: "tabular-nums", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
365
- /* @__PURE__ */ jsx(SelectContent, { children: pageSizeOptions.map((n) => /* @__PURE__ */ jsx(SelectItem, { value: String(n), className: "tabular-nums", children: n }, n)) })
366
- ]
367
- }
368
- )
369
- ] }),
370
- /* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", gap: "sm", children: [
371
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm tabular-nums", children: t("dataGrid.pageOf", { page: pageIndex + 1, total: Math.max(1, pageCount) }) }),
372
- /* @__PURE__ */ jsx(
373
- Button,
374
- {
375
- variant: "outline",
376
- size: "icon",
377
- disabled: !table.getCanPreviousPage(),
378
- onClick: () => table.previousPage(),
379
- "aria-label": t("common.previous") ?? "Previous",
380
- children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4", "aria-hidden": "true" })
381
- }
382
- ),
383
- /* @__PURE__ */ jsx(
384
- Button,
385
- {
386
- variant: "outline",
387
- size: "icon",
388
- disabled: !table.getCanNextPage(),
389
- onClick: () => table.nextPage(),
390
- "aria-label": t("common.next") ?? "Next",
391
- children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4", "aria-hidden": "true" })
392
- }
393
- )
394
- ] })
395
- ]
396
- }
397
- );
398
- };
399
- DataGrid.Pagination.displayName = "DataGrid.Pagination";
400
- export {
401
- DataGrid
402
- };
@@ -1,2 +0,0 @@
1
- export { DataGrid } from "./data-grid";
2
- export type { DataGridProps, DataGridDensity, ColumnDef } from "./data-grid";
@@ -1,4 +0,0 @@
1
- import { DataGrid } from "./data-grid";
2
- export {
3
- DataGrid
4
- };
@@ -1,28 +0,0 @@
1
- import * as React from "react";
2
- import type { ShapeProp } from "../../props/vocabulary";
3
- declare const logoVariants: (props?: ({
4
- size?: "xs" | "sm" | "md" | "lg" | null | undefined;
5
- shape?: "default" | "pill" | "sharp" | null | undefined;
6
- } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
- export interface LogoProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
8
- /**
9
- * Accessible product name. When set, the mark exposes `role="img"` + `aria-label` (use this when
10
- * the Logo IS the accessible name — e.g. a home link). When omitted the mark is `aria-hidden`
11
- * (decorative — assume an adjacent wordmark provides the name).
12
- */
13
- label?: string;
14
- /** Box size — maps to the square size scale. Default `md`. */
15
- size?: "xs" | "sm" | "md" | "lg";
16
- /** Corner shape — `default` (--logo-radius) · `pill` (fully rounded) · `sharp` (square). */
17
- shape?: ShapeProp;
18
- /** The mark — a short lettermark string (default `"G"`) or a custom SVG/image node. */
19
- glyph?: React.ReactNode;
20
- }
21
- /**
22
- * Logo — the product brand-mark primitive. Use it INSTEAD of a hand-rolled
23
- * `<span className="flex size-[2rem] rounded-md bg-primary font-bold …">g</span>` (typography-on-span,
24
- * literal size/radius — cardinal rules #42/#46). Renders the lettermark (or a custom SVG) in a
25
- * tokenized box that a service rethemes via `--primary` (fill) and `--logo-radius` (corner).
26
- */
27
- export declare const Logo: React.ForwardRefExoticComponent<LogoProps & React.RefAttributes<HTMLSpanElement>>;
28
- export { logoVariants };