@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.
Files changed (44) hide show
  1. package/dist/components/card/Card.cjs +4 -7
  2. package/dist/components/card/Card.js +4 -7
  3. package/dist/components/card/Card.module.css +4 -9
  4. package/dist/components/code-block/CodeBlock.cjs +11 -1
  5. package/dist/components/code-block/CodeBlock.d.ts +1 -1
  6. package/dist/components/code-block/CodeBlock.js +12 -2
  7. package/dist/components/code-block/CodeBlock.module.css +12 -1
  8. package/dist/components/forms/file-upload/FileUpload.d.ts +2 -2
  9. package/dist/components/search-box/SearchBox.cjs +9 -4
  10. package/dist/components/search-box/SearchBox.js +9 -4
  11. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.cjs +3 -2
  12. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.js +4 -3
  13. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.module.css +5 -0
  14. package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.cjs +1 -1
  15. package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.js +1 -1
  16. package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.module.css +11 -7
  17. package/dist/components/table/Table.cjs +9 -4
  18. package/dist/components/table/Table.d.ts +1 -1
  19. package/dist/components/table/Table.js +10 -5
  20. package/dist/components/table/Table.module.css +25 -0
  21. package/dist/components/table/Table.types.d.ts +13 -0
  22. package/dist/components/table/TanstackTable.cjs +10 -1
  23. package/dist/components/table/TanstackTable.js +10 -1
  24. package/dist/components/table/components/TableBody.cjs +2 -0
  25. package/dist/components/table/components/TableBody.d.ts +7 -2
  26. package/dist/components/table/components/TableBody.js +2 -0
  27. package/dist/components/table/components/TableHeader.cjs +10 -1
  28. package/dist/components/table/components/TableHeader.d.ts +2 -1
  29. package/dist/components/table/components/TableHeader.js +10 -1
  30. package/dist/components/table/components/TableRow.cjs +75 -1
  31. package/dist/components/table/components/TableRow.d.ts +7 -2
  32. package/dist/components/table/components/TableRow.js +75 -1
  33. package/dist/components/table/hooks/useTableRowInteractions.cjs +2 -2
  34. package/dist/components/table/hooks/useTableRowInteractions.js +2 -2
  35. package/dist/components/table/table.utils.cjs +2 -0
  36. package/dist/components/table/table.utils.d.ts +1 -0
  37. package/dist/components/table/table.utils.js +2 -1
  38. package/dist/components/table/tanstackTable.utils.cjs +6 -4
  39. package/dist/components/table/tanstackTable.utils.d.ts +2 -0
  40. package/dist/components/table/tanstackTable.utils.js +7 -5
  41. package/package.json +1 -1
  42. package/dist/components/table/components/TableLoadingBody.cjs +0 -35
  43. package/dist/components/table/components/TableLoadingBody.d.ts +0 -9
  44. 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 SkeletonLoaderItem = require('../skeleton-loader/skeleton-loader-item/SkeletonLoaderItem');
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 = 4,
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.loadingList, "aria-busy": "true", "aria-live": "polite", children: Array.from({ length: 4 }, (_, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.loadingRow, children: [
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 { SkeletonLoaderItem } from '../skeleton-loader/skeleton-loader-item/SkeletonLoaderItem';
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 = 4,
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.loadingList, "aria-busy": "true", "aria-live": "polite", children: Array.from({ length: 4 }, (_, index) => /* @__PURE__ */ jsxs("div", { className: styles.loadingRow, children: [
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
- .loadingList {
162
+ .loadingBody {
163
163
  display: flex;
164
- flex-direction: column;
165
- gap: var(--spacing-md);
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 = [
@@ -4,7 +4,7 @@ export interface CodeBlockProps {
4
4
  children?: ReactNode;
5
5
  copyButton?: boolean;
6
6
  copyText?: string;
7
- size?: 'sm' | 'md' | 'lg';
7
+ size?: 'xs' | 'sm' | 'md' | 'lg';
8
8
  smart?: boolean;
9
9
  wrap?: boolean;
10
10
  }
@@ -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
- /** Short hint shown below the icon when no custom children */
8
- hint?: string;
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
- if (!onSearch) return;
66
+ onSearchRef.current = onSearch;
67
+ }, [onSearch]);
68
+ react.useEffect(() => {
69
+ if (!onSearchRef.current) return;
66
70
  if (!debounce) {
67
71
  setSearchQuery(draft);
68
- onSearch(draft);
72
+ onSearchRef.current(draft);
69
73
  return;
70
74
  }
71
75
  const handler = setTimeout(() => {
76
+ var _a2;
72
77
  setSearchQuery(draft);
73
- onSearch(draft);
78
+ (_a2 = onSearchRef.current) == null ? void 0 : _a2.call(onSearchRef, draft);
74
79
  }, debounceMs);
75
80
  return () => clearTimeout(handler);
76
- }, [draft, onSearch, debounce, debounceMs]);
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
- if (!onSearch) return;
60
+ onSearchRef.current = onSearch;
61
+ }, [onSearch]);
62
+ useEffect(() => {
63
+ if (!onSearchRef.current) return;
60
64
  if (!debounce) {
61
65
  setSearchQuery(draft);
62
- onSearch(draft);
66
+ onSearchRef.current(draft);
63
67
  return;
64
68
  }
65
69
  const handler = setTimeout(() => {
70
+ var _a2;
66
71
  setSearchQuery(draft);
67
- onSearch(draft);
72
+ (_a2 = onSearchRef.current) == null ? void 0 : _a2.call(onSearchRef, draft);
68
73
  }, debounceMs);
69
74
  return () => clearTimeout(handler);
70
- }, [draft, onSearch, debounce, debounceMs]);
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: "md",
172
+ size: "sm",
173
173
  variant: "inline",
174
174
  shape: "round",
175
175
  "aria-label": "Collapse sidebar",
176
- icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: isSidebarCollapsed ? styles__default.default.collapsedIcon : "" }),
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 { ChevronLeft } from 'lucide-react';
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: "md",
165
+ size: "sm",
166
166
  variant: "inline",
167
167
  shape: "round",
168
168
  "aria-label": "Collapse sidebar",
169
- icon: /* @__PURE__ */ jsx(ChevronLeft, { className: isSidebarCollapsed ? styles.collapsedIcon : "" }),
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
  )
@@ -15,6 +15,11 @@
15
15
  inline-size var(--transition-fast) var(--ease-standard);
16
16
  }
17
17
 
18
+ .sidebarIcon {
19
+ inline-size: var(--icon-size-sm);
20
+ block-size: var(--icon-size-sm);
21
+ color: var(--color-fg-subtle);
22
+ }
18
23
  .container.resizing {
19
24
  transition: none;
20
25
  }
@@ -11,7 +11,7 @@ function SkeletonLoaderItem({
11
11
  height = 14,
12
12
  width = "100%",
13
13
  radius = 6,
14
- speedSec = 3,
14
+ speedSec = 4,
15
15
  ariaLabel = "Loading",
16
16
  variant = "default"
17
17
  }) {
@@ -5,7 +5,7 @@ function SkeletonLoaderItem({
5
5
  height = 14,
6
6
  width = "100%",
7
7
  radius = 6,
8
- speedSec = 3,
8
+ speedSec = 4,
9
9
  ariaLabel = "Loading",
10
10
  variant = "default"
11
11
  }) {
@@ -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-dark);
6
- --skeleton-sheen: var(--opac-bg-default);
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-sheen) 0%,
18
- var(--skeleton-base) 45%,
19
- var(--skeleton-sheen) 60%,
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: 200% 100%;
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-dark-invert);
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 = loading && !data.length ? /* @__PURE__ */ jsxRuntime.jsx(TableLoadingBody.TableLoadingBody, { rows: take != null ? take : 5, columns: visibleColumns, hasSelection }) : /* @__PURE__ */ jsxRuntime.jsx(
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 && !loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.emptyStateSlot, children: /* @__PURE__ */ jsxRuntime.jsx(EmptyState.TableEmptyState, { config: emptyConfig }) }) : /* @__PURE__ */ jsxRuntime.jsxs(
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 = loading && !data.length ? /* @__PURE__ */ jsx(TableLoadingBody, { rows: take != null ? take : 5, columns: visibleColumns, hasSelection }) : /* @__PURE__ */ jsx(
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 && !loading ? /* @__PURE__ */ jsx("div", { className: styles.emptyStateSlot, children: /* @__PURE__ */ jsx(TableEmptyState, { config: emptyConfig }) }) : /* @__PURE__ */ jsxs(
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;