@trackunit/react-table-base-components 1.3.130 → 1.3.133
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/index.cjs.js +118 -30
- package/index.esm.js +120 -33
- package/package.json +7 -7
- package/src/components/RowActions/RowActions.d.ts +28 -0
- package/src/components/RowActions/RowActions.stories.d.ts +9 -0
- package/src/components/Th.d.ts +1 -5
- package/src/index.d.ts +1 -0
package/index.cjs.js
CHANGED
|
@@ -74,7 +74,7 @@ const cvaIdentityCell = cssClassVarianceUtilities.cvaMerge(["grid", "items-cente
|
|
|
74
74
|
density: "default",
|
|
75
75
|
},
|
|
76
76
|
});
|
|
77
|
-
const cvaIdentityCellLayout = cssClassVarianceUtilities.cvaMerge(["grid", "items-center", "
|
|
77
|
+
const cvaIdentityCellLayout = cssClassVarianceUtilities.cvaMerge(["grid", "items-center", "text-sm"], {
|
|
78
78
|
variants: {
|
|
79
79
|
density: {
|
|
80
80
|
default: "grid-rows-[min-content_auto]",
|
|
@@ -85,7 +85,7 @@ const cvaIdentityCellLayout = cssClassVarianceUtilities.cvaMerge(["grid", "items
|
|
|
85
85
|
density: "default",
|
|
86
86
|
},
|
|
87
87
|
});
|
|
88
|
-
const cvaIdentityCellDetails = cssClassVarianceUtilities.cvaMerge(["flex", "w-full", "min-w-0", "items-center", "truncate", "text-xs", "text-gray-
|
|
88
|
+
const cvaIdentityCellDetails = cssClassVarianceUtilities.cvaMerge(["flex", "w-full", "min-w-0", "items-center", "truncate", "text-xs", "text-gray-600", "font-medium"], {
|
|
89
89
|
variants: {
|
|
90
90
|
density: {
|
|
91
91
|
default: "pt-0",
|
|
@@ -102,7 +102,7 @@ const cvaIdentityCellDetailsItem = cssClassVarianceUtilities.cvaMerge(["last:tru
|
|
|
102
102
|
* @returns {ReactElement} LinkCell component
|
|
103
103
|
*/
|
|
104
104
|
const IdentityCell = ({ className, dataTestId = "identity-cell", density = "default", title, details = [], thumbnail, }) => {
|
|
105
|
-
return (jsxRuntime.jsxs("div", { className: cvaIdentityCell({ className, density, hasThumbnail: !!thumbnail }), "data-testid": dataTestId, children: [thumbnail ? (jsxRuntime.jsx("div", { className: "mr-1 flex h-8 w-8 items-center justify-center overflow-hidden rounded-md", children: thumbnail })) : null, jsxRuntime.jsxs("div", { className: cvaIdentityCellLayout({ className, density }), children: [jsxRuntime.jsx("div", { className: "flex w-full min-w-0 truncate text-sm", children: jsxRuntime.jsx(reactComponents.Heading, { className: "truncate text-sm", dataTestId: `${dataTestId}-name`, variant: "tertiary", children: title }) }), details.length > 0 && (jsxRuntime.jsx("div", { className: cvaIdentityCellDetails({ className, density }), children: details.map((value, index, array) => (jsxRuntime.jsxs(react.Fragment, { children: [jsxRuntime.jsx("span", { className: cvaIdentityCellDetailsItem({ className }), children: value }), index < array.length - 1 && (jsxRuntime.jsx("div", { className: "mx-0.5 flex items-center", children: jsxRuntime.jsx(reactComponents.Icon, { className: "w-4 text-neutral-
|
|
105
|
+
return (jsxRuntime.jsxs("div", { className: cvaIdentityCell({ className, density, hasThumbnail: !!thumbnail }), "data-testid": dataTestId, children: [thumbnail ? (jsxRuntime.jsx("div", { className: "mr-1 flex h-8 w-8 items-center justify-center overflow-hidden rounded-md", children: thumbnail })) : null, jsxRuntime.jsxs("div", { className: cvaIdentityCellLayout({ className, density }), children: [jsxRuntime.jsx("div", { className: "flex w-full min-w-0 truncate text-sm", children: jsxRuntime.jsx(reactComponents.Heading, { className: "truncate text-sm", dataTestId: `${dataTestId}-name`, variant: "tertiary", children: title }) }), details.length > 0 && (jsxRuntime.jsx("div", { className: cvaIdentityCellDetails({ className, density }), children: details.map((value, index, array) => (jsxRuntime.jsxs(react.Fragment, { children: [jsxRuntime.jsx("span", { className: cvaIdentityCellDetailsItem({ className }), children: value }), index < array.length - 1 && (jsxRuntime.jsx("div", { className: "mx-0.5 flex items-center", children: jsxRuntime.jsx(reactComponents.Icon, { className: "w-4 text-neutral-300", color: "neutral", name: "Slash", size: "small" }) }))] }, index))) }))] })] }));
|
|
106
106
|
};
|
|
107
107
|
|
|
108
108
|
/**
|
|
@@ -255,15 +255,79 @@ const ResizeHandle = ({ isResizing = false, dataTestId, onMouseDown: onMouseDown
|
|
|
255
255
|
};
|
|
256
256
|
return (jsxRuntime.jsx("div", { className: cvaResizeHandel({ isResizing, className }), "data-testid": dataTestId, onMouseDown: event => onMouseDown(event), role: "separator", ...rest }));
|
|
257
257
|
};
|
|
258
|
-
const cvaResizeHandel = cssClassVarianceUtilities.cvaMerge([
|
|
258
|
+
const cvaResizeHandel = cssClassVarianceUtilities.cvaMerge([
|
|
259
|
+
"absolute",
|
|
260
|
+
"cursor-ew-resize",
|
|
261
|
+
"z-2",
|
|
262
|
+
"h-full",
|
|
263
|
+
"w-2",
|
|
264
|
+
"top-0",
|
|
265
|
+
"right-[-3px]",
|
|
266
|
+
"flex",
|
|
267
|
+
"items-center",
|
|
268
|
+
"after:block",
|
|
269
|
+
"after:left-[calc(50%-2px)]",
|
|
270
|
+
"after:h-full",
|
|
271
|
+
"after:z-[1]",
|
|
272
|
+
"after:absolute",
|
|
273
|
+
"after:w-0.5",
|
|
274
|
+
"after:hover:bg-info-500",
|
|
275
|
+
], {
|
|
259
276
|
variants: {
|
|
260
277
|
isResizing: {
|
|
261
|
-
true: ["
|
|
278
|
+
true: ["opacity-1"],
|
|
262
279
|
false: [],
|
|
263
280
|
},
|
|
264
281
|
},
|
|
265
282
|
});
|
|
266
283
|
|
|
284
|
+
/**
|
|
285
|
+
* RowActions component displays actions as individual buttons or a dropdown menu
|
|
286
|
+
* based on the number of actions provided.
|
|
287
|
+
*
|
|
288
|
+
* - If there is a single action, it displays a standalone button.
|
|
289
|
+
* - If there are multiple actions, they are grouped into a dropdown menu.
|
|
290
|
+
*
|
|
291
|
+
* @param {RowActionsProps} props - The properties for the component.
|
|
292
|
+
* @param {Action[]} props.actions - A list of actions to display, including their labels, icons, and handlers.
|
|
293
|
+
* @returns {JSX.Element} A React component rendering the actions.
|
|
294
|
+
*/
|
|
295
|
+
const RowActions = ({ actions }) => {
|
|
296
|
+
const selectedActions = actions.filter(action => action.isSelected);
|
|
297
|
+
const normalActions = actions.filter(action => (action.isVisible ?? true) && action.variant !== "danger");
|
|
298
|
+
const dangerActions = actions.filter(action => (action.isVisible ?? true) && action.variant === "danger");
|
|
299
|
+
if (actions.length === 0) {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
if (actions.length === 1) {
|
|
303
|
+
const [action] = actions;
|
|
304
|
+
return (action &&
|
|
305
|
+
(action.isVisible ?? true) && (jsxRuntime.jsx(reactComponents.Button, { disabled: action.disabled || action.loading, onClick: event => {
|
|
306
|
+
event.stopPropagation();
|
|
307
|
+
action.onClick();
|
|
308
|
+
}, prefix: jsxRuntime.jsx(ActionIcon, { action: action }), size: "small", variant: "secondary", children: action.label })));
|
|
309
|
+
}
|
|
310
|
+
return (jsxRuntime.jsxs("div", { className: "flex items-center", "data-testid": "row-actions", children: [selectedActions.map((action, index) => (jsxRuntime.jsx(reactComponents.IconButton, { className: "mr-2", icon: action.iconName ? jsxRuntime.jsx(reactComponents.Icon, { name: action.iconName, size: "small" }) : undefined, onClick: event => {
|
|
311
|
+
event.stopPropagation();
|
|
312
|
+
action.onClick();
|
|
313
|
+
}, size: "small", variant: "ghost-neutral" }, `selected-action-${index}`))), jsxRuntime.jsx(reactComponents.MoreMenu, { customButton: jsxRuntime.jsx(reactComponents.IconButton, { icon: jsxRuntime.jsx(reactComponents.Icon, { name: "EllipsisHorizontal", size: "medium" }), onClick: event => event.stopPropagation(), size: "small", variant: "ghost-neutral" }), children: close => (jsxRuntime.jsxs(reactComponents.MenuList, { children: [normalActions.map((action, index) => (jsxRuntime.jsx(reactComponents.MenuItem, { disabled: action.disabled || action.loading, label: action.label, onClick: () => {
|
|
314
|
+
action.onClick();
|
|
315
|
+
close();
|
|
316
|
+
}, prefix: jsxRuntime.jsx(ActionIcon, { action: action }), variant: action.variant }, `action-${index}`))), normalActions.length > 0 && dangerActions.length > 0 && jsxRuntime.jsx(reactComponents.MenuDivider, {}), dangerActions.map((action, index) => (jsxRuntime.jsx(reactComponents.MenuItem, { disabled: action.disabled || action.loading, label: action.label, onClick: () => {
|
|
317
|
+
action.onClick();
|
|
318
|
+
close();
|
|
319
|
+
}, prefix: jsxRuntime.jsx(ActionIcon, { action: action }), variant: action.variant }, `danger-action-${index}`)))] })) })] }));
|
|
320
|
+
};
|
|
321
|
+
const ActionIcon = ({ action }) => {
|
|
322
|
+
if (action.loading) {
|
|
323
|
+
return jsxRuntime.jsx(reactComponents.Spinner, { size: "small" });
|
|
324
|
+
}
|
|
325
|
+
if (action.iconName) {
|
|
326
|
+
return jsxRuntime.jsx(reactComponents.Icon, { name: action.iconName, size: "medium" });
|
|
327
|
+
}
|
|
328
|
+
return null;
|
|
329
|
+
};
|
|
330
|
+
|
|
267
331
|
/**
|
|
268
332
|
* The SortIndicator is used in the table header to indicate the current sort order of the column.
|
|
269
333
|
* This is a visual only component and does not handle the sorting logic.
|
|
@@ -278,24 +342,23 @@ const cvaResizeHandel = cssClassVarianceUtilities.cvaMerge(["absolute", "cursor-
|
|
|
278
342
|
* @returns {ReactElement} A React element representing the sorting indicator.
|
|
279
343
|
*/
|
|
280
344
|
const SortIndicator = ({ sortingState = false, dataTestId, className, ...rest }) => {
|
|
281
|
-
return (jsxRuntime.jsx("
|
|
345
|
+
return (jsxRuntime.jsx("div", { className: cvaSortIndicator({ sortingState, className }), "data-testid": dataTestId, role: "separator", ...rest }));
|
|
282
346
|
};
|
|
283
347
|
const cvaSortIndicator = cssClassVarianceUtilities.cvaMerge([
|
|
284
|
-
"relative",
|
|
285
348
|
"before:block",
|
|
286
|
-
"before:h-
|
|
349
|
+
"before:h-1",
|
|
287
350
|
"before:absolute",
|
|
288
|
-
"before:
|
|
289
|
-
"before:
|
|
351
|
+
"before:top-[13px]",
|
|
352
|
+
"before:w-1",
|
|
290
353
|
"before:content-['_']",
|
|
291
354
|
"before:border-4",
|
|
292
355
|
"before:border-solid",
|
|
293
356
|
"before:border-transparent",
|
|
294
357
|
"after:block",
|
|
295
|
-
"after:h-
|
|
358
|
+
"after:h-1",
|
|
296
359
|
"after:absolute",
|
|
297
|
-
"after:w-
|
|
298
|
-
"after
|
|
360
|
+
"after:w-1",
|
|
361
|
+
"after:top-[18px]",
|
|
299
362
|
"after:content-['_']",
|
|
300
363
|
"after:border-4",
|
|
301
364
|
"after:border-solid",
|
|
@@ -305,9 +368,9 @@ const cvaSortIndicator = cssClassVarianceUtilities.cvaMerge([
|
|
|
305
368
|
], {
|
|
306
369
|
variants: {
|
|
307
370
|
sortingState: {
|
|
308
|
-
asc: ["before:border-b-
|
|
309
|
-
desc: ["after:border-t-
|
|
310
|
-
false: "",
|
|
371
|
+
asc: ["before:border-b-neutral-400 after:hidden"],
|
|
372
|
+
desc: ["before:hidden after:border-t-neutral-400"],
|
|
373
|
+
false: "hidden",
|
|
311
374
|
},
|
|
312
375
|
},
|
|
313
376
|
});
|
|
@@ -325,7 +388,7 @@ const cvaSortIndicator = cssClassVarianceUtilities.cvaMerge([
|
|
|
325
388
|
const TableRoot = ({ dataTestId, className, children, ...rest }) => {
|
|
326
389
|
return (jsxRuntime.jsx("table", { className: cvaTableRoot({ className }), "data-testid": dataTestId, ...rest, children: children }));
|
|
327
390
|
};
|
|
328
|
-
const cvaTableRoot = cssClassVarianceUtilities.cvaMerge(["border-spacing-0", "min-w-full", "grid-rows-min-fr", "grid"]);
|
|
391
|
+
const cvaTableRoot = cssClassVarianceUtilities.cvaMerge(["border-spacing-0", "min-w-full", "border-collapse", "grid-rows-min-fr", "grid"]);
|
|
329
392
|
|
|
330
393
|
const cvaTagsCell = cssClassVarianceUtilities.cvaMerge(["flex", "gap-2"]);
|
|
331
394
|
|
|
@@ -366,9 +429,22 @@ const Tbody = ({ dataTestId, className, children, ...rest }) => {
|
|
|
366
429
|
* @returns {ReactElement} Td component
|
|
367
430
|
*/
|
|
368
431
|
const Td = ({ dataTestId, className, children, ...rest }) => {
|
|
369
|
-
return (jsxRuntime.jsx("td", { className: cvaTd({ className }), "data-testid": dataTestId, ...rest, children: children
|
|
432
|
+
return (jsxRuntime.jsx("td", { className: cvaTd({ className }), "data-testid": dataTestId, ...rest, children: Array.isArray(children)
|
|
433
|
+
? children
|
|
434
|
+
.filter(Boolean)
|
|
435
|
+
.map((child, index) => (react.isValidElement(child) ? react.cloneElement(child, { key: index }) : child))
|
|
436
|
+
: children }));
|
|
370
437
|
};
|
|
371
|
-
const cvaTd = cssClassVarianceUtilities.cvaMerge([
|
|
438
|
+
const cvaTd = cssClassVarianceUtilities.cvaMerge([
|
|
439
|
+
"overflow-hidden",
|
|
440
|
+
"border-r",
|
|
441
|
+
"border-neutral-200",
|
|
442
|
+
"align-middle",
|
|
443
|
+
"text-ellipsis",
|
|
444
|
+
"whitespace-nowrap",
|
|
445
|
+
"py-table-spacing",
|
|
446
|
+
"px-4",
|
|
447
|
+
]);
|
|
372
448
|
|
|
373
449
|
const cvaTextCell = cssClassVarianceUtilities.cvaMerge(["truncate", "text-sm"]);
|
|
374
450
|
const cvaTextCellTooltip = cssClassVarianceUtilities.cvaMerge(["grid"]);
|
|
@@ -412,25 +488,36 @@ const Tfoot = ({ dataTestId, className, children, ...rest }) => {
|
|
|
412
488
|
* @param {ThProps} props - The props for the Th component
|
|
413
489
|
* @returns {ReactElement} Th component
|
|
414
490
|
*/
|
|
415
|
-
const Th = ({ dataTestId, className, children,
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}, [thWidth, childrenWidth, tooltipLabel]);
|
|
422
|
-
return (jsxRuntime.jsx("th", { className: cvaTh({ className }), "data-testid": dataTestId, ref: elementRef => setThWidth(elementRef ? elementRef.clientWidth : 0), ...rest, children: tooltipLabel ? (jsxRuntime.jsx(reactComponents.Tooltip, { className: cvaTooltip(), disabled: showToolTip, label: tooltipLabel, placement: "bottom", children: jsxRuntime.jsx("div", { className: cvaChildrenContainer(), ref: elementRef => setChildrenWidth(elementRef ? elementRef.clientWidth : 0), children: children }) })) : (jsxRuntime.jsx("div", { className: cvaChildrenContainer(), ref: elementRef => setChildrenWidth(elementRef ? elementRef.clientWidth : 0), children: children })) }));
|
|
491
|
+
const Th = ({ dataTestId, className, children, ...rest }) => {
|
|
492
|
+
return (jsxRuntime.jsx("th", { className: cvaTh({ className }), "data-testid": dataTestId, ...rest, children: jsxRuntime.jsx("div", { className: cvaChildrenContainer(), children: Array.isArray(children)
|
|
493
|
+
? children
|
|
494
|
+
.filter(Boolean)
|
|
495
|
+
.map((child, index) => (react.isValidElement(child) ? react.cloneElement(child, { key: index }) : child))
|
|
496
|
+
: children }) }));
|
|
423
497
|
};
|
|
424
498
|
const cvaTh = cssClassVarianceUtilities.cvaMerge([
|
|
425
499
|
"hover:bg-neutral-200",
|
|
426
500
|
"text-sm",
|
|
501
|
+
"border-r",
|
|
502
|
+
"border-neutral-200",
|
|
427
503
|
"overflow-hidden",
|
|
428
504
|
"font-medium",
|
|
429
505
|
"whitespace-nowrap",
|
|
506
|
+
"h-[46px]",
|
|
430
507
|
"p-0",
|
|
431
508
|
]);
|
|
432
|
-
const
|
|
433
|
-
|
|
509
|
+
const cvaChildrenContainer = cssClassVarianceUtilities.cvaMerge([
|
|
510
|
+
"w-full",
|
|
511
|
+
"min-w-0",
|
|
512
|
+
"flex",
|
|
513
|
+
"items-center",
|
|
514
|
+
"overflow-hidden",
|
|
515
|
+
"text-ellipsis",
|
|
516
|
+
"whitespace-nowrap",
|
|
517
|
+
"pl-4",
|
|
518
|
+
"py-table-spacing",
|
|
519
|
+
"pr-2",
|
|
520
|
+
]);
|
|
434
521
|
|
|
435
522
|
/**
|
|
436
523
|
* The Thead is a wrapper for the thead html element.
|
|
@@ -470,7 +557,7 @@ const cvaThead = cssClassVarianceUtilities.cvaMerge(["bg-neutral-100", "text-lef
|
|
|
470
557
|
const Tr = ({ dataTestId, className, children, layout = "default", ...rest }) => {
|
|
471
558
|
return (jsxRuntime.jsx("tr", { className: cvaTr({ layout, className }), "data-testid": dataTestId, role: "row", ...rest, children: children }));
|
|
472
559
|
};
|
|
473
|
-
const cvaTr = cssClassVarianceUtilities.cvaMerge(["
|
|
560
|
+
const cvaTr = cssClassVarianceUtilities.cvaMerge(["w-full", "h-max", "border-b", "border-neutral-200"], {
|
|
474
561
|
variants: {
|
|
475
562
|
layout: {
|
|
476
563
|
default: "",
|
|
@@ -495,6 +582,7 @@ exports.NoticeCell = NoticeCell;
|
|
|
495
582
|
exports.NumberCell = NumberCell;
|
|
496
583
|
exports.PlainDateCell = PlainDateCell;
|
|
497
584
|
exports.ResizeHandle = ResizeHandle;
|
|
585
|
+
exports.RowActions = RowActions;
|
|
498
586
|
exports.SortIndicator = SortIndicator;
|
|
499
587
|
exports.TableRoot = TableRoot;
|
|
500
588
|
exports.TagsCell = TagsCell;
|
package/index.esm.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { Button, Icon, Heading, Indicator, ExternalLink, Tooltip, Tag, Notice } from '@trackunit/react-components';
|
|
2
|
+
import { Button, Icon, Heading, Indicator, ExternalLink, Tooltip, Tag, Notice, IconButton, MoreMenu, MenuList, MenuItem, MenuDivider, Spinner } from '@trackunit/react-components';
|
|
3
3
|
import { Checkbox } from '@trackunit/react-form-components';
|
|
4
4
|
import { cvaMerge } from '@trackunit/css-class-variance-utilities';
|
|
5
5
|
import { formatDateUtil, timeSinceAuto, timeSinceInDays } from '@trackunit/date-and-time-utils';
|
|
6
|
-
import { Fragment, useState,
|
|
6
|
+
import { Fragment, useState, isValidElement, cloneElement } from 'react';
|
|
7
7
|
import { Temporal } from '@js-temporal/polyfill';
|
|
8
8
|
import { DateTimeFormat } from '@trackunit/shared-utils';
|
|
9
9
|
|
|
@@ -72,7 +72,7 @@ const cvaIdentityCell = cvaMerge(["grid", "items-center", "text-sm"], {
|
|
|
72
72
|
density: "default",
|
|
73
73
|
},
|
|
74
74
|
});
|
|
75
|
-
const cvaIdentityCellLayout = cvaMerge(["grid", "items-center", "
|
|
75
|
+
const cvaIdentityCellLayout = cvaMerge(["grid", "items-center", "text-sm"], {
|
|
76
76
|
variants: {
|
|
77
77
|
density: {
|
|
78
78
|
default: "grid-rows-[min-content_auto]",
|
|
@@ -83,7 +83,7 @@ const cvaIdentityCellLayout = cvaMerge(["grid", "items-center", "gap-1", "text-s
|
|
|
83
83
|
density: "default",
|
|
84
84
|
},
|
|
85
85
|
});
|
|
86
|
-
const cvaIdentityCellDetails = cvaMerge(["flex", "w-full", "min-w-0", "items-center", "truncate", "text-xs", "text-gray-
|
|
86
|
+
const cvaIdentityCellDetails = cvaMerge(["flex", "w-full", "min-w-0", "items-center", "truncate", "text-xs", "text-gray-600", "font-medium"], {
|
|
87
87
|
variants: {
|
|
88
88
|
density: {
|
|
89
89
|
default: "pt-0",
|
|
@@ -100,7 +100,7 @@ const cvaIdentityCellDetailsItem = cvaMerge(["last:truncate"]);
|
|
|
100
100
|
* @returns {ReactElement} LinkCell component
|
|
101
101
|
*/
|
|
102
102
|
const IdentityCell = ({ className, dataTestId = "identity-cell", density = "default", title, details = [], thumbnail, }) => {
|
|
103
|
-
return (jsxs("div", { className: cvaIdentityCell({ className, density, hasThumbnail: !!thumbnail }), "data-testid": dataTestId, children: [thumbnail ? (jsx("div", { className: "mr-1 flex h-8 w-8 items-center justify-center overflow-hidden rounded-md", children: thumbnail })) : null, jsxs("div", { className: cvaIdentityCellLayout({ className, density }), children: [jsx("div", { className: "flex w-full min-w-0 truncate text-sm", children: jsx(Heading, { className: "truncate text-sm", dataTestId: `${dataTestId}-name`, variant: "tertiary", children: title }) }), details.length > 0 && (jsx("div", { className: cvaIdentityCellDetails({ className, density }), children: details.map((value, index, array) => (jsxs(Fragment, { children: [jsx("span", { className: cvaIdentityCellDetailsItem({ className }), children: value }), index < array.length - 1 && (jsx("div", { className: "mx-0.5 flex items-center", children: jsx(Icon, { className: "w-4 text-neutral-
|
|
103
|
+
return (jsxs("div", { className: cvaIdentityCell({ className, density, hasThumbnail: !!thumbnail }), "data-testid": dataTestId, children: [thumbnail ? (jsx("div", { className: "mr-1 flex h-8 w-8 items-center justify-center overflow-hidden rounded-md", children: thumbnail })) : null, jsxs("div", { className: cvaIdentityCellLayout({ className, density }), children: [jsx("div", { className: "flex w-full min-w-0 truncate text-sm", children: jsx(Heading, { className: "truncate text-sm", dataTestId: `${dataTestId}-name`, variant: "tertiary", children: title }) }), details.length > 0 && (jsx("div", { className: cvaIdentityCellDetails({ className, density }), children: details.map((value, index, array) => (jsxs(Fragment, { children: [jsx("span", { className: cvaIdentityCellDetailsItem({ className }), children: value }), index < array.length - 1 && (jsx("div", { className: "mx-0.5 flex items-center", children: jsx(Icon, { className: "w-4 text-neutral-300", color: "neutral", name: "Slash", size: "small" }) }))] }, index))) }))] })] }));
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
/**
|
|
@@ -253,15 +253,79 @@ const ResizeHandle = ({ isResizing = false, dataTestId, onMouseDown: onMouseDown
|
|
|
253
253
|
};
|
|
254
254
|
return (jsx("div", { className: cvaResizeHandel({ isResizing, className }), "data-testid": dataTestId, onMouseDown: event => onMouseDown(event), role: "separator", ...rest }));
|
|
255
255
|
};
|
|
256
|
-
const cvaResizeHandel = cvaMerge([
|
|
256
|
+
const cvaResizeHandel = cvaMerge([
|
|
257
|
+
"absolute",
|
|
258
|
+
"cursor-ew-resize",
|
|
259
|
+
"z-2",
|
|
260
|
+
"h-full",
|
|
261
|
+
"w-2",
|
|
262
|
+
"top-0",
|
|
263
|
+
"right-[-3px]",
|
|
264
|
+
"flex",
|
|
265
|
+
"items-center",
|
|
266
|
+
"after:block",
|
|
267
|
+
"after:left-[calc(50%-2px)]",
|
|
268
|
+
"after:h-full",
|
|
269
|
+
"after:z-[1]",
|
|
270
|
+
"after:absolute",
|
|
271
|
+
"after:w-0.5",
|
|
272
|
+
"after:hover:bg-info-500",
|
|
273
|
+
], {
|
|
257
274
|
variants: {
|
|
258
275
|
isResizing: {
|
|
259
|
-
true: ["
|
|
276
|
+
true: ["opacity-1"],
|
|
260
277
|
false: [],
|
|
261
278
|
},
|
|
262
279
|
},
|
|
263
280
|
});
|
|
264
281
|
|
|
282
|
+
/**
|
|
283
|
+
* RowActions component displays actions as individual buttons or a dropdown menu
|
|
284
|
+
* based on the number of actions provided.
|
|
285
|
+
*
|
|
286
|
+
* - If there is a single action, it displays a standalone button.
|
|
287
|
+
* - If there are multiple actions, they are grouped into a dropdown menu.
|
|
288
|
+
*
|
|
289
|
+
* @param {RowActionsProps} props - The properties for the component.
|
|
290
|
+
* @param {Action[]} props.actions - A list of actions to display, including their labels, icons, and handlers.
|
|
291
|
+
* @returns {JSX.Element} A React component rendering the actions.
|
|
292
|
+
*/
|
|
293
|
+
const RowActions = ({ actions }) => {
|
|
294
|
+
const selectedActions = actions.filter(action => action.isSelected);
|
|
295
|
+
const normalActions = actions.filter(action => (action.isVisible ?? true) && action.variant !== "danger");
|
|
296
|
+
const dangerActions = actions.filter(action => (action.isVisible ?? true) && action.variant === "danger");
|
|
297
|
+
if (actions.length === 0) {
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
if (actions.length === 1) {
|
|
301
|
+
const [action] = actions;
|
|
302
|
+
return (action &&
|
|
303
|
+
(action.isVisible ?? true) && (jsx(Button, { disabled: action.disabled || action.loading, onClick: event => {
|
|
304
|
+
event.stopPropagation();
|
|
305
|
+
action.onClick();
|
|
306
|
+
}, prefix: jsx(ActionIcon, { action: action }), size: "small", variant: "secondary", children: action.label })));
|
|
307
|
+
}
|
|
308
|
+
return (jsxs("div", { className: "flex items-center", "data-testid": "row-actions", children: [selectedActions.map((action, index) => (jsx(IconButton, { className: "mr-2", icon: action.iconName ? jsx(Icon, { name: action.iconName, size: "small" }) : undefined, onClick: event => {
|
|
309
|
+
event.stopPropagation();
|
|
310
|
+
action.onClick();
|
|
311
|
+
}, size: "small", variant: "ghost-neutral" }, `selected-action-${index}`))), jsx(MoreMenu, { customButton: jsx(IconButton, { icon: jsx(Icon, { name: "EllipsisHorizontal", size: "medium" }), onClick: event => event.stopPropagation(), size: "small", variant: "ghost-neutral" }), children: close => (jsxs(MenuList, { children: [normalActions.map((action, index) => (jsx(MenuItem, { disabled: action.disabled || action.loading, label: action.label, onClick: () => {
|
|
312
|
+
action.onClick();
|
|
313
|
+
close();
|
|
314
|
+
}, prefix: jsx(ActionIcon, { action: action }), variant: action.variant }, `action-${index}`))), normalActions.length > 0 && dangerActions.length > 0 && jsx(MenuDivider, {}), dangerActions.map((action, index) => (jsx(MenuItem, { disabled: action.disabled || action.loading, label: action.label, onClick: () => {
|
|
315
|
+
action.onClick();
|
|
316
|
+
close();
|
|
317
|
+
}, prefix: jsx(ActionIcon, { action: action }), variant: action.variant }, `danger-action-${index}`)))] })) })] }));
|
|
318
|
+
};
|
|
319
|
+
const ActionIcon = ({ action }) => {
|
|
320
|
+
if (action.loading) {
|
|
321
|
+
return jsx(Spinner, { size: "small" });
|
|
322
|
+
}
|
|
323
|
+
if (action.iconName) {
|
|
324
|
+
return jsx(Icon, { name: action.iconName, size: "medium" });
|
|
325
|
+
}
|
|
326
|
+
return null;
|
|
327
|
+
};
|
|
328
|
+
|
|
265
329
|
/**
|
|
266
330
|
* The SortIndicator is used in the table header to indicate the current sort order of the column.
|
|
267
331
|
* This is a visual only component and does not handle the sorting logic.
|
|
@@ -276,24 +340,23 @@ const cvaResizeHandel = cvaMerge(["absolute", "cursor-col-resize", "right-0", "t
|
|
|
276
340
|
* @returns {ReactElement} A React element representing the sorting indicator.
|
|
277
341
|
*/
|
|
278
342
|
const SortIndicator = ({ sortingState = false, dataTestId, className, ...rest }) => {
|
|
279
|
-
return (jsx("
|
|
343
|
+
return (jsx("div", { className: cvaSortIndicator({ sortingState, className }), "data-testid": dataTestId, role: "separator", ...rest }));
|
|
280
344
|
};
|
|
281
345
|
const cvaSortIndicator = cvaMerge([
|
|
282
|
-
"relative",
|
|
283
346
|
"before:block",
|
|
284
|
-
"before:h-
|
|
347
|
+
"before:h-1",
|
|
285
348
|
"before:absolute",
|
|
286
|
-
"before:
|
|
287
|
-
"before:
|
|
349
|
+
"before:top-[13px]",
|
|
350
|
+
"before:w-1",
|
|
288
351
|
"before:content-['_']",
|
|
289
352
|
"before:border-4",
|
|
290
353
|
"before:border-solid",
|
|
291
354
|
"before:border-transparent",
|
|
292
355
|
"after:block",
|
|
293
|
-
"after:h-
|
|
356
|
+
"after:h-1",
|
|
294
357
|
"after:absolute",
|
|
295
|
-
"after:w-
|
|
296
|
-
"after
|
|
358
|
+
"after:w-1",
|
|
359
|
+
"after:top-[18px]",
|
|
297
360
|
"after:content-['_']",
|
|
298
361
|
"after:border-4",
|
|
299
362
|
"after:border-solid",
|
|
@@ -303,9 +366,9 @@ const cvaSortIndicator = cvaMerge([
|
|
|
303
366
|
], {
|
|
304
367
|
variants: {
|
|
305
368
|
sortingState: {
|
|
306
|
-
asc: ["before:border-b-
|
|
307
|
-
desc: ["after:border-t-
|
|
308
|
-
false: "",
|
|
369
|
+
asc: ["before:border-b-neutral-400 after:hidden"],
|
|
370
|
+
desc: ["before:hidden after:border-t-neutral-400"],
|
|
371
|
+
false: "hidden",
|
|
309
372
|
},
|
|
310
373
|
},
|
|
311
374
|
});
|
|
@@ -323,7 +386,7 @@ const cvaSortIndicator = cvaMerge([
|
|
|
323
386
|
const TableRoot = ({ dataTestId, className, children, ...rest }) => {
|
|
324
387
|
return (jsx("table", { className: cvaTableRoot({ className }), "data-testid": dataTestId, ...rest, children: children }));
|
|
325
388
|
};
|
|
326
|
-
const cvaTableRoot = cvaMerge(["border-spacing-0", "min-w-full", "grid-rows-min-fr", "grid"]);
|
|
389
|
+
const cvaTableRoot = cvaMerge(["border-spacing-0", "min-w-full", "border-collapse", "grid-rows-min-fr", "grid"]);
|
|
327
390
|
|
|
328
391
|
const cvaTagsCell = cvaMerge(["flex", "gap-2"]);
|
|
329
392
|
|
|
@@ -364,9 +427,22 @@ const Tbody = ({ dataTestId, className, children, ...rest }) => {
|
|
|
364
427
|
* @returns {ReactElement} Td component
|
|
365
428
|
*/
|
|
366
429
|
const Td = ({ dataTestId, className, children, ...rest }) => {
|
|
367
|
-
return (jsx("td", { className: cvaTd({ className }), "data-testid": dataTestId, ...rest, children: children
|
|
430
|
+
return (jsx("td", { className: cvaTd({ className }), "data-testid": dataTestId, ...rest, children: Array.isArray(children)
|
|
431
|
+
? children
|
|
432
|
+
.filter(Boolean)
|
|
433
|
+
.map((child, index) => (isValidElement(child) ? cloneElement(child, { key: index }) : child))
|
|
434
|
+
: children }));
|
|
368
435
|
};
|
|
369
|
-
const cvaTd = cvaMerge([
|
|
436
|
+
const cvaTd = cvaMerge([
|
|
437
|
+
"overflow-hidden",
|
|
438
|
+
"border-r",
|
|
439
|
+
"border-neutral-200",
|
|
440
|
+
"align-middle",
|
|
441
|
+
"text-ellipsis",
|
|
442
|
+
"whitespace-nowrap",
|
|
443
|
+
"py-table-spacing",
|
|
444
|
+
"px-4",
|
|
445
|
+
]);
|
|
370
446
|
|
|
371
447
|
const cvaTextCell = cvaMerge(["truncate", "text-sm"]);
|
|
372
448
|
const cvaTextCellTooltip = cvaMerge(["grid"]);
|
|
@@ -410,25 +486,36 @@ const Tfoot = ({ dataTestId, className, children, ...rest }) => {
|
|
|
410
486
|
* @param {ThProps} props - The props for the Th component
|
|
411
487
|
* @returns {ReactElement} Th component
|
|
412
488
|
*/
|
|
413
|
-
const Th = ({ dataTestId, className, children,
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
}, [thWidth, childrenWidth, tooltipLabel]);
|
|
420
|
-
return (jsx("th", { className: cvaTh({ className }), "data-testid": dataTestId, ref: elementRef => setThWidth(elementRef ? elementRef.clientWidth : 0), ...rest, children: tooltipLabel ? (jsx(Tooltip, { className: cvaTooltip(), disabled: showToolTip, label: tooltipLabel, placement: "bottom", children: jsx("div", { className: cvaChildrenContainer(), ref: elementRef => setChildrenWidth(elementRef ? elementRef.clientWidth : 0), children: children }) })) : (jsx("div", { className: cvaChildrenContainer(), ref: elementRef => setChildrenWidth(elementRef ? elementRef.clientWidth : 0), children: children })) }));
|
|
489
|
+
const Th = ({ dataTestId, className, children, ...rest }) => {
|
|
490
|
+
return (jsx("th", { className: cvaTh({ className }), "data-testid": dataTestId, ...rest, children: jsx("div", { className: cvaChildrenContainer(), children: Array.isArray(children)
|
|
491
|
+
? children
|
|
492
|
+
.filter(Boolean)
|
|
493
|
+
.map((child, index) => (isValidElement(child) ? cloneElement(child, { key: index }) : child))
|
|
494
|
+
: children }) }));
|
|
421
495
|
};
|
|
422
496
|
const cvaTh = cvaMerge([
|
|
423
497
|
"hover:bg-neutral-200",
|
|
424
498
|
"text-sm",
|
|
499
|
+
"border-r",
|
|
500
|
+
"border-neutral-200",
|
|
425
501
|
"overflow-hidden",
|
|
426
502
|
"font-medium",
|
|
427
503
|
"whitespace-nowrap",
|
|
504
|
+
"h-[46px]",
|
|
428
505
|
"p-0",
|
|
429
506
|
]);
|
|
430
|
-
const
|
|
431
|
-
|
|
507
|
+
const cvaChildrenContainer = cvaMerge([
|
|
508
|
+
"w-full",
|
|
509
|
+
"min-w-0",
|
|
510
|
+
"flex",
|
|
511
|
+
"items-center",
|
|
512
|
+
"overflow-hidden",
|
|
513
|
+
"text-ellipsis",
|
|
514
|
+
"whitespace-nowrap",
|
|
515
|
+
"pl-4",
|
|
516
|
+
"py-table-spacing",
|
|
517
|
+
"pr-2",
|
|
518
|
+
]);
|
|
432
519
|
|
|
433
520
|
/**
|
|
434
521
|
* The Thead is a wrapper for the thead html element.
|
|
@@ -468,7 +555,7 @@ const cvaThead = cvaMerge(["bg-neutral-100", "text-left"], {
|
|
|
468
555
|
const Tr = ({ dataTestId, className, children, layout = "default", ...rest }) => {
|
|
469
556
|
return (jsx("tr", { className: cvaTr({ layout, className }), "data-testid": dataTestId, role: "row", ...rest, children: children }));
|
|
470
557
|
};
|
|
471
|
-
const cvaTr = cvaMerge(["
|
|
558
|
+
const cvaTr = cvaMerge(["w-full", "h-max", "border-b", "border-neutral-200"], {
|
|
472
559
|
variants: {
|
|
473
560
|
layout: {
|
|
474
561
|
default: "",
|
|
@@ -480,4 +567,4 @@ const cvaTr = cvaMerge(["border-b", "border-neutral-300", "w-full", "h-max"], {
|
|
|
480
567
|
},
|
|
481
568
|
});
|
|
482
569
|
|
|
483
|
-
export { ButtonCell, CheckboxCell, DateTimeCell, IdentityCell, ImageCell, IndicatorCell, LinkCell, MultiRowTableCell, MultiValueTextCell, NoticeCell, NumberCell, PlainDateCell, ResizeHandle, SortIndicator, TableRoot, TagsCell, Tbody, Td, TextCell, Tfoot, Th, Thead, Tr };
|
|
570
|
+
export { ButtonCell, CheckboxCell, DateTimeCell, IdentityCell, ImageCell, IndicatorCell, LinkCell, MultiRowTableCell, MultiValueTextCell, NoticeCell, NumberCell, PlainDateCell, ResizeHandle, RowActions, SortIndicator, TableRoot, TagsCell, Tbody, Td, TextCell, Tfoot, Th, Thead, Tr };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-table-base-components",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.133",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"react": "19.0.0",
|
|
11
11
|
"@js-temporal/polyfill": "^0.4.4",
|
|
12
|
-
"@trackunit/react-components": "1.4.
|
|
13
|
-
"@trackunit/ui-icons": "1.3.
|
|
14
|
-
"@trackunit/react-form-components": "1.3.
|
|
15
|
-
"@trackunit/css-class-variance-utilities": "1.3.
|
|
16
|
-
"@trackunit/date-and-time-utils": "1.3.
|
|
17
|
-
"@trackunit/shared-utils": "1.5.
|
|
12
|
+
"@trackunit/react-components": "1.4.117",
|
|
13
|
+
"@trackunit/ui-icons": "1.3.99",
|
|
14
|
+
"@trackunit/react-form-components": "1.3.133",
|
|
15
|
+
"@trackunit/css-class-variance-utilities": "1.3.98",
|
|
16
|
+
"@trackunit/date-and-time-utils": "1.3.98",
|
|
17
|
+
"@trackunit/shared-utils": "1.5.98"
|
|
18
18
|
},
|
|
19
19
|
"module": "./index.esm.js",
|
|
20
20
|
"main": "./index.cjs.js",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { MenuItemVariant } from "@trackunit/react-components";
|
|
2
|
+
import { IconName } from "@trackunit/ui-icons";
|
|
3
|
+
export type Action = {
|
|
4
|
+
label: string;
|
|
5
|
+
variant?: MenuItemVariant;
|
|
6
|
+
onClick: () => void;
|
|
7
|
+
iconName?: IconName;
|
|
8
|
+
isSelected?: boolean;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
loading?: boolean;
|
|
11
|
+
isVisible?: boolean | null;
|
|
12
|
+
};
|
|
13
|
+
interface RowActionsProps {
|
|
14
|
+
actions: Action[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* RowActions component displays actions as individual buttons or a dropdown menu
|
|
18
|
+
* based on the number of actions provided.
|
|
19
|
+
*
|
|
20
|
+
* - If there is a single action, it displays a standalone button.
|
|
21
|
+
* - If there are multiple actions, they are grouped into a dropdown menu.
|
|
22
|
+
*
|
|
23
|
+
* @param {RowActionsProps} props - The properties for the component.
|
|
24
|
+
* @param {Action[]} props.actions - A list of actions to display, including their labels, icons, and handlers.
|
|
25
|
+
* @returns {JSX.Element} A React component rendering the actions.
|
|
26
|
+
*/
|
|
27
|
+
export declare const RowActions: ({ actions }: RowActionsProps) => false | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { RowActions } from "./RowActions";
|
|
3
|
+
declare const meta: Meta<typeof RowActions>;
|
|
4
|
+
export default meta;
|
|
5
|
+
export declare const packageName: () => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export declare const SingleAction: StoryObj<typeof RowActions>;
|
|
7
|
+
export declare const MultipleActions: StoryObj<typeof RowActions>;
|
|
8
|
+
export declare const NoActions: StoryObj<typeof RowActions>;
|
|
9
|
+
export declare const OnlyDangerActions: StoryObj<typeof RowActions>;
|
package/src/components/Th.d.ts
CHANGED
|
@@ -13,10 +13,6 @@ export interface ThProps extends CommonProps, React.HTMLAttributes<HTMLTableCell
|
|
|
13
13
|
* Children to render in the table cell.
|
|
14
14
|
*/
|
|
15
15
|
children?: ReactNode;
|
|
16
|
-
/**
|
|
17
|
-
* Label for the tooltip.
|
|
18
|
-
*/
|
|
19
|
-
tooltipLabel?: string;
|
|
20
16
|
}
|
|
21
17
|
/**
|
|
22
18
|
* The Th is a wrapper for the th html element.
|
|
@@ -28,4 +24,4 @@ export interface ThProps extends CommonProps, React.HTMLAttributes<HTMLTableCell
|
|
|
28
24
|
* @param {ThProps} props - The props for the Th component
|
|
29
25
|
* @returns {ReactElement} Th component
|
|
30
26
|
*/
|
|
31
|
-
export declare const Th: ({ dataTestId, className, children,
|
|
27
|
+
export declare const Th: ({ dataTestId, className, children, ...rest }: ThProps) => import("react/jsx-runtime").JSX.Element;
|
package/src/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from "./components/NoticeCell/NoticeCell";
|
|
|
11
11
|
export * from "./components/NumberCell/NumberCell";
|
|
12
12
|
export * from "./components/PlainDateCell/PlainDateCell";
|
|
13
13
|
export * from "./components/ResizeHandle";
|
|
14
|
+
export * from "./components/RowActions/RowActions";
|
|
14
15
|
export * from "./components/SortIndicator";
|
|
15
16
|
export * from "./components/TableRoot";
|
|
16
17
|
export * from "./components/TagsCell/TagsCell";
|