@rovula/ui 0.1.29 → 0.1.31
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.
- package/dist/cjs/bundle.css +21 -0
- package/dist/cjs/bundle.js +14 -9235
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/DataTable/DataTable.d.ts +3 -3
- package/dist/cjs/types/components/DataTable/DataTable.stories.d.ts +29 -3
- package/dist/cjs/types/components/Icon/Icon.stories.d.ts +4 -0
- package/dist/components/DataTable/DataTable.js +16 -6
- package/dist/components/DataTable/DataTable.stories.js +60 -0
- package/dist/components/Icon/Icon.stories.js +21 -2
- package/dist/components/Table/Table.js +5 -5
- package/dist/esm/bundle.css +21 -0
- package/dist/esm/bundle.js +14 -9235
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/DataTable/DataTable.d.ts +3 -3
- package/dist/esm/types/components/DataTable/DataTable.stories.d.ts +29 -3
- package/dist/esm/types/components/Icon/Icon.stories.d.ts +4 -0
- package/dist/index.d.ts +3 -3
- package/dist/src/theme/global.css +28 -0
- package/package.json +3 -3
- package/src/components/DataTable/DataTable.stories.tsx +141 -0
- package/src/components/DataTable/DataTable.tsx +35 -20
- package/src/components/Icon/Icon.stories.tsx +77 -5
- package/src/components/Table/Table.tsx +54 -42
|
@@ -130,11 +130,11 @@ export interface DataTableProps<TData, TValue> extends DataTableEditingProps<TDa
|
|
|
130
130
|
/** Add vertical column dividers */
|
|
131
131
|
divided?: boolean;
|
|
132
132
|
/** Return a className string to apply to a specific body row. */
|
|
133
|
-
rowClassName?: (row: Row<TData>, index: number) => string | undefined;
|
|
133
|
+
rowClassName?: string | ((row: Row<TData>, index: number) => string | undefined);
|
|
134
134
|
/** Return a className string to apply to a specific body cell. */
|
|
135
|
-
cellClassName?: (cell: Cell<TData, unknown>, row: Row<TData>) => string | undefined;
|
|
135
|
+
cellClassName?: string | ((cell: Cell<TData, unknown>, row: Row<TData>) => string | undefined);
|
|
136
136
|
/** Return a className string to apply to a specific column header cell (`<th>`). */
|
|
137
|
-
headerCellClassName?: (header: Header<TData, unknown>) => string | undefined;
|
|
137
|
+
headerCellClassName?: string | ((header: Header<TData, unknown>) => string | undefined);
|
|
138
138
|
/** Additional className for the header section (`<thead>`). */
|
|
139
139
|
headerClassName?: string;
|
|
140
140
|
/** Additional className for the header row (`<tr>` inside `<thead>`). */
|
|
@@ -69,9 +69,9 @@ declare const meta: {
|
|
|
69
69
|
surface?: "default" | "panel" | undefined;
|
|
70
70
|
striped?: boolean | undefined;
|
|
71
71
|
divided?: boolean | undefined;
|
|
72
|
-
rowClassName?: ((row: Row<unknown>, index: number) => string | undefined) | undefined;
|
|
73
|
-
cellClassName?: ((cell: import("@tanstack/react-table").Cell<unknown, unknown>, row: Row<unknown>) => string | undefined) | undefined;
|
|
74
|
-
headerCellClassName?: ((header: import("@tanstack/react-table").Header<unknown, unknown>) => string | undefined) | undefined;
|
|
72
|
+
rowClassName?: string | ((row: Row<unknown>, index: number) => string | undefined) | undefined;
|
|
73
|
+
cellClassName?: string | ((cell: import("@tanstack/react-table").Cell<unknown, unknown>, row: Row<unknown>) => string | undefined) | undefined;
|
|
74
|
+
headerCellClassName?: string | ((header: import("@tanstack/react-table").Header<unknown, unknown>) => string | undefined) | undefined;
|
|
75
75
|
headerClassName?: string | undefined;
|
|
76
76
|
headerRowClassName?: string | undefined;
|
|
77
77
|
sortIndicatorVisibility?: "always" | "hover" | undefined;
|
|
@@ -94,6 +94,14 @@ declare const meta: {
|
|
|
94
94
|
export default meta;
|
|
95
95
|
/** Default — striped rows + column dividers, all columns sortable. */
|
|
96
96
|
export declare const Default: StoryObj;
|
|
97
|
+
/**
|
|
98
|
+
* Matches the Figma "Projects" page design — striped alternating rows,
|
|
99
|
+
* column dividers, row actions (more + navigate), client pagination,
|
|
100
|
+
* and a rounded bordered frame.
|
|
101
|
+
*
|
|
102
|
+
* Design ref: Xspector-New / node 11786-14865
|
|
103
|
+
*/
|
|
104
|
+
export declare const FigmaProjectsPage: StoryObj;
|
|
97
105
|
/** Empty state — displayed when `data` is an empty array. */
|
|
98
106
|
export declare const Empty: StoryObj;
|
|
99
107
|
/** Non-striped with column dividers only. */
|
|
@@ -252,6 +260,24 @@ export declare const TableLayoutComparison: StoryObj;
|
|
|
252
260
|
* - The **"Type"** cells for ROV are highlighted with an info tint.
|
|
253
261
|
*/
|
|
254
262
|
export declare const WithCustomRowAndCellClassName: StoryObj;
|
|
263
|
+
/**
|
|
264
|
+
* Showcase overriding header and body row heights via className props.
|
|
265
|
+
*
|
|
266
|
+
* The base `TableHead` uses `h-[44px] typography-body2` and `TableCell`
|
|
267
|
+
* uses `h-[42px] typography-body3`.
|
|
268
|
+
*
|
|
269
|
+
* `cn()` is configured with a custom `typography` class-group so
|
|
270
|
+
* `tailwind-merge` correctly deduplicates conflicting `typography-*`
|
|
271
|
+
* utilities (e.g. `typography-small2` replaces `typography-body2`).
|
|
272
|
+
*
|
|
273
|
+
* **Note:** `<th>` / `<td>` elements treat `height` as a minimum —
|
|
274
|
+
* to go smaller than the default, internal content (sort icon, badges)
|
|
275
|
+
* must also fit. Compact swaps to `typography-small2` (12px) text and
|
|
276
|
+
* reduces padding to reclaim space.
|
|
277
|
+
*
|
|
278
|
+
* Three sizes: **Compact**, **Default**, **Comfortable**.
|
|
279
|
+
*/
|
|
280
|
+
export declare const CustomRowAndHeaderSize: StoryObj;
|
|
255
281
|
/**
|
|
256
282
|
* Data management table — Figma **Xspector-New**:
|
|
257
283
|
* [full frame](https://www.figma.com/design/99rq6FbfPx6hgPS0VCvHJh/Xspector-New?node-id=11965-17125),
|
|
@@ -510,6 +510,10 @@ export declare const LucideIconBrowser: {
|
|
|
510
510
|
args: {};
|
|
511
511
|
render: () => import("react/jsx-runtime").JSX.Element;
|
|
512
512
|
};
|
|
513
|
+
export declare const LucideIconAllBrowser: {
|
|
514
|
+
args: {};
|
|
515
|
+
render: () => import("react/jsx-runtime").JSX.Element;
|
|
516
|
+
};
|
|
513
517
|
export declare const PreviewMaterialIcon: {
|
|
514
518
|
args: {};
|
|
515
519
|
render: (args: {}) => import("react/jsx-runtime").JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -1036,11 +1036,11 @@ interface DataTableProps<TData, TValue> extends DataTableEditingProps<TData> {
|
|
|
1036
1036
|
/** Add vertical column dividers */
|
|
1037
1037
|
divided?: boolean;
|
|
1038
1038
|
/** Return a className string to apply to a specific body row. */
|
|
1039
|
-
rowClassName?: (row: Row<TData>, index: number) => string | undefined;
|
|
1039
|
+
rowClassName?: string | ((row: Row<TData>, index: number) => string | undefined);
|
|
1040
1040
|
/** Return a className string to apply to a specific body cell. */
|
|
1041
|
-
cellClassName?: (cell: Cell<TData, unknown>, row: Row<TData>) => string | undefined;
|
|
1041
|
+
cellClassName?: string | ((cell: Cell<TData, unknown>, row: Row<TData>) => string | undefined);
|
|
1042
1042
|
/** Return a className string to apply to a specific column header cell (`<th>`). */
|
|
1043
|
-
headerCellClassName?: (header: Header<TData, unknown>) => string | undefined;
|
|
1043
|
+
headerCellClassName?: string | ((header: Header<TData, unknown>) => string | undefined);
|
|
1044
1044
|
/** Additional className for the header section (`<thead>`). */
|
|
1045
1045
|
headerClassName?: string;
|
|
1046
1046
|
/** Additional className for the header row (`<tr>` inside `<thead>`). */
|
|
@@ -4354,6 +4354,10 @@ input[type=number] {
|
|
|
4354
4354
|
height: 280px;
|
|
4355
4355
|
}
|
|
4356
4356
|
|
|
4357
|
+
.h-\[28px\] {
|
|
4358
|
+
height: 28px;
|
|
4359
|
+
}
|
|
4360
|
+
|
|
4357
4361
|
.h-\[2px\] {
|
|
4358
4362
|
height: 2px;
|
|
4359
4363
|
}
|
|
@@ -4386,10 +4390,18 @@ input[type=number] {
|
|
|
4386
4390
|
height: 48px;
|
|
4387
4391
|
}
|
|
4388
4392
|
|
|
4393
|
+
.h-\[50px\] {
|
|
4394
|
+
height: 50px;
|
|
4395
|
+
}
|
|
4396
|
+
|
|
4389
4397
|
.h-\[54px\] {
|
|
4390
4398
|
height: 54px;
|
|
4391
4399
|
}
|
|
4392
4400
|
|
|
4401
|
+
.h-\[56px\] {
|
|
4402
|
+
height: 56px;
|
|
4403
|
+
}
|
|
4404
|
+
|
|
4393
4405
|
.h-\[64px\] {
|
|
4394
4406
|
height: 64px;
|
|
4395
4407
|
}
|
|
@@ -5134,6 +5146,10 @@ input[type=number] {
|
|
|
5134
5146
|
white-space: nowrap;
|
|
5135
5147
|
}
|
|
5136
5148
|
|
|
5149
|
+
.whitespace-pre {
|
|
5150
|
+
white-space: pre;
|
|
5151
|
+
}
|
|
5152
|
+
|
|
5137
5153
|
.whitespace-pre-line {
|
|
5138
5154
|
white-space: pre-line;
|
|
5139
5155
|
}
|
|
@@ -8267,6 +8283,14 @@ input[type=number] {
|
|
|
8267
8283
|
font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction);
|
|
8268
8284
|
}
|
|
8269
8285
|
|
|
8286
|
+
.leading-\[18px\] {
|
|
8287
|
+
line-height: 18px;
|
|
8288
|
+
}
|
|
8289
|
+
|
|
8290
|
+
.leading-\[20px\] {
|
|
8291
|
+
line-height: 20px;
|
|
8292
|
+
}
|
|
8293
|
+
|
|
8270
8294
|
.leading-\[3rem\] {
|
|
8271
8295
|
line-height: 3rem;
|
|
8272
8296
|
}
|
|
@@ -12361,6 +12385,10 @@ input[type=number] {
|
|
|
12361
12385
|
border-bottom-width: 0px;
|
|
12362
12386
|
}
|
|
12363
12387
|
|
|
12388
|
+
.\[\&_tr\>th\]\:box-border tr>th {
|
|
12389
|
+
box-sizing: border-box;
|
|
12390
|
+
}
|
|
12391
|
+
|
|
12364
12392
|
.\[\&_tr\>th\]\:border-b tr>th {
|
|
12365
12393
|
border-bottom-width: 1px;
|
|
12366
12394
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rovula/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.31",
|
|
4
4
|
"main": "dist/cjs/bundle.js",
|
|
5
5
|
"module": "dist/esm/bundle.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
"@vitejs/plugin-react": "^4.3.4",
|
|
64
64
|
"autoprefixer": "^10.4.19",
|
|
65
65
|
"babel-loader": "^9.1.3",
|
|
66
|
-
"jsdom": "^26.0.0",
|
|
67
66
|
"chromatic": "^11.7.1",
|
|
68
67
|
"copyfiles": "^2.4.1",
|
|
69
68
|
"css-loader": "^7.1.2",
|
|
69
|
+
"jsdom": "^26.0.0",
|
|
70
70
|
"postcss": "^8.4.38",
|
|
71
71
|
"rollup": "^4.18.0",
|
|
72
72
|
"rollup-plugin-dts": "^6.1.1",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"class-variance-authority": "^0.7.0",
|
|
112
112
|
"clsx": "^2.1.1",
|
|
113
113
|
"date-fns": "^3.6.0",
|
|
114
|
-
"lucide-react": "^
|
|
114
|
+
"lucide-react": "^1.7.0",
|
|
115
115
|
"react": "^17.0.0 || ^18.0.0",
|
|
116
116
|
"react-day-picker": "^9.0.7",
|
|
117
117
|
"react-dom": "^17.0.0 || ^18.0.0",
|
|
@@ -320,6 +320,45 @@ export const Default: StoryObj = {
|
|
|
320
320
|
),
|
|
321
321
|
};
|
|
322
322
|
|
|
323
|
+
/**
|
|
324
|
+
* Matches the Figma "Projects" page design — striped alternating rows,
|
|
325
|
+
* column dividers, row actions (more + navigate), client pagination,
|
|
326
|
+
* and a rounded bordered frame.
|
|
327
|
+
*
|
|
328
|
+
* Design ref: Xspector-New / node 11786-14865
|
|
329
|
+
*/
|
|
330
|
+
export const FigmaProjectsPage: StoryObj = {
|
|
331
|
+
render: () => {
|
|
332
|
+
const figmaProjectColumns: ColumnDef<Project>[] = [
|
|
333
|
+
{ accessorKey: "name", header: "Project name" },
|
|
334
|
+
{ accessorKey: "type", header: "Type", size: 120 },
|
|
335
|
+
{ accessorKey: "subtype", header: "Subtype" },
|
|
336
|
+
{ accessorKey: "createdDate", header: "Created date", size: 180 },
|
|
337
|
+
{
|
|
338
|
+
accessorKey: "status",
|
|
339
|
+
header: "Status",
|
|
340
|
+
size: 200,
|
|
341
|
+
cell: ({ row }) => <StatusBadge status={row.original.status} />,
|
|
342
|
+
},
|
|
343
|
+
];
|
|
344
|
+
|
|
345
|
+
return (
|
|
346
|
+
<DataTable
|
|
347
|
+
columns={figmaProjectColumns}
|
|
348
|
+
data={projectData}
|
|
349
|
+
bordered
|
|
350
|
+
striped
|
|
351
|
+
divided
|
|
352
|
+
tableLayout="fixed"
|
|
353
|
+
paginationMode="client"
|
|
354
|
+
pageSizeOptions={[5, 10, 20]}
|
|
355
|
+
rowActions={(row) => <ProjectRowActions row={row} />}
|
|
356
|
+
onSorting={(s) => console.log("sort", s)}
|
|
357
|
+
/>
|
|
358
|
+
);
|
|
359
|
+
},
|
|
360
|
+
};
|
|
361
|
+
|
|
323
362
|
/** Empty state — displayed when `data` is an empty array. */
|
|
324
363
|
export const Empty: StoryObj = {
|
|
325
364
|
render: () => (
|
|
@@ -1435,6 +1474,108 @@ export const WithCustomRowAndCellClassName: StoryObj = {
|
|
|
1435
1474
|
),
|
|
1436
1475
|
};
|
|
1437
1476
|
|
|
1477
|
+
// ---------------------------------------------------------------------------
|
|
1478
|
+
// 13b. Custom body row size and header size
|
|
1479
|
+
// ---------------------------------------------------------------------------
|
|
1480
|
+
|
|
1481
|
+
/**
|
|
1482
|
+
* Showcase overriding header and body row heights via className props.
|
|
1483
|
+
*
|
|
1484
|
+
* The base `TableHead` uses `h-[44px] typography-body2` and `TableCell`
|
|
1485
|
+
* uses `h-[42px] typography-body3`.
|
|
1486
|
+
*
|
|
1487
|
+
* `cn()` is configured with a custom `typography` class-group so
|
|
1488
|
+
* `tailwind-merge` correctly deduplicates conflicting `typography-*`
|
|
1489
|
+
* utilities (e.g. `typography-small2` replaces `typography-body2`).
|
|
1490
|
+
*
|
|
1491
|
+
* **Note:** `<th>` / `<td>` elements treat `height` as a minimum —
|
|
1492
|
+
* to go smaller than the default, internal content (sort icon, badges)
|
|
1493
|
+
* must also fit. Compact swaps to `typography-small2` (12px) text and
|
|
1494
|
+
* reduces padding to reclaim space.
|
|
1495
|
+
*
|
|
1496
|
+
* Three sizes: **Compact**, **Default**, **Comfortable**.
|
|
1497
|
+
*/
|
|
1498
|
+
export const CustomRowAndHeaderSize: StoryObj = {
|
|
1499
|
+
render: () => {
|
|
1500
|
+
const compactColumns: ColumnDef<Project>[] = [
|
|
1501
|
+
{ accessorKey: "name", header: "Project name" },
|
|
1502
|
+
{ accessorKey: "type", header: "Type" },
|
|
1503
|
+
{ accessorKey: "subtype", header: "Subtype" },
|
|
1504
|
+
{ accessorKey: "createdDate", header: "Created date" },
|
|
1505
|
+
{
|
|
1506
|
+
accessorKey: "status",
|
|
1507
|
+
header: "Status",
|
|
1508
|
+
cell: ({ row }) => (
|
|
1509
|
+
<span
|
|
1510
|
+
className={`inline-flex items-center px-2 py-0.5 rounded typography-small2 ${
|
|
1511
|
+
statusCls[row.original.status]
|
|
1512
|
+
}`}
|
|
1513
|
+
>
|
|
1514
|
+
{row.original.status}
|
|
1515
|
+
</span>
|
|
1516
|
+
),
|
|
1517
|
+
},
|
|
1518
|
+
];
|
|
1519
|
+
|
|
1520
|
+
return (
|
|
1521
|
+
<div className="flex flex-col gap-8 h-full">
|
|
1522
|
+
<div className="flex flex-col gap-2 flex-1 min-h-0">
|
|
1523
|
+
<p className="typography-subtitle1 text-text-contrast-max px-1">
|
|
1524
|
+
Compact{" "}
|
|
1525
|
+
<span className="typography-small2 text-text-g-contrast-medium">
|
|
1526
|
+
— Header 32px · Row 28px · typography-small2 (12px)
|
|
1527
|
+
</span>
|
|
1528
|
+
</p>
|
|
1529
|
+
<DataTable
|
|
1530
|
+
columns={compactColumns}
|
|
1531
|
+
data={projectData}
|
|
1532
|
+
striped
|
|
1533
|
+
divided
|
|
1534
|
+
headerCellClassName="h-[32px] typography-small2"
|
|
1535
|
+
cellClassName="h-[28px] typography-small2"
|
|
1536
|
+
onSorting={(s) => console.log("sort", s)}
|
|
1537
|
+
/>
|
|
1538
|
+
</div>
|
|
1539
|
+
|
|
1540
|
+
<div className="flex flex-col gap-2 flex-1 min-h-0">
|
|
1541
|
+
<p className="typography-subtitle1 text-text-contrast-max px-1">
|
|
1542
|
+
Default{" "}
|
|
1543
|
+
<span className="typography-small2 text-text-g-contrast-medium">
|
|
1544
|
+
— Header 44px · Row 42px · typography-body2 / body3
|
|
1545
|
+
</span>
|
|
1546
|
+
</p>
|
|
1547
|
+
<DataTable
|
|
1548
|
+
columns={projectColumns}
|
|
1549
|
+
data={projectData}
|
|
1550
|
+
striped
|
|
1551
|
+
divided
|
|
1552
|
+
onSorting={(s) => console.log("sort", s)}
|
|
1553
|
+
/>
|
|
1554
|
+
</div>
|
|
1555
|
+
|
|
1556
|
+
<div className="flex flex-col gap-2 flex-1 min-h-0">
|
|
1557
|
+
<p className="typography-subtitle1 text-text-contrast-max px-1">
|
|
1558
|
+
Comfortable{" "}
|
|
1559
|
+
<span className="typography-small2 text-text-g-contrast-medium">
|
|
1560
|
+
— Header 56px · Row 50px · typography-subtitle2 / subtitle4 (16px
|
|
1561
|
+
/ 14px)
|
|
1562
|
+
</span>
|
|
1563
|
+
</p>
|
|
1564
|
+
<DataTable
|
|
1565
|
+
columns={projectColumns}
|
|
1566
|
+
data={projectData}
|
|
1567
|
+
striped
|
|
1568
|
+
divided
|
|
1569
|
+
headerCellClassName="h-[56px] typography-subtitle2"
|
|
1570
|
+
cellClassName="h-[50px] typography-subtitle4"
|
|
1571
|
+
onSorting={(s) => console.log("sort", s)}
|
|
1572
|
+
/>
|
|
1573
|
+
</div>
|
|
1574
|
+
</div>
|
|
1575
|
+
);
|
|
1576
|
+
},
|
|
1577
|
+
};
|
|
1578
|
+
|
|
1438
1579
|
// ---------------------------------------------------------------------------
|
|
1439
1580
|
// 14. Real-world example — Data Management (Figma: Xspector-New → Data management)
|
|
1440
1581
|
// ---------------------------------------------------------------------------
|
|
@@ -136,10 +136,9 @@ function renderDataTableBodyCells<TData extends RowData>(opts: {
|
|
|
136
136
|
resizable: boolean;
|
|
137
137
|
tableLayout: "auto" | "fixed" | "equal";
|
|
138
138
|
resizableSlackGrowColId: string | null;
|
|
139
|
-
cellClassName?:
|
|
140
|
-
|
|
141
|
-
row: Row<TData
|
|
142
|
-
) => string | undefined;
|
|
139
|
+
cellClassName?:
|
|
140
|
+
| string
|
|
141
|
+
| ((cell: Cell<TData, unknown>, row: Row<TData>) => string | undefined);
|
|
143
142
|
onCellClick?: (
|
|
144
143
|
cell: Cell<TData, unknown>,
|
|
145
144
|
row: Row<TData>,
|
|
@@ -186,7 +185,9 @@ function renderDataTableBodyCells<TData extends RowData>(opts: {
|
|
|
186
185
|
className={cn(
|
|
187
186
|
columnMetaAlignClass(cell.column.columnDef.meta),
|
|
188
187
|
cell.column.columnDef.meta?.cellClassName,
|
|
189
|
-
cellClassName
|
|
188
|
+
typeof cellClassName === "function"
|
|
189
|
+
? cellClassName(cell, row)
|
|
190
|
+
: cellClassName,
|
|
190
191
|
)}
|
|
191
192
|
onClick={
|
|
192
193
|
onCellClick
|
|
@@ -442,14 +443,17 @@ export interface DataTableProps<TData, TValue>
|
|
|
442
443
|
/** Add vertical column dividers */
|
|
443
444
|
divided?: boolean;
|
|
444
445
|
/** Return a className string to apply to a specific body row. */
|
|
445
|
-
rowClassName?:
|
|
446
|
+
rowClassName?:
|
|
447
|
+
| string
|
|
448
|
+
| ((row: Row<TData>, index: number) => string | undefined);
|
|
446
449
|
/** Return a className string to apply to a specific body cell. */
|
|
447
|
-
cellClassName?:
|
|
448
|
-
|
|
449
|
-
row: Row<TData
|
|
450
|
-
) => string | undefined;
|
|
450
|
+
cellClassName?:
|
|
451
|
+
| string
|
|
452
|
+
| ((cell: Cell<TData, unknown>, row: Row<TData>) => string | undefined);
|
|
451
453
|
/** Return a className string to apply to a specific column header cell (`<th>`). */
|
|
452
|
-
headerCellClassName?:
|
|
454
|
+
headerCellClassName?:
|
|
455
|
+
| string
|
|
456
|
+
| ((header: Header<TData, unknown>) => string | undefined);
|
|
453
457
|
/** Additional className for the header section (`<thead>`). */
|
|
454
458
|
headerClassName?: string;
|
|
455
459
|
/** Additional className for the header row (`<tr>` inside `<thead>`). */
|
|
@@ -1822,15 +1826,17 @@ export function DataTable<TData, TValue>({
|
|
|
1822
1826
|
colSpan={header.colSpan}
|
|
1823
1827
|
style={headerStyle}
|
|
1824
1828
|
className={cn(
|
|
1825
|
-
"relative overflow-visible group/col",
|
|
1829
|
+
"relative overflow-visible group/col whitespace-pre",
|
|
1826
1830
|
isResizing && "select-none",
|
|
1827
1831
|
header.column.columnDef.meta?.headerCellClassName,
|
|
1828
|
-
headerCellClassName
|
|
1832
|
+
typeof headerCellClassName === "function"
|
|
1833
|
+
? headerCellClassName(header)
|
|
1834
|
+
: headerCellClassName,
|
|
1829
1835
|
)}
|
|
1830
1836
|
>
|
|
1831
1837
|
<div className="flex flex-row items-center gap-1 group/header">
|
|
1832
1838
|
{/* Column label — flex-1 pushes sort + ⋮ to the right */}
|
|
1833
|
-
<
|
|
1839
|
+
<span
|
|
1834
1840
|
className={cn(
|
|
1835
1841
|
"flex flex-1 flex-row items-center overflow-hidden",
|
|
1836
1842
|
canSort && "cursor-pointer select-none",
|
|
@@ -1846,13 +1852,13 @@ export function DataTable<TData, TValue>({
|
|
|
1846
1852
|
header.column.columnDef.header,
|
|
1847
1853
|
header.getContext(),
|
|
1848
1854
|
)}
|
|
1849
|
-
</
|
|
1855
|
+
</span>
|
|
1850
1856
|
|
|
1851
1857
|
{/* Sort button — visible when sorted; shown on hover when unsorted */}
|
|
1852
1858
|
{canSort && (
|
|
1853
1859
|
<ActionButton
|
|
1854
1860
|
variant="icon"
|
|
1855
|
-
size="
|
|
1861
|
+
size="xs"
|
|
1856
1862
|
className={cn(
|
|
1857
1863
|
"shrink-0 transition-opacity",
|
|
1858
1864
|
isSorted
|
|
@@ -2018,7 +2024,10 @@ export function DataTable<TData, TValue>({
|
|
|
2018
2024
|
* - TableBody nth-child alternation applies across all rows (parents + children)
|
|
2019
2025
|
* - Row borders suppressed
|
|
2020
2026
|
*/}
|
|
2021
|
-
<TableBody
|
|
2027
|
+
<TableBody
|
|
2028
|
+
striped={striped}
|
|
2029
|
+
data-testid={testId ? `${testId}-tbody` : undefined}
|
|
2030
|
+
>
|
|
2022
2031
|
{!isEmpty ? (
|
|
2023
2032
|
virtualized ? (
|
|
2024
2033
|
(() => {
|
|
@@ -2066,7 +2075,9 @@ export function DataTable<TData, TValue>({
|
|
|
2066
2075
|
className: cn(
|
|
2067
2076
|
rowBg,
|
|
2068
2077
|
onRowClick && "cursor-pointer",
|
|
2069
|
-
rowClassName
|
|
2078
|
+
typeof rowClassName === "function"
|
|
2079
|
+
? rowClassName(row, item.index)
|
|
2080
|
+
: rowClassName,
|
|
2070
2081
|
),
|
|
2071
2082
|
onClick: onRowClick
|
|
2072
2083
|
? (e: React.MouseEvent<HTMLTableRowElement>) =>
|
|
@@ -2142,7 +2153,9 @@ export function DataTable<TData, TValue>({
|
|
|
2142
2153
|
className: cn(
|
|
2143
2154
|
rowBg,
|
|
2144
2155
|
onRowClick && "cursor-pointer",
|
|
2145
|
-
rowClassName
|
|
2156
|
+
typeof rowClassName === "function"
|
|
2157
|
+
? rowClassName(row, rowIndex)
|
|
2158
|
+
: rowClassName,
|
|
2146
2159
|
),
|
|
2147
2160
|
onClick: onRowClick
|
|
2148
2161
|
? (e: React.MouseEvent<HTMLTableRowElement>) =>
|
|
@@ -2207,7 +2220,9 @@ export function DataTable<TData, TValue>({
|
|
|
2207
2220
|
className={cn(
|
|
2208
2221
|
rowBg,
|
|
2209
2222
|
onRowClick && "cursor-pointer",
|
|
2210
|
-
rowClassName
|
|
2223
|
+
typeof rowClassName === "function"
|
|
2224
|
+
? rowClassName(row, rowIndex)
|
|
2225
|
+
: rowClassName,
|
|
2211
2226
|
)}
|
|
2212
2227
|
data-highlighted={isHighlighted ? "true" : undefined}
|
|
2213
2228
|
onClick={
|
|
@@ -390,13 +390,40 @@ export const PreviewLucideIcon = {
|
|
|
390
390
|
<div className="flex flex-col justify-start gap-4 w-full h-full">
|
|
391
391
|
<h4>Lucide icons (designer set)</h4>
|
|
392
392
|
<p className="text-sm text-gray-500">
|
|
393
|
-
Names from
|
|
393
|
+
Names from{" "}
|
|
394
|
+
<a
|
|
395
|
+
href="https://lucide.dev/icons"
|
|
396
|
+
target="_blank"
|
|
397
|
+
rel="noreferrer"
|
|
398
|
+
className="underline"
|
|
399
|
+
>
|
|
400
|
+
lucide.dev/icons
|
|
401
|
+
</a>
|
|
402
|
+
. Use <code>getLucideIconNames()</code> for full list.
|
|
394
403
|
</p>
|
|
395
404
|
{LUCIDE_DESIGNER_ICONS.map((iconName) => (
|
|
396
405
|
<div key={iconName} className="flex flex-row gap-6 items-center">
|
|
397
|
-
<Icon
|
|
398
|
-
|
|
399
|
-
|
|
406
|
+
<Icon
|
|
407
|
+
{...args}
|
|
408
|
+
type="lucide"
|
|
409
|
+
name={iconName}
|
|
410
|
+
variant="outline"
|
|
411
|
+
size="sm"
|
|
412
|
+
/>
|
|
413
|
+
<Icon
|
|
414
|
+
{...args}
|
|
415
|
+
type="lucide"
|
|
416
|
+
name={iconName}
|
|
417
|
+
variant="outline"
|
|
418
|
+
size="md"
|
|
419
|
+
/>
|
|
420
|
+
<Icon
|
|
421
|
+
{...args}
|
|
422
|
+
type="lucide"
|
|
423
|
+
name={iconName}
|
|
424
|
+
variant="outline"
|
|
425
|
+
size="lg"
|
|
426
|
+
/>
|
|
400
427
|
<p className="ml-4 font-mono text-sm">{iconName}</p>
|
|
401
428
|
</div>
|
|
402
429
|
))}
|
|
@@ -421,8 +448,12 @@ export const LucideIconBrowser = {
|
|
|
421
448
|
});
|
|
422
449
|
}, []);
|
|
423
450
|
|
|
451
|
+
console.log(names);
|
|
452
|
+
|
|
424
453
|
const filtered = filter
|
|
425
|
-
? names
|
|
454
|
+
? names
|
|
455
|
+
.filter((n) => n.toLowerCase().includes(filter.toLowerCase()))
|
|
456
|
+
.slice(0, 80)
|
|
426
457
|
: names.slice(0, 50);
|
|
427
458
|
|
|
428
459
|
return (
|
|
@@ -457,6 +488,47 @@ export const LucideIconBrowser = {
|
|
|
457
488
|
},
|
|
458
489
|
} satisfies StoryObj;
|
|
459
490
|
|
|
491
|
+
export const LucideIconAllBrowser = {
|
|
492
|
+
args: {},
|
|
493
|
+
render: () => {
|
|
494
|
+
const [names, setNames] = React.useState<string[]>([]);
|
|
495
|
+
const [loading, setLoading] = React.useState(true);
|
|
496
|
+
|
|
497
|
+
React.useEffect(() => {
|
|
498
|
+
import("@/icons").then(({ getLucideIconNames }) => {
|
|
499
|
+
getLucideIconNames().then((n) => {
|
|
500
|
+
setNames(n.sort());
|
|
501
|
+
setLoading(false);
|
|
502
|
+
});
|
|
503
|
+
});
|
|
504
|
+
}, []);
|
|
505
|
+
|
|
506
|
+
return (
|
|
507
|
+
<div className="flex flex-col gap-4 p-4 max-h-[80vh] overflow-auto w-full h-full">
|
|
508
|
+
<h4>Lucide icon names ({names.length} total)</h4>
|
|
509
|
+
|
|
510
|
+
{loading ? (
|
|
511
|
+
<p>Loading...</p>
|
|
512
|
+
) : (
|
|
513
|
+
<div className="grid grid-cols-[repeat(auto-fill,minmax(140px,1fr))] gap-2">
|
|
514
|
+
{names.map((name) => (
|
|
515
|
+
<div
|
|
516
|
+
key={name}
|
|
517
|
+
className="flex flex-col items-center gap-1 p-2 border rounded hover:bg-gray-50"
|
|
518
|
+
>
|
|
519
|
+
<Icon type="lucide" name={name} size="md" />
|
|
520
|
+
<span className="font-mono text-xs truncate w-full text-center">
|
|
521
|
+
{name}
|
|
522
|
+
</span>
|
|
523
|
+
</div>
|
|
524
|
+
))}
|
|
525
|
+
</div>
|
|
526
|
+
)}
|
|
527
|
+
</div>
|
|
528
|
+
);
|
|
529
|
+
},
|
|
530
|
+
} satisfies StoryObj;
|
|
531
|
+
|
|
460
532
|
export const PreviewMaterialIcon = {
|
|
461
533
|
args: {
|
|
462
534
|
// variant: "outline",
|