@dbcdk/react-components 0.0.120 → 0.0.122
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/components/card/Card.cjs +4 -7
- package/dist/components/card/Card.js +4 -7
- package/dist/components/card/Card.module.css +4 -9
- package/dist/components/code-block/CodeBlock.cjs +11 -1
- package/dist/components/code-block/CodeBlock.d.ts +1 -1
- package/dist/components/code-block/CodeBlock.js +12 -2
- package/dist/components/code-block/CodeBlock.module.css +12 -1
- package/dist/components/forms/file-upload/FileUpload.d.ts +2 -2
- package/dist/components/search-box/SearchBox.cjs +9 -4
- package/dist/components/search-box/SearchBox.js +9 -4
- package/dist/components/sidebar/components/sidebar-container/SidebarContainer.cjs +3 -2
- package/dist/components/sidebar/components/sidebar-container/SidebarContainer.js +4 -3
- package/dist/components/sidebar/components/sidebar-container/SidebarContainer.module.css +5 -0
- package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.cjs +1 -1
- package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.js +1 -1
- package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.module.css +11 -7
- package/dist/components/table/Table.cjs +9 -4
- package/dist/components/table/Table.d.ts +1 -1
- package/dist/components/table/Table.js +10 -5
- package/dist/components/table/Table.module.css +25 -0
- package/dist/components/table/Table.types.d.ts +13 -0
- package/dist/components/table/TanstackTable.cjs +10 -1
- package/dist/components/table/TanstackTable.js +10 -1
- package/dist/components/table/components/TableBody.cjs +2 -0
- package/dist/components/table/components/TableBody.d.ts +7 -2
- package/dist/components/table/components/TableBody.js +2 -0
- package/dist/components/table/components/TableHeader.cjs +10 -1
- package/dist/components/table/components/TableHeader.d.ts +2 -1
- package/dist/components/table/components/TableHeader.js +10 -1
- package/dist/components/table/components/TableRow.cjs +75 -1
- package/dist/components/table/components/TableRow.d.ts +7 -2
- package/dist/components/table/components/TableRow.js +75 -1
- package/dist/components/table/hooks/useTableRowInteractions.cjs +2 -2
- package/dist/components/table/hooks/useTableRowInteractions.js +2 -2
- package/dist/components/table/table.utils.cjs +2 -0
- package/dist/components/table/table.utils.d.ts +1 -0
- package/dist/components/table/table.utils.js +2 -1
- package/dist/components/table/tanstackTable.utils.cjs +6 -4
- package/dist/components/table/tanstackTable.utils.d.ts +2 -0
- package/dist/components/table/tanstackTable.utils.js +7 -5
- package/package.json +1 -1
- package/dist/components/table/components/TableLoadingBody.cjs +0 -35
- package/dist/components/table/components/TableLoadingBody.d.ts +0 -9
- package/dist/components/table/components/TableLoadingBody.js +0 -29
|
@@ -5,7 +5,7 @@ var styles = require('./Card.module.css');
|
|
|
5
5
|
var CardMeta = require('./components/CardMeta');
|
|
6
6
|
var Headline = require('../headline/Headline');
|
|
7
7
|
var Hyperlink = require('../hyperlink/Hyperlink');
|
|
8
|
-
var
|
|
8
|
+
var SkeletonLoader = require('../skeleton-loader/SkeletonLoader');
|
|
9
9
|
|
|
10
10
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
11
|
|
|
@@ -52,7 +52,7 @@ function CardImpl({
|
|
|
52
52
|
children,
|
|
53
53
|
link,
|
|
54
54
|
width,
|
|
55
|
-
headlineSize =
|
|
55
|
+
headlineSize = 3,
|
|
56
56
|
truncateTitle = false
|
|
57
57
|
}) {
|
|
58
58
|
var _a;
|
|
@@ -76,7 +76,7 @@ function CardImpl({
|
|
|
76
76
|
Headline.Headline,
|
|
77
77
|
{
|
|
78
78
|
severity,
|
|
79
|
-
marker: headerMarker,
|
|
79
|
+
marker: Boolean(severity) && headerMarker,
|
|
80
80
|
icon: headerIcon,
|
|
81
81
|
addition: headerAddition,
|
|
82
82
|
subheader,
|
|
@@ -89,10 +89,7 @@ function CardImpl({
|
|
|
89
89
|
) : null,
|
|
90
90
|
headerMeta ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.headerMeta, children: headerMeta }) : null
|
|
91
91
|
] }) : null,
|
|
92
|
-
loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.
|
|
93
|
-
/* @__PURE__ */ jsxRuntime.jsx(SkeletonLoaderItem.SkeletonLoaderItem, {}),
|
|
94
|
-
/* @__PURE__ */ jsxRuntime.jsx(SkeletonLoaderItem.SkeletonLoaderItem, { width: "100%" })
|
|
95
|
-
] }, index)) }) : null,
|
|
92
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.loadingBody, "aria-busy": "true", "aria-live": "polite", children: /* @__PURE__ */ jsxRuntime.jsx(SkeletonLoader.SkeletonLoader, { type: "squares", rows: 1, columns: 1 }) }) : null,
|
|
96
93
|
showSection ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.section, children: [
|
|
97
94
|
showSectionDivider ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.sectionDivider }) : null,
|
|
98
95
|
sectionTitle ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.sectionTitle, children: sectionTitle }) : null
|
|
@@ -3,7 +3,7 @@ import styles from './Card.module.css';
|
|
|
3
3
|
import { CardMetaRow, CardMeta } from './components/CardMeta';
|
|
4
4
|
import { Headline } from '../headline/Headline';
|
|
5
5
|
import { Hyperlink } from '../hyperlink/Hyperlink';
|
|
6
|
-
import {
|
|
6
|
+
import { SkeletonLoader } from '../skeleton-loader/SkeletonLoader';
|
|
7
7
|
|
|
8
8
|
function getInnerPlacementClass(imgPlacement, s) {
|
|
9
9
|
switch (imgPlacement) {
|
|
@@ -46,7 +46,7 @@ function CardImpl({
|
|
|
46
46
|
children,
|
|
47
47
|
link,
|
|
48
48
|
width,
|
|
49
|
-
headlineSize =
|
|
49
|
+
headlineSize = 3,
|
|
50
50
|
truncateTitle = false
|
|
51
51
|
}) {
|
|
52
52
|
var _a;
|
|
@@ -70,7 +70,7 @@ function CardImpl({
|
|
|
70
70
|
Headline,
|
|
71
71
|
{
|
|
72
72
|
severity,
|
|
73
|
-
marker: headerMarker,
|
|
73
|
+
marker: Boolean(severity) && headerMarker,
|
|
74
74
|
icon: headerIcon,
|
|
75
75
|
addition: headerAddition,
|
|
76
76
|
subheader,
|
|
@@ -83,10 +83,7 @@ function CardImpl({
|
|
|
83
83
|
) : null,
|
|
84
84
|
headerMeta ? /* @__PURE__ */ jsx("div", { className: styles.headerMeta, children: headerMeta }) : null
|
|
85
85
|
] }) : null,
|
|
86
|
-
loading ? /* @__PURE__ */ jsx("div", { className: styles.
|
|
87
|
-
/* @__PURE__ */ jsx(SkeletonLoaderItem, {}),
|
|
88
|
-
/* @__PURE__ */ jsx(SkeletonLoaderItem, { width: "100%" })
|
|
89
|
-
] }, index)) }) : null,
|
|
86
|
+
loading ? /* @__PURE__ */ jsx("div", { className: styles.loadingBody, "aria-busy": "true", "aria-live": "polite", children: /* @__PURE__ */ jsx(SkeletonLoader, { type: "squares", rows: 1, columns: 1 }) }) : null,
|
|
90
87
|
showSection ? /* @__PURE__ */ jsxs("div", { className: styles.section, children: [
|
|
91
88
|
showSectionDivider ? /* @__PURE__ */ jsx("div", { className: styles.sectionDivider }) : null,
|
|
92
89
|
sectionTitle ? /* @__PURE__ */ jsx("div", { className: styles.sectionTitle, children: sectionTitle }) : null
|
|
@@ -159,16 +159,11 @@
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
/* Loading */
|
|
162
|
-
.
|
|
162
|
+
.loadingBody {
|
|
163
163
|
display: flex;
|
|
164
|
-
flex
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
.loadingRow {
|
|
169
|
-
display: flex;
|
|
170
|
-
flex-direction: column;
|
|
171
|
-
gap: var(--spacing-sm);
|
|
164
|
+
flex: 1 1 auto;
|
|
165
|
+
min-width: 0;
|
|
166
|
+
min-height: 180px;
|
|
172
167
|
}
|
|
173
168
|
|
|
174
169
|
/* Responsive */
|
|
@@ -38,6 +38,7 @@ function CodeBlock({
|
|
|
38
38
|
const text = typeof code === "string" ? code : void 0;
|
|
39
39
|
const hasChildren = children !== void 0 && children !== null;
|
|
40
40
|
const [isWrapped, setIsWrapped] = react.useState(wrap);
|
|
41
|
+
const codeRef = react.useRef(null);
|
|
41
42
|
const copy = react.useMemo(
|
|
42
43
|
() => {
|
|
43
44
|
var _a;
|
|
@@ -49,6 +50,15 @@ function CodeBlock({
|
|
|
49
50
|
() => smart && !hasChildren && typeof text === "string" ? text.split("\n") : null,
|
|
50
51
|
[smart, hasChildren, text]
|
|
51
52
|
);
|
|
53
|
+
const handleDoubleClick = () => {
|
|
54
|
+
const el = codeRef.current;
|
|
55
|
+
const selection = typeof window !== "undefined" ? window.getSelection() : null;
|
|
56
|
+
if (!el || !selection) return;
|
|
57
|
+
const range = document.createRange();
|
|
58
|
+
range.selectNodeContents(el);
|
|
59
|
+
selection.removeAllRanges();
|
|
60
|
+
selection.addRange(range);
|
|
61
|
+
};
|
|
52
62
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
53
63
|
"div",
|
|
54
64
|
{
|
|
@@ -76,7 +86,7 @@ function CodeBlock({
|
|
|
76
86
|
),
|
|
77
87
|
/* @__PURE__ */ jsxRuntime.jsx(CopyButton.CopyButton, { size: "sm", shape: "round", variant: "inline", text: copy })
|
|
78
88
|
] }),
|
|
79
|
-
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: styles__default.default.container, tabIndex: 0, children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: styles__default.default.code, children: hasChildren ? children : lines ? lines.map((line, i) => {
|
|
89
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: styles__default.default.container, tabIndex: 0, onDoubleClick: handleDoubleClick, children: /* @__PURE__ */ jsxRuntime.jsx("code", { ref: codeRef, className: styles__default.default.code, children: hasChildren ? children : lines ? lines.map((line, i) => {
|
|
80
90
|
const isFirst = i === 0;
|
|
81
91
|
const isFrame = looksLikeStackFrame(line);
|
|
82
92
|
const cls = [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { TextWrap } from 'lucide-react';
|
|
3
|
-
import { useState, useMemo, isValidElement } from 'react';
|
|
3
|
+
import { useState, useRef, useMemo, isValidElement } from 'react';
|
|
4
4
|
import styles from './CodeBlock.module.css';
|
|
5
5
|
import { Button } from '../button/Button';
|
|
6
6
|
import { CopyButton } from '../copy-button/CopyButton';
|
|
@@ -32,6 +32,7 @@ function CodeBlock({
|
|
|
32
32
|
const text = typeof code === "string" ? code : void 0;
|
|
33
33
|
const hasChildren = children !== void 0 && children !== null;
|
|
34
34
|
const [isWrapped, setIsWrapped] = useState(wrap);
|
|
35
|
+
const codeRef = useRef(null);
|
|
35
36
|
const copy = useMemo(
|
|
36
37
|
() => {
|
|
37
38
|
var _a;
|
|
@@ -43,6 +44,15 @@ function CodeBlock({
|
|
|
43
44
|
() => smart && !hasChildren && typeof text === "string" ? text.split("\n") : null,
|
|
44
45
|
[smart, hasChildren, text]
|
|
45
46
|
);
|
|
47
|
+
const handleDoubleClick = () => {
|
|
48
|
+
const el = codeRef.current;
|
|
49
|
+
const selection = typeof window !== "undefined" ? window.getSelection() : null;
|
|
50
|
+
if (!el || !selection) return;
|
|
51
|
+
const range = document.createRange();
|
|
52
|
+
range.selectNodeContents(el);
|
|
53
|
+
selection.removeAllRanges();
|
|
54
|
+
selection.addRange(range);
|
|
55
|
+
};
|
|
46
56
|
return /* @__PURE__ */ jsxs(
|
|
47
57
|
"div",
|
|
48
58
|
{
|
|
@@ -70,7 +80,7 @@ function CodeBlock({
|
|
|
70
80
|
),
|
|
71
81
|
/* @__PURE__ */ jsx(CopyButton, { size: "sm", shape: "round", variant: "inline", text: copy })
|
|
72
82
|
] }),
|
|
73
|
-
/* @__PURE__ */ jsx("pre", { className: styles.container, tabIndex: 0, children: /* @__PURE__ */ jsx("code", { className: styles.code, children: hasChildren ? children : lines ? lines.map((line, i) => {
|
|
83
|
+
/* @__PURE__ */ jsx("pre", { className: styles.container, tabIndex: 0, onDoubleClick: handleDoubleClick, children: /* @__PURE__ */ jsx("code", { ref: codeRef, className: styles.code, children: hasChildren ? children : lines ? lines.map((line, i) => {
|
|
74
84
|
const isFirst = i === 0;
|
|
75
85
|
const isFrame = looksLikeStackFrame(line);
|
|
76
86
|
const cls = [
|
|
@@ -18,13 +18,20 @@
|
|
|
18
18
|
font-family: var(--font-family-mono);
|
|
19
19
|
line-height: 1.35;
|
|
20
20
|
overflow: auto;
|
|
21
|
-
scrollbar-gutter: stable;
|
|
22
21
|
display: inline-flex;
|
|
23
22
|
align-items: flex-start;
|
|
24
23
|
max-inline-size: 100%;
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
/* Sizes */
|
|
27
|
+
.xs .container {
|
|
28
|
+
padding: var(--spacing-xxs);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.xs .code {
|
|
32
|
+
font-size: var(--font-size-xs);
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
.sm .container {
|
|
29
36
|
padding: var(--spacing-xs);
|
|
30
37
|
}
|
|
@@ -45,6 +52,10 @@
|
|
|
45
52
|
min-block-size: calc(var(--code-actions-h) + var(--spacing-sm) + var(--spacing-sm));
|
|
46
53
|
}
|
|
47
54
|
|
|
55
|
+
.xs.hasActions .container {
|
|
56
|
+
min-block-size: calc(var(--code-actions-h) + var(--spacing-xxs) + var(--spacing-xxs));
|
|
57
|
+
}
|
|
58
|
+
|
|
48
59
|
.sm.hasActions .container {
|
|
49
60
|
min-block-size: calc(var(--code-actions-h) + var(--spacing-xs) + var(--spacing-xs));
|
|
50
61
|
}
|
|
@@ -4,8 +4,8 @@ export interface FileUploadProps extends Omit<InputHTMLAttributes<HTMLInputEleme
|
|
|
4
4
|
onChange?: (files: FileList | null) => void;
|
|
5
5
|
/** Custom content to replace the default icon + text hint */
|
|
6
6
|
children?: ReactNode;
|
|
7
|
-
/**
|
|
8
|
-
hint?:
|
|
7
|
+
/** Hint shown below the icon when no custom children */
|
|
8
|
+
hint?: ReactNode;
|
|
9
9
|
fullWidth?: boolean;
|
|
10
10
|
height?: number | string;
|
|
11
11
|
minWidth?: string | number;
|
|
@@ -49,6 +49,7 @@ const SearchBox = react.forwardRef(function SearchBoxInner({
|
|
|
49
49
|
const listboxId = react.useId();
|
|
50
50
|
const popoverRef = react.useRef(null);
|
|
51
51
|
const internalInputRef = react.useRef(null);
|
|
52
|
+
const onSearchRef = react.useRef(onSearch);
|
|
52
53
|
react.useEffect(() => {
|
|
53
54
|
if (typeof ref === "function") {
|
|
54
55
|
ref(internalInputRef.current);
|
|
@@ -62,18 +63,22 @@ const SearchBox = react.forwardRef(function SearchBoxInner({
|
|
|
62
63
|
if (next !== draft) setDraft(next);
|
|
63
64
|
}, [value]);
|
|
64
65
|
react.useEffect(() => {
|
|
65
|
-
|
|
66
|
+
onSearchRef.current = onSearch;
|
|
67
|
+
}, [onSearch]);
|
|
68
|
+
react.useEffect(() => {
|
|
69
|
+
if (!onSearchRef.current) return;
|
|
66
70
|
if (!debounce) {
|
|
67
71
|
setSearchQuery(draft);
|
|
68
|
-
|
|
72
|
+
onSearchRef.current(draft);
|
|
69
73
|
return;
|
|
70
74
|
}
|
|
71
75
|
const handler = setTimeout(() => {
|
|
76
|
+
var _a2;
|
|
72
77
|
setSearchQuery(draft);
|
|
73
|
-
|
|
78
|
+
(_a2 = onSearchRef.current) == null ? void 0 : _a2.call(onSearchRef, draft);
|
|
74
79
|
}, debounceMs);
|
|
75
80
|
return () => clearTimeout(handler);
|
|
76
|
-
}, [draft,
|
|
81
|
+
}, [draft, debounce, debounceMs]);
|
|
77
82
|
react.useEffect(() => {
|
|
78
83
|
function handleKeyDown(event) {
|
|
79
84
|
var _a2;
|
|
@@ -43,6 +43,7 @@ const SearchBox = forwardRef(function SearchBoxInner({
|
|
|
43
43
|
const listboxId = useId();
|
|
44
44
|
const popoverRef = useRef(null);
|
|
45
45
|
const internalInputRef = useRef(null);
|
|
46
|
+
const onSearchRef = useRef(onSearch);
|
|
46
47
|
useEffect(() => {
|
|
47
48
|
if (typeof ref === "function") {
|
|
48
49
|
ref(internalInputRef.current);
|
|
@@ -56,18 +57,22 @@ const SearchBox = forwardRef(function SearchBoxInner({
|
|
|
56
57
|
if (next !== draft) setDraft(next);
|
|
57
58
|
}, [value]);
|
|
58
59
|
useEffect(() => {
|
|
59
|
-
|
|
60
|
+
onSearchRef.current = onSearch;
|
|
61
|
+
}, [onSearch]);
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (!onSearchRef.current) return;
|
|
60
64
|
if (!debounce) {
|
|
61
65
|
setSearchQuery(draft);
|
|
62
|
-
|
|
66
|
+
onSearchRef.current(draft);
|
|
63
67
|
return;
|
|
64
68
|
}
|
|
65
69
|
const handler = setTimeout(() => {
|
|
70
|
+
var _a2;
|
|
66
71
|
setSearchQuery(draft);
|
|
67
|
-
|
|
72
|
+
(_a2 = onSearchRef.current) == null ? void 0 : _a2.call(onSearchRef, draft);
|
|
68
73
|
}, debounceMs);
|
|
69
74
|
return () => clearTimeout(handler);
|
|
70
|
-
}, [draft,
|
|
75
|
+
}, [draft, debounce, debounceMs]);
|
|
71
76
|
useEffect(() => {
|
|
72
77
|
function handleKeyDown(event) {
|
|
73
78
|
var _a2;
|
|
@@ -169,11 +169,12 @@ function SidebarContainer({
|
|
|
169
169
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
170
170
|
Button.Button,
|
|
171
171
|
{
|
|
172
|
-
size: "
|
|
172
|
+
size: "sm",
|
|
173
173
|
variant: "inline",
|
|
174
174
|
shape: "round",
|
|
175
175
|
"aria-label": "Collapse sidebar",
|
|
176
|
-
|
|
176
|
+
tooltip: isSidebarCollapsed ? "Vis sidebj\xE6lke" : "Skjul sidebj\xE6lke",
|
|
177
|
+
icon: isSidebarCollapsed ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeftOpen, { className: styles__default.default.sidebarIcon }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeft, { className: styles__default.default.sidebarIcon }),
|
|
177
178
|
onClick: () => handleSidebarCollapseChange(!isSidebarCollapsed)
|
|
178
179
|
}
|
|
179
180
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import {
|
|
3
|
+
import { PanelLeftOpen, PanelLeft } from 'lucide-react';
|
|
4
4
|
import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
|
|
5
5
|
import { Logo } from '../../../../assets/logo';
|
|
6
6
|
import { Button } from '../../../../components/button/Button';
|
|
@@ -162,11 +162,12 @@ function SidebarContainer({
|
|
|
162
162
|
/* @__PURE__ */ jsx(
|
|
163
163
|
Button,
|
|
164
164
|
{
|
|
165
|
-
size: "
|
|
165
|
+
size: "sm",
|
|
166
166
|
variant: "inline",
|
|
167
167
|
shape: "round",
|
|
168
168
|
"aria-label": "Collapse sidebar",
|
|
169
|
-
|
|
169
|
+
tooltip: isSidebarCollapsed ? "Vis sidebj\xE6lke" : "Skjul sidebj\xE6lke",
|
|
170
|
+
icon: isSidebarCollapsed ? /* @__PURE__ */ jsx(PanelLeftOpen, { className: styles.sidebarIcon }) : /* @__PURE__ */ jsx(PanelLeft, { className: styles.sidebarIcon }),
|
|
170
171
|
onClick: () => handleSidebarCollapseChange(!isSidebarCollapsed)
|
|
171
172
|
}
|
|
172
173
|
)
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
--h: var(--skeleton-height, 14px);
|
|
3
3
|
--r: var(--border-radius-md, 6px);
|
|
4
4
|
--speed: var(--skeleton-speed, 1.2s);
|
|
5
|
-
--skeleton-base: var(--opac-bg-
|
|
6
|
-
--skeleton-sheen: var(--opac-bg-
|
|
5
|
+
--skeleton-base: var(--opac-bg-default);
|
|
6
|
+
--skeleton-sheen: var(--opac-bg-light);
|
|
7
|
+
--skeleton-sheen-soft: color-mix(in srgb, var(--skeleton-sheen) 60%, var(--skeleton-base));
|
|
7
8
|
position: relative;
|
|
8
9
|
display: block;
|
|
9
10
|
inline-size: var(--width, 100%);
|
|
@@ -14,17 +15,20 @@
|
|
|
14
15
|
border-radius: var(--r);
|
|
15
16
|
background: linear-gradient(
|
|
16
17
|
90deg,
|
|
17
|
-
var(--skeleton-
|
|
18
|
-
var(--skeleton-base)
|
|
19
|
-
var(--skeleton-sheen)
|
|
18
|
+
var(--skeleton-base) 0%,
|
|
19
|
+
var(--skeleton-base) 34%,
|
|
20
|
+
var(--skeleton-sheen-soft) 45%,
|
|
21
|
+
var(--skeleton-sheen) 50%,
|
|
22
|
+
var(--skeleton-sheen-soft) 55%,
|
|
23
|
+
var(--skeleton-base) 66%,
|
|
20
24
|
var(--skeleton-base) 100%
|
|
21
25
|
);
|
|
22
|
-
background-size:
|
|
26
|
+
background-size: 240% 100%;
|
|
23
27
|
animation: shimmer var(--speed) linear infinite;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
.invert {
|
|
27
|
-
--skeleton-base: var(--opac-bg-
|
|
31
|
+
--skeleton-base: var(--opac-bg-default-invert);
|
|
28
32
|
--skeleton-sheen: var(--opac-bg-light-invert);
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var react = require('react');
|
|
6
6
|
var Pagination = require('../../components/pagination/Pagination');
|
|
7
|
+
var SkeletonLoader = require('../../components/skeleton-loader/SkeletonLoader');
|
|
7
8
|
var useViewportFill = require('../../hooks/useViewportFill');
|
|
8
9
|
var EmptyState = require('./components/empty-state/EmptyState');
|
|
9
10
|
var TableBody = require('./components/TableBody');
|
|
10
11
|
var TableHeader = require('./components/TableHeader');
|
|
11
|
-
var TableLoadingBody = require('./components/TableLoadingBody');
|
|
12
12
|
var table_classes = require('./table.classes');
|
|
13
13
|
var styles = require('./Table.module.css');
|
|
14
14
|
var table_utils = require('./table.utils');
|
|
@@ -51,6 +51,7 @@ function Table({
|
|
|
51
51
|
pageSizeOptions,
|
|
52
52
|
showHeader = true,
|
|
53
53
|
getRowSeverity,
|
|
54
|
+
getContextMenuItems,
|
|
54
55
|
onRowClick,
|
|
55
56
|
onRowMouseEnter,
|
|
56
57
|
onRowSelect,
|
|
@@ -64,6 +65,7 @@ function Table({
|
|
|
64
65
|
const internalTableRootRef = react.useRef(null);
|
|
65
66
|
const tableRootRefWrapper = react.useRef(tableRootRef);
|
|
66
67
|
const hasSelection = Boolean(selectedRows && onRowSelect);
|
|
68
|
+
const hasContextMenu = Boolean(getContextMenuItems);
|
|
67
69
|
const hasPagination = Boolean(onPageChange && (loading || data.length > 0));
|
|
68
70
|
const paginationOffset = hasPagination ? 72 : 0;
|
|
69
71
|
const { style: viewportFillStyle, maxHeight } = useViewportFill.useViewportFill(internalTableRootRef, {
|
|
@@ -86,7 +88,7 @@ function Table({
|
|
|
86
88
|
},
|
|
87
89
|
[onPageChange]
|
|
88
90
|
);
|
|
89
|
-
const bodyContent =
|
|
91
|
+
const bodyContent = /* @__PURE__ */ jsxRuntime.jsx(
|
|
90
92
|
TableBody.TableBody,
|
|
91
93
|
{
|
|
92
94
|
data,
|
|
@@ -99,6 +101,7 @@ function Table({
|
|
|
99
101
|
selectionInputName,
|
|
100
102
|
viewMode,
|
|
101
103
|
getRowSeverity,
|
|
104
|
+
getContextMenuItems,
|
|
102
105
|
onRowClick,
|
|
103
106
|
onRowMouseEnter,
|
|
104
107
|
onRowSelect
|
|
@@ -139,7 +142,7 @@ function Table({
|
|
|
139
142
|
ref: setTableRootRef,
|
|
140
143
|
className: styles__default.default.tableScroll,
|
|
141
144
|
style: fillViewportActive ? viewportFillStyle : !containScrolling ? { overflow: "visible" } : void 0,
|
|
142
|
-
children: !data.length
|
|
145
|
+
children: loading && !data.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.emptyStateSlot, children: /* @__PURE__ */ jsxRuntime.jsx(SkeletonLoader.SkeletonLoader, { type: "table", rows: 5, columns: 3 }) }) : !data.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.emptyStateSlot, children: /* @__PURE__ */ jsxRuntime.jsx(EmptyState.TableEmptyState, { config: emptyConfig }) }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
143
146
|
"table",
|
|
144
147
|
{
|
|
145
148
|
className: styles__default.default.tableElement,
|
|
@@ -155,13 +158,15 @@ function Table({
|
|
|
155
158
|
style: column.width != null ? { width: column.width } : void 0
|
|
156
159
|
},
|
|
157
160
|
column.id
|
|
158
|
-
))
|
|
161
|
+
)),
|
|
162
|
+
hasContextMenu ? /* @__PURE__ */ jsxRuntime.jsx("col", { style: { width: table_utils.CONTEXT_MENU_COLUMN_PX } }) : null
|
|
159
163
|
] }),
|
|
160
164
|
showHeader && /* @__PURE__ */ jsxRuntime.jsx(
|
|
161
165
|
TableHeader.TableHeader,
|
|
162
166
|
{
|
|
163
167
|
columns: visibleColumns,
|
|
164
168
|
hasSelection,
|
|
169
|
+
hasContextMenu,
|
|
165
170
|
selectionMode,
|
|
166
171
|
allRowsSelected,
|
|
167
172
|
onSelectAllRows,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { JSX } from 'react';
|
|
2
2
|
import type { TableProps } from './Table.types';
|
|
3
|
-
export declare function Table<T extends Record<string, any>>({ data, dataKey, columns, selectedRows, selectionMode, allRowsSelected, sortById, sortDirection, loading, emptyConfig, variant, size, viewMode, striped, fillViewport, fillViewportBottomOffset, containScrolling, stickyHeader, tableWidth, tableRootRef, measuringLayout, toolbar, headerExtras, take, skip, totalItemsCount, paginationPlacement, showFirstLast, showGoToPage, showPageSize, pageSizeOptions, showHeader, getRowSeverity, onRowClick, onRowMouseEnter, onRowSelect, onSelectAllRows, onSortChange, onPageChange, ...rest }: TableProps<T>): JSX.Element;
|
|
3
|
+
export declare function Table<T extends Record<string, any>>({ data, dataKey, columns, selectedRows, selectionMode, allRowsSelected, sortById, sortDirection, loading, emptyConfig, variant, size, viewMode, striped, fillViewport, fillViewportBottomOffset, containScrolling, stickyHeader, tableWidth, tableRootRef, measuringLayout, toolbar, headerExtras, take, skip, totalItemsCount, paginationPlacement, showFirstLast, showGoToPage, showPageSize, pageSizeOptions, showHeader, getRowSeverity, getContextMenuItems, onRowClick, onRowMouseEnter, onRowSelect, onSelectAllRows, onSortChange, onPageChange, ...rest }: TableProps<T>): JSX.Element;
|
|
4
4
|
export type { ColumnItem } from './Table.types';
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import { useMemo, useId, useRef, useCallback } from 'react';
|
|
4
4
|
import { Pagination } from '../../components/pagination/Pagination';
|
|
5
|
+
import { SkeletonLoader } from '../../components/skeleton-loader/SkeletonLoader';
|
|
5
6
|
import { useViewportFill } from '../../hooks/useViewportFill';
|
|
6
7
|
import { TableEmptyState } from './components/empty-state/EmptyState';
|
|
7
8
|
import { TableBody } from './components/TableBody';
|
|
8
9
|
import { TableHeader } from './components/TableHeader';
|
|
9
|
-
import { TableLoadingBody } from './components/TableLoadingBody';
|
|
10
10
|
import { cx } from './table.classes';
|
|
11
11
|
import styles from './Table.module.css';
|
|
12
|
-
import { getVisibleColumns, SELECTION_COLUMN_PX } from './table.utils';
|
|
12
|
+
import { getVisibleColumns, SELECTION_COLUMN_PX, CONTEXT_MENU_COLUMN_PX } from './table.utils';
|
|
13
13
|
|
|
14
14
|
function Table({
|
|
15
15
|
data,
|
|
@@ -45,6 +45,7 @@ function Table({
|
|
|
45
45
|
pageSizeOptions,
|
|
46
46
|
showHeader = true,
|
|
47
47
|
getRowSeverity,
|
|
48
|
+
getContextMenuItems,
|
|
48
49
|
onRowClick,
|
|
49
50
|
onRowMouseEnter,
|
|
50
51
|
onRowSelect,
|
|
@@ -58,6 +59,7 @@ function Table({
|
|
|
58
59
|
const internalTableRootRef = useRef(null);
|
|
59
60
|
const tableRootRefWrapper = useRef(tableRootRef);
|
|
60
61
|
const hasSelection = Boolean(selectedRows && onRowSelect);
|
|
62
|
+
const hasContextMenu = Boolean(getContextMenuItems);
|
|
61
63
|
const hasPagination = Boolean(onPageChange && (loading || data.length > 0));
|
|
62
64
|
const paginationOffset = hasPagination ? 72 : 0;
|
|
63
65
|
const { style: viewportFillStyle, maxHeight } = useViewportFill(internalTableRootRef, {
|
|
@@ -80,7 +82,7 @@ function Table({
|
|
|
80
82
|
},
|
|
81
83
|
[onPageChange]
|
|
82
84
|
);
|
|
83
|
-
const bodyContent =
|
|
85
|
+
const bodyContent = /* @__PURE__ */ jsx(
|
|
84
86
|
TableBody,
|
|
85
87
|
{
|
|
86
88
|
data,
|
|
@@ -93,6 +95,7 @@ function Table({
|
|
|
93
95
|
selectionInputName,
|
|
94
96
|
viewMode,
|
|
95
97
|
getRowSeverity,
|
|
98
|
+
getContextMenuItems,
|
|
96
99
|
onRowClick,
|
|
97
100
|
onRowMouseEnter,
|
|
98
101
|
onRowSelect
|
|
@@ -133,7 +136,7 @@ function Table({
|
|
|
133
136
|
ref: setTableRootRef,
|
|
134
137
|
className: styles.tableScroll,
|
|
135
138
|
style: fillViewportActive ? viewportFillStyle : !containScrolling ? { overflow: "visible" } : void 0,
|
|
136
|
-
children: !data.length
|
|
139
|
+
children: loading && !data.length ? /* @__PURE__ */ jsx("div", { className: styles.emptyStateSlot, children: /* @__PURE__ */ jsx(SkeletonLoader, { type: "table", rows: 5, columns: 3 }) }) : !data.length ? /* @__PURE__ */ jsx("div", { className: styles.emptyStateSlot, children: /* @__PURE__ */ jsx(TableEmptyState, { config: emptyConfig }) }) : /* @__PURE__ */ jsxs(
|
|
137
140
|
"table",
|
|
138
141
|
{
|
|
139
142
|
className: styles.tableElement,
|
|
@@ -149,13 +152,15 @@ function Table({
|
|
|
149
152
|
style: column.width != null ? { width: column.width } : void 0
|
|
150
153
|
},
|
|
151
154
|
column.id
|
|
152
|
-
))
|
|
155
|
+
)),
|
|
156
|
+
hasContextMenu ? /* @__PURE__ */ jsx("col", { style: { width: CONTEXT_MENU_COLUMN_PX } }) : null
|
|
153
157
|
] }),
|
|
154
158
|
showHeader && /* @__PURE__ */ jsx(
|
|
155
159
|
TableHeader,
|
|
156
160
|
{
|
|
157
161
|
columns: visibleColumns,
|
|
158
162
|
hasSelection,
|
|
163
|
+
hasContextMenu,
|
|
159
164
|
selectionMode,
|
|
160
165
|
allRowsSelected,
|
|
161
166
|
onSelectAllRows,
|
|
@@ -241,6 +241,14 @@
|
|
|
241
241
|
line-height: 0;
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
+
.headerCell.contextMenuCell,
|
|
245
|
+
.cell.contextMenuCell {
|
|
246
|
+
inline-size: 1%;
|
|
247
|
+
white-space: nowrap;
|
|
248
|
+
padding-inline: var(--spacing-2xs);
|
|
249
|
+
overflow: visible;
|
|
250
|
+
}
|
|
251
|
+
|
|
244
252
|
.headerCell.selectionCell {
|
|
245
253
|
padding-block: var(--spacing-xxs);
|
|
246
254
|
vertical-align: middle;
|
|
@@ -251,6 +259,15 @@
|
|
|
251
259
|
padding-block: var(--spacing-xxs);
|
|
252
260
|
}
|
|
253
261
|
|
|
262
|
+
.headerCell.contextMenuHeaderCell {
|
|
263
|
+
padding-block: var(--spacing-xxs);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.cell.contextMenuCell {
|
|
267
|
+
vertical-align: top;
|
|
268
|
+
padding-block: var(--spacing-2xs);
|
|
269
|
+
}
|
|
270
|
+
|
|
254
271
|
.selectionHitArea {
|
|
255
272
|
display: inline-flex;
|
|
256
273
|
align-items: flex-start;
|
|
@@ -475,6 +492,10 @@
|
|
|
475
492
|
text-align: right;
|
|
476
493
|
}
|
|
477
494
|
|
|
495
|
+
.contextMenuCellContent {
|
|
496
|
+
justify-content: flex-end;
|
|
497
|
+
}
|
|
498
|
+
|
|
478
499
|
/* vertical alignment inside content wrapper */
|
|
479
500
|
.cellContent[data-vertical-align='top'] {
|
|
480
501
|
align-items: flex-start;
|
|
@@ -535,6 +556,10 @@
|
|
|
535
556
|
text-overflow: clip;
|
|
536
557
|
}
|
|
537
558
|
|
|
559
|
+
.contextMenuTrigger {
|
|
560
|
+
color: var(--color-fg-subtle);
|
|
561
|
+
}
|
|
562
|
+
|
|
538
563
|
.severityTable {
|
|
539
564
|
--row-rail-width: 2px;
|
|
540
565
|
--row-rail-inset-block: 1px;
|
|
@@ -24,6 +24,14 @@ export type HeaderExtrasArgs<T> = {
|
|
|
24
24
|
column: ColumnItem<T>;
|
|
25
25
|
index: number;
|
|
26
26
|
};
|
|
27
|
+
export type TableContextMenuItem = {
|
|
28
|
+
label: ReactNode;
|
|
29
|
+
onClick: () => void;
|
|
30
|
+
active?: boolean;
|
|
31
|
+
selected?: boolean;
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
variant?: 'default' | 'danger';
|
|
34
|
+
};
|
|
27
35
|
export type StickyHeader = false | 'app-header' | number;
|
|
28
36
|
export type TableVariant = 'primary' | 'embedded';
|
|
29
37
|
export type SortDirection = 'asc' | 'desc' | null;
|
|
@@ -61,6 +69,11 @@ export type TableProps<T extends Record<string, any>> = Omit<HTMLAttributes<HTML
|
|
|
61
69
|
pageSizeOptions?: number[];
|
|
62
70
|
showHeader?: boolean;
|
|
63
71
|
getRowSeverity?: (row: T) => Severity | undefined;
|
|
72
|
+
getContextMenuItems?: (args: {
|
|
73
|
+
row: T;
|
|
74
|
+
rowId: string | number;
|
|
75
|
+
open: () => void;
|
|
76
|
+
}) => TableContextMenuItem[];
|
|
64
77
|
onRowClick?: (row: T) => void;
|
|
65
78
|
onRowMouseEnter?: (row: T) => void;
|
|
66
79
|
onRowSelect?: (rowId: number | string, isSelected: boolean) => void;
|