@dbcdk/react-components 0.0.88 → 0.0.90

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 (70) hide show
  1. package/dist/components/accordion/Accordion.d.ts +1 -0
  2. package/dist/components/accordion/components/AccordionRow.js +1 -1
  3. package/dist/components/avatar/Avatar.js +16 -10
  4. package/dist/components/avatar/Avatar.module.css +33 -12
  5. package/dist/components/button/Button.js +8 -1
  6. package/dist/components/button/Button.module.css +2 -1
  7. package/dist/components/card/Card.d.ts +1 -5
  8. package/dist/components/card/Card.js +29 -4
  9. package/dist/components/card/Card.module.css +86 -98
  10. package/dist/components/card-container/CardContainer.d.ts +2 -1
  11. package/dist/components/card-container/CardContainer.js +2 -2
  12. package/dist/components/card-container/CardContainer.module.css +10 -9
  13. package/dist/components/clear-button/ClearButton.d.ts +2 -1
  14. package/dist/components/clear-button/ClearButton.js +6 -2
  15. package/dist/components/clear-button/ClearButton.module.css +6 -0
  16. package/dist/components/divider/Divider.d.ts +5 -0
  17. package/dist/components/divider/Divider.js +12 -0
  18. package/dist/components/forms/input/Input.d.ts +2 -1
  19. package/dist/components/forms/input/Input.js +6 -2
  20. package/dist/components/forms/input/Input.module.css +32 -0
  21. package/dist/components/forms/select/Select.d.ts +2 -1
  22. package/dist/components/forms/select/Select.js +2 -2
  23. package/dist/components/forms/typeahead/Typeahead.d.ts +2 -1
  24. package/dist/components/forms/typeahead/Typeahead.js +180 -118
  25. package/dist/components/forms/typeahead/Typeahead.module.css +4 -0
  26. package/dist/components/grid/Grid.d.ts +23 -0
  27. package/dist/components/grid/Grid.js +23 -0
  28. package/dist/components/grid/Grid.module.css +35 -0
  29. package/dist/components/headline/CollapsibleHeadline.d.ts +21 -0
  30. package/dist/components/headline/CollapsibleHeadline.js +29 -0
  31. package/dist/components/headline/Headline.d.ts +7 -5
  32. package/dist/components/headline/Headline.js +7 -6
  33. package/dist/components/headline/Headline.module.css +80 -8
  34. package/dist/components/nav-bar/NavBar.module.css +6 -2
  35. package/dist/components/overlay/modal/Modal.d.ts +2 -1
  36. package/dist/components/overlay/modal/Modal.js +5 -3
  37. package/dist/components/overlay/modal/provider/ModalProvider.js +2 -0
  38. package/dist/components/overlay/side-panel/SidePanel.d.ts +2 -1
  39. package/dist/components/overlay/side-panel/SidePanel.js +2 -2
  40. package/dist/components/page/Page.d.ts +5 -1
  41. package/dist/components/page/Page.js +6 -2
  42. package/dist/components/page/Page.module.css +54 -4
  43. package/dist/components/panel/Panel.d.ts +2 -1
  44. package/dist/components/panel/Panel.js +2 -2
  45. package/dist/components/popover/Popover.js +1 -1
  46. package/dist/components/stack/Stack.d.ts +16 -0
  47. package/dist/components/stack/Stack.js +19 -0
  48. package/dist/components/state-page/StatePage.d.ts +2 -1
  49. package/dist/components/state-page/StatePage.js +2 -2
  50. package/dist/components/table/Table.d.ts +1 -1
  51. package/dist/components/table/Table.js +22 -4
  52. package/dist/components/table/Table.module.css +14 -0
  53. package/dist/components/table/Table.types.d.ts +1 -0
  54. package/dist/components/tabs/Tabs.d.ts +3 -1
  55. package/dist/components/tabs/Tabs.js +4 -2
  56. package/dist/components/tabs/Tabs.module.css +4 -0
  57. package/dist/components/theme-button/ThemeButton.d.ts +1 -0
  58. package/dist/components/theme-button/ThemeButton.js +5 -1
  59. package/dist/components/toast/Toast.d.ts +2 -1
  60. package/dist/components/toast/Toast.js +2 -2
  61. package/dist/hooks/useViewportFill.d.ts +2 -6
  62. package/dist/hooks/useViewportFill.js +29 -24
  63. package/dist/index.d.ts +5 -0
  64. package/dist/index.js +5 -0
  65. package/dist/styles/css-helper-classes/flex.css +12 -0
  66. package/dist/styles/css-helper-classes/spacing.css +5 -0
  67. package/dist/styles/styles.css +154 -66
  68. package/dist/styles/themes/dbc/colors.css +10 -0
  69. package/dist/styles.css +154 -66
  70. package/package.json +1 -1
@@ -5,7 +5,7 @@ import { ErrorIllustration } from './error';
5
5
  import { NotFoundIllustration } from './notFound';
6
6
  import styles from './StatePage.module.css';
7
7
  import { Headline } from '../headline/Headline';
8
- export function StatePage({ header, type, children, actions }) {
8
+ export function StatePage({ header, subheader, type, children, actions, }) {
9
9
  const illustration = useMemo(() => {
10
10
  switch (type) {
11
11
  case 'error':
@@ -16,5 +16,5 @@ export function StatePage({ header, type, children, actions }) {
16
16
  return _jsx(NotFoundIllustration, {});
17
17
  }
18
18
  }, [type]);
19
- return (_jsxs("div", { className: `dbc-flex dbc-flex-column dbc-gap-lg dbc-items-center dbc-justify-center ${styles.container}`, children: [_jsx("div", { className: styles.illustration, children: illustration }), _jsxs("div", { className: "dbc-flex dbc-flex-column dbc-gap-md dbc-items-center", children: [_jsx(Headline, { disableMargin: true, size: 1, children: header }), _jsx("div", { children: children }), _jsx("div", { className: "dbc-flex dbc-gap-sm dbc-justify-center", children: actions })] })] }));
19
+ return (_jsxs("div", { className: `dbc-flex dbc-flex-column dbc-gap-lg dbc-items-center dbc-justify-center ${styles.container}`, children: [_jsx("div", { className: styles.illustration, children: illustration }), _jsxs("div", { className: "dbc-flex dbc-flex-column dbc-gap-md dbc-items-center", children: [_jsx(Headline, { disableMargin: true, size: 1, subheader: subheader, children: header }), _jsx("div", { children: children }), _jsx("div", { className: "dbc-flex dbc-gap-sm dbc-justify-center", children: actions })] })] }));
20
20
  }
@@ -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, tableWidth, tableRootRef, measuringLayout, toolbar, headerExtras, take, skip, totalItemsCount, paginationPlacement, showFirstLast, pageSizeOptions, 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, tableWidth, tableRootRef, measuringLayout, toolbar, headerExtras, take, skip, totalItemsCount, paginationPlacement, showFirstLast, pageSizeOptions, getRowSeverity, onRowClick, onRowMouseEnter, onRowSelect, onSelectAllRows, onSortChange, onPageChange, ...rest }: TableProps<T>): JSX.Element;
4
4
  export type { ColumnItem } from './Table.types';
@@ -1,7 +1,8 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useCallback, useId, useMemo } from 'react';
3
+ import { useCallback, useId, useMemo, useRef } from 'react';
4
4
  import { Pagination } from '../../components/pagination/Pagination';
5
+ import { useViewportFill } from '../../hooks/useViewportFill';
5
6
  import { TableEmptyState } from './components/empty-state/EmptyState';
6
7
  import { TableBody } from './components/TableBody';
7
8
  import { TableHeader } from './components/TableHeader';
@@ -9,17 +10,34 @@ import { TableLoadingBody } from './components/TableLoadingBody';
9
10
  import { cx } from './table.classes';
10
11
  import styles from './Table.module.css';
11
12
  import { getVisibleColumns, SELECTION_COLUMN_PX } from './table.utils';
12
- export function Table({ data, dataKey, columns, selectedRows, selectionMode = 'single', allRowsSelected, sortById, sortDirection, loading, emptyConfig, variant = 'primary', size = 'md', viewMode, striped, fillViewport = false, tableWidth, tableRootRef, measuringLayout = false, toolbar, headerExtras, take, skip, totalItemsCount, paginationPlacement = 'bottom', showFirstLast = false, pageSizeOptions, getRowSeverity, onRowClick, onRowMouseEnter, onRowSelect, onSelectAllRows, onSortChange, onPageChange, ...rest }) {
13
+ export function Table({ data, dataKey, columns, selectedRows, selectionMode = 'single', allRowsSelected, sortById, sortDirection, loading, emptyConfig, variant = 'primary', size = 'md', viewMode, striped, fillViewport = false, fillViewportBottomOffset = 16, tableWidth, tableRootRef, measuringLayout = false, toolbar, headerExtras, take, skip, totalItemsCount, paginationPlacement = 'bottom', showFirstLast = false, pageSizeOptions, getRowSeverity, onRowClick, onRowMouseEnter, onRowSelect, onSelectAllRows, onSortChange, onPageChange, ...rest }) {
13
14
  const visibleColumns = useMemo(() => getVisibleColumns(columns), [columns]);
14
15
  const selectionInputName = useId();
16
+ const internalTableRootRef = useRef(null);
17
+ const tableRootRefWrapper = useRef(tableRootRef);
15
18
  const hasSelection = Boolean(selectedRows && onRowSelect);
19
+ const hasPagination = Boolean(onPageChange && (loading || data.length > 0));
20
+ const paginationOffset = hasPagination ? 72 : 0;
21
+ const { style: viewportFillStyle } = useViewportFill(internalTableRootRef, {
22
+ bottomOffset: fillViewportBottomOffset + paginationOffset,
23
+ min: 120,
24
+ });
25
+ const setTableRootRef = useCallback((node) => {
26
+ internalTableRootRef.current = node;
27
+ if (typeof tableRootRefWrapper.current === 'function') {
28
+ tableRootRefWrapper.current(node);
29
+ }
30
+ else if (tableRootRefWrapper.current) {
31
+ tableRootRefWrapper.current.current = node;
32
+ }
33
+ }, []);
16
34
  const handlePageChange = useCallback((e) => {
17
35
  onPageChange === null || onPageChange === void 0 ? void 0 : onPageChange(e);
18
36
  }, [onPageChange]);
19
37
  const bodyContent = loading && !data.length ? (_jsx(TableLoadingBody, { rows: take !== null && take !== void 0 ? take : 5, columns: visibleColumns, hasSelection: hasSelection })) : (_jsx(TableBody, { data: data, dataKey: dataKey, columns: visibleColumns, striped: striped, selectedRows: selectedRows, hasSelection: hasSelection, selectionMode: selectionMode, selectionInputName: selectionInputName, viewMode: viewMode, getRowSeverity: getRowSeverity, onRowClick: onRowClick, onRowMouseEnter: onRowMouseEnter, onRowSelect: onRowSelect }));
20
- const paginationEl = onPageChange && (loading || data.length > 0) ? (_jsx("div", { className: cx(styles.paginationSlot, paginationPlacement === 'top' && styles.paginationSlotTop), children: _jsx(Pagination, { itemsCount: totalItemsCount, take: take, skip: skip, onPageChange: handlePageChange, showFirstLast: showFirstLast, pageSizeOptions: pageSizeOptions }) })) : null;
38
+ const paginationEl = hasPagination ? (_jsx("div", { className: cx(styles.paginationSlot, paginationPlacement === 'top' && styles.paginationSlotTop), children: _jsx(Pagination, { itemsCount: totalItemsCount, take: take, skip: skip, onPageChange: handlePageChange, showFirstLast: showFirstLast, pageSizeOptions: pageSizeOptions }) })) : null;
21
39
  const tableClassName = cx(styles.tableRoot, styles[variant], styles[size], measuringLayout && styles.measuringLayout, getRowSeverity && styles.severityTable);
22
- const tableShell = (_jsx("div", { ...rest, className: tableClassName, children: _jsx("div", { ref: tableRootRef, className: styles.tableScroll, children: !data.length && !loading ? (_jsx("div", { className: styles.emptyStateSlot, children: _jsx(TableEmptyState, { config: emptyConfig }) })) : (_jsxs("table", { className: styles.tableElement, "aria-rowcount": data.length, style: tableWidth != null ? { width: tableWidth } : undefined, children: [_jsxs("colgroup", { children: [hasSelection ? _jsx("col", { style: { width: SELECTION_COLUMN_PX } }) : null, visibleColumns.map(column => (_jsx("col", { style: column.width != null ? { width: column.width } : undefined }, column.id)))] }), _jsx(TableHeader, { columns: visibleColumns, hasSelection: hasSelection, selectionMode: selectionMode, allRowsSelected: allRowsSelected, onSelectAllRows: onSelectAllRows, sortById: sortById, sortDirection: sortDirection, onSortChange: onSortChange, headerExtras: headerExtras }), bodyContent] })) }) }));
40
+ const tableShell = (_jsx("div", { ...rest, className: tableClassName, children: _jsx("div", { ref: setTableRootRef, className: styles.tableScroll, style: fillViewport ? viewportFillStyle : undefined, children: !data.length && !loading ? (_jsx("div", { className: styles.emptyStateSlot, children: _jsx(TableEmptyState, { config: emptyConfig }) })) : (_jsxs("table", { className: styles.tableElement, "aria-rowcount": data.length, style: tableWidth != null ? { width: tableWidth } : undefined, children: [_jsxs("colgroup", { children: [hasSelection ? _jsx("col", { style: { width: SELECTION_COLUMN_PX } }) : null, visibleColumns.map(column => (_jsx("col", { style: column.width != null ? { width: column.width } : undefined }, column.id)))] }), _jsx(TableHeader, { columns: visibleColumns, hasSelection: hasSelection, selectionMode: selectionMode, allRowsSelected: allRowsSelected, onSelectAllRows: onSelectAllRows, sortById: sortById, sortDirection: sortDirection, onSortChange: onSortChange, headerExtras: headerExtras }), bodyContent] })) }) }));
23
41
  if (fillViewport) {
24
42
  return (_jsxs("div", { className: styles.fillViewportRoot, style: {
25
43
  flexDirection: paginationPlacement === 'top' ? 'column-reverse' : 'column',
@@ -101,6 +101,10 @@
101
101
  min-block-size: 0;
102
102
  }
103
103
 
104
+ .body .row:first-child .cell {
105
+ border-block-start: var(--spacing-xs) solid var(--table-row-bg);
106
+ }
107
+
104
108
  .headerCell,
105
109
  .cell {
106
110
  position: relative;
@@ -136,6 +140,16 @@
136
140
  line-height: 20px;
137
141
  }
138
142
 
143
+ .md .headerCell {
144
+ padding-block: var(--spacing-xs);
145
+ padding-inline: var(--spacing-sm);
146
+ }
147
+
148
+ .md .cell {
149
+ padding-block: var(--spacing-xs);
150
+ padding-inline: var(--spacing-sm);
151
+ }
152
+
139
153
  .sm .headerCell {
140
154
  padding-block: var(--spacing-xxs);
141
155
  padding-inline: var(--spacing-sm);
@@ -42,6 +42,7 @@ export type TableProps<T extends Record<string, any>> = Omit<HTMLAttributes<HTML
42
42
  viewMode?: ViewMode;
43
43
  striped?: boolean;
44
44
  fillViewport?: boolean;
45
+ fillViewportBottomOffset?: number;
45
46
  tableWidth?: number;
46
47
  tableRootRef?: Ref<HTMLDivElement>;
47
48
  measuringLayout?: boolean;
@@ -12,6 +12,7 @@ export type TabItem = {
12
12
  type TabsVariant = 'filled' | 'outlined';
13
13
  export interface TabsProps {
14
14
  header?: string;
15
+ subheader?: ReactNode;
15
16
  variant: TabsVariant;
16
17
  panelStyle?: boolean;
17
18
  /** Data-driven API */
@@ -22,6 +23,7 @@ export interface TabsProps {
22
23
  defaultValue?: TabId;
23
24
  onValueChange?: (id: TabId, tab: TabItem, index: number) => void;
24
25
  addition?: ReactNode;
26
+ disableTopPadding?: boolean;
25
27
  /** Composition API */
26
28
  children?: ReactNode;
27
29
  }
@@ -38,7 +40,7 @@ type SlotName = 'Item';
38
40
  type TabsItemComponent = ((props: TabsItemProps) => JSX.Element) & {
39
41
  __TABS_SLOT__?: SlotName;
40
42
  };
41
- export declare function Tabs({ header, variant, panelStyle, tabs, value, defaultValue, onValueChange, addition, children, }: TabsProps): JSX.Element;
43
+ export declare function Tabs({ header, subheader, variant, panelStyle, tabs, value, defaultValue, onValueChange, addition, disableTopPadding, children, }: TabsProps): JSX.Element;
42
44
  export declare namespace Tabs {
43
45
  var Item: TabsItemComponent;
44
46
  }
@@ -33,7 +33,7 @@ function normalizeFromChildren(children) {
33
33
  });
34
34
  return items;
35
35
  }
36
- export function Tabs({ header, variant, panelStyle = false, tabs, value, defaultValue, onValueChange, addition, children, }) {
36
+ export function Tabs({ header, subheader, variant, panelStyle = false, tabs, value, defaultValue, onValueChange, addition, disableTopPadding, children, }) {
37
37
  const uid = useId();
38
38
  // Data API wins if provided; otherwise parse <Tabs.Item>
39
39
  const sourceTabs = useMemo(() => {
@@ -113,7 +113,9 @@ export function Tabs({ header, variant, panelStyle = false, tabs, value, default
113
113
  focusAndSelect(enabled.length - 1);
114
114
  }
115
115
  }, [uid, visibleTabs, setValue]);
116
- return (_jsxs("div", { className: styles.root, children: [header ? (_jsxs("div", { className: styles.headerContainer, children: [_jsx(Headline, { disableMargin: true, size: 2, children: header }), addition] })) : null, _jsxs("div", { className: `${styles.tabs} ${styles[variant]} ${panelStyle ? styles.panelStyle : ''}`, children: [_jsx("div", { className: styles.tabList, role: "tablist", "aria-label": header !== null && header !== void 0 ? header : 'Tabs', children: visibleTabs.map((tab, index) => {
116
+ return (_jsxs("div", { className: styles.root, children: [header ? (_jsx("div", { className: [styles.headerContainer, disableTopPadding ? styles.disableTopPadding : '']
117
+ .filter(Boolean)
118
+ .join(' '), children: _jsx(Headline, { disableMargin: true, size: 2, subheader: subheader, addition: addition, children: header }) })) : null, _jsxs("div", { className: `${styles.tabs} ${styles[variant]} ${panelStyle ? styles.panelStyle : ''}`, children: [_jsx("div", { className: styles.tabList, role: "tablist", "aria-label": header !== null && header !== void 0 ? header : 'Tabs', children: visibleTabs.map((tab, index) => {
117
119
  const selected = index === activeIndex;
118
120
  const tabDomId = `${uid}-tab-${String(tab.id)}`;
119
121
  const panelDomId = `${uid}-panel-${String(tab.id)}`;
@@ -13,6 +13,10 @@
13
13
  gap: var(--spacing-md);
14
14
  }
15
15
 
16
+ .headerContainer.disableTopPadding {
17
+ padding-block-start: 0;
18
+ }
19
+
16
20
  /* Outer wrapper for tablist + content */
17
21
  .tabs {
18
22
  display: flex;
@@ -4,4 +4,5 @@ export interface ThemeButtonProps {
4
4
  size?: ButtonSize;
5
5
  variant?: ButtonVariant;
6
6
  }
7
+ export declare function ThemeMenuSection(): JSX.Element;
7
8
  export declare function ThemeButton({ size, variant }: ThemeButtonProps): JSX.Element;
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Monitor, Moon, Palette, Sun } from 'lucide-react';
4
4
  import { Button } from '../../components/button/Button';
5
5
  import { Menu } from '../../components/menu/Menu';
@@ -10,6 +10,10 @@ const THEME_OPTIONS = [
10
10
  { value: 'light', label: 'Lyst', icon: _jsx(Sun, { size: 16 }) },
11
11
  { value: 'dark', label: 'Mørkt', icon: _jsx(Moon, { size: 16 }) },
12
12
  ];
13
+ export function ThemeMenuSection() {
14
+ const { theme, switchTheme } = useTheme();
15
+ return (_jsxs(_Fragment, { children: [_jsx(Menu.Header, { children: "Udseende" }), THEME_OPTIONS.map(option => (_jsx(Menu.RadioItem, { name: "theme", value: option.value, checked: theme === option.value, label: option.label, onValueChange: value => switchTheme(value) }, option.value)))] }));
16
+ }
13
17
  export function ThemeButton({ size, variant = 'outlined' }) {
14
18
  const { theme, switchTheme } = useTheme();
15
19
  return (_jsx(Popover, { matchTriggerWidth: false, minWidth: "140px", trigger: (handleClick, chevron) => (_jsxs(Button, { variant: variant, size: size, onClick: handleClick, "aria-label": "Skift tema", "aria-haspopup": "menu", children: [_jsx(Palette, {}), chevron] })), children: close => (_jsxs(Menu, { children: [_jsx(Menu.Header, { children: "Udseende" }), THEME_OPTIONS.map(option => (_jsx(Menu.Item, { active: theme === option.value, children: _jsxs("button", { onClick: () => {
@@ -6,9 +6,10 @@ export type ToastActionConfig = {
6
6
  };
7
7
  export type ToastProps = {
8
8
  title?: ReactNode;
9
+ subheader?: ReactNode;
9
10
  message?: ReactNode;
10
11
  severity: Severity;
11
12
  action?: ToastActionConfig;
12
13
  onClose?: () => void;
13
14
  };
14
- export declare function Toast({ title, message, severity, action, onClose, }: ToastProps): React.ReactNode;
15
+ export declare function Toast({ title, subheader, message, severity, action, onClose, }: ToastProps): React.ReactNode;
@@ -3,7 +3,7 @@ import { X } from 'lucide-react';
3
3
  import styles from './Toast.module.css';
4
4
  import { Button } from '../button/Button';
5
5
  import { Headline } from '../headline/Headline';
6
- export function Toast({ title, message, severity = 'info', action, onClose, }) {
6
+ export function Toast({ title, subheader, message, severity = 'info', action, onClose, }) {
7
7
  const showHeader = Boolean(title);
8
8
  const showMessage = Boolean(message);
9
9
  const canClose = severity !== 'neutral';
@@ -16,5 +16,5 @@ export function Toast({ title, message, severity = 'info', action, onClose, }) {
16
16
  onClose === null || onClose === void 0 ? void 0 : onClose();
17
17
  }
18
18
  }
19
- : undefined, tabIndex: isDismissibleNeutral ? 0 : undefined, "aria-label": isDismissibleNeutral ? 'Luk notifikation' : undefined, children: [_jsxs("div", { className: styles.content, children: [showHeader && (_jsxs("div", { className: styles.row, children: [_jsx(Headline, { size: 4, severity: severity, disableMargin: true, children: title }), CloseButton] })), showMessage && (_jsxs("div", { className: styles.row, children: [_jsx("div", { className: styles.message, children: message }), !showHeader && CloseButton] }))] }), action && (_jsx("div", { className: styles.actions, children: _jsx(Button, { type: "button", variant: "primary", onClick: action.onClick, children: action.label }) }))] }));
19
+ : undefined, tabIndex: isDismissibleNeutral ? 0 : undefined, "aria-label": isDismissibleNeutral ? 'Luk notifikation' : undefined, children: [_jsxs("div", { className: styles.content, children: [showHeader && (_jsxs("div", { className: styles.row, children: [_jsx(Headline, { size: 4, severity: severity, disableMargin: true, subheader: subheader, children: title }), CloseButton] })), showMessage && (_jsxs("div", { className: styles.row, children: [_jsx("div", { className: styles.message, children: message }), !showHeader && CloseButton] }))] }), action && (_jsx("div", { className: styles.actions, children: _jsx(Button, { type: "button", variant: "primary", onClick: action.onClick, children: action.label }) }))] }));
20
20
  }
@@ -1,15 +1,11 @@
1
- import { CSSProperties, RefObject } from 'react';
1
+ import { type CSSProperties, type RefObject } from 'react';
2
2
  type Options = {
3
3
  bottomOffset?: number;
4
4
  min?: number;
5
5
  includeMarginTop?: boolean;
6
- /**
7
- * Optional element to observe in addition to the target itself.
8
- * Useful when a nearby wrapper changes height and pushes the table.
9
- */
10
6
  watchRef?: RefObject<HTMLElement | null>;
11
7
  };
12
- export declare function useViewportFill<T extends HTMLElement>(ref: RefObject<T>, { bottomOffset, min, includeMarginTop, watchRef }?: Options): {
8
+ export declare function useViewportFill<T extends HTMLElement>(ref: RefObject<T | null>, { bottomOffset, min, includeMarginTop, watchRef }?: Options): {
13
9
  maxHeight: number;
14
10
  style: CSSProperties;
15
11
  recompute: () => void;
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { useCallback, useEffect, useLayoutEffect, useRef, useState, } from 'react';
2
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
3
3
  const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
4
4
  export function useViewportFill(ref, { bottomOffset = 0, min = 120, includeMarginTop = false, watchRef } = {}) {
5
5
  const [maxHeight, setMaxHeight] = useState(min);
@@ -11,18 +11,22 @@ export function useViewportFill(ref, { bottomOffset = 0, min = 120, includeMargi
11
11
  const rect = el.getBoundingClientRect();
12
12
  let top = rect.top;
13
13
  if (includeMarginTop) {
14
- const mt = parseFloat(window.getComputedStyle(el).marginTop || '0') || 0;
15
- top -= mt;
14
+ const marginTop = parseFloat(window.getComputedStyle(el).marginTop || '0') || 0;
15
+ top -= marginTop;
16
16
  }
17
17
  const next = Math.max(min, Math.floor(window.innerHeight - bottomOffset - top));
18
- setMaxHeight(prev => (prev !== next ? next : prev));
18
+ setMaxHeight(prev => (prev === next ? prev : next));
19
19
  }, [ref, bottomOffset, min, includeMarginTop]);
20
20
  const scheduleMeasure = useCallback(() => {
21
21
  if (typeof window === 'undefined')
22
22
  return;
23
- if (raf.current != null)
23
+ if (raf.current != null) {
24
24
  cancelAnimationFrame(raf.current);
25
- raf.current = window.requestAnimationFrame(measure);
25
+ }
26
+ raf.current = window.requestAnimationFrame(() => {
27
+ raf.current = null;
28
+ measure();
29
+ });
26
30
  }, [measure]);
27
31
  useIsomorphicLayoutEffect(() => {
28
32
  measure();
@@ -34,39 +38,40 @@ export function useViewportFill(ref, { bottomOffset = 0, min = 120, includeMargi
34
38
  const target = ref.current;
35
39
  const extra = (_a = watchRef === null || watchRef === void 0 ? void 0 : watchRef.current) !== null && _a !== void 0 ? _a : null;
36
40
  const parent = target.parentElement;
37
- const onResizeOrScroll = () => scheduleMeasure();
41
+ const onResize = () => scheduleMeasure();
38
42
  const onTransitionOrAnimationEnd = () => scheduleMeasure();
39
- window.addEventListener('resize', onResizeOrScroll);
40
- window.addEventListener('scroll', onResizeOrScroll, { passive: true });
41
- // Cheap and often enough for collapsible filter panels.
43
+ window.addEventListener('resize', onResize);
42
44
  document.addEventListener('transitionend', onTransitionOrAnimationEnd, true);
43
45
  document.addEventListener('animationend', onTransitionOrAnimationEnd, true);
44
- let ro = null;
46
+ let resizeObserver = null;
45
47
  if ('ResizeObserver' in window) {
46
- ro = new ResizeObserver(() => scheduleMeasure());
47
- ro.observe(target);
48
- if (parent && parent !== target)
49
- ro.observe(parent);
50
- if (extra && extra !== target && extra !== parent)
51
- ro.observe(extra);
48
+ resizeObserver = new ResizeObserver(() => scheduleMeasure());
49
+ resizeObserver.observe(target);
50
+ if (parent && parent !== target) {
51
+ resizeObserver.observe(parent);
52
+ }
53
+ if (extra && extra !== target && extra !== parent) {
54
+ resizeObserver.observe(extra);
55
+ }
52
56
  }
53
57
  return () => {
54
- window.removeEventListener('resize', onResizeOrScroll);
55
- window.removeEventListener('scroll', onResizeOrScroll);
58
+ window.removeEventListener('resize', onResize);
56
59
  document.removeEventListener('transitionend', onTransitionOrAnimationEnd, true);
57
60
  document.removeEventListener('animationend', onTransitionOrAnimationEnd, true);
58
- ro === null || ro === void 0 ? void 0 : ro.disconnect();
61
+ resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect();
59
62
  if (raf.current != null) {
60
63
  cancelAnimationFrame(raf.current);
64
+ raf.current = null;
61
65
  }
62
66
  };
63
67
  }, [ref, watchRef, scheduleMeasure]);
68
+ const style = useMemo(() => ({
69
+ maxHeight,
70
+ overflow: 'auto',
71
+ }), [maxHeight]);
64
72
  return {
65
73
  maxHeight,
66
- style: {
67
- maxHeight,
68
- overflow: 'auto',
69
- },
74
+ style,
70
75
  recompute: measure,
71
76
  };
72
77
  }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './components/stack/Stack';
1
2
  export * from './components/button/Button';
2
3
  export * from './components/button-select/ButtonSelect';
3
4
  export * from './components/nav-bar/NavBar';
@@ -8,6 +9,7 @@ export * from './components/icon/Icon';
8
9
  export * from './components/user-display/UserDisplay';
9
10
  export * from './components/tabs/Tabs';
10
11
  export * from './components/headline/Headline';
12
+ export * from './components/headline/CollapsibleHeadline';
11
13
  export * from './components/page-layout/PageLayout';
12
14
  export * from './components/page-layout/components/layout-footer/LayoutFooter';
13
15
  export * from './components/forms/input/Input';
@@ -71,3 +73,6 @@ export * from './components/sticky-footer-layout/StickyFooterLayout';
71
73
  export * from './components/forms/typeahead/Typeahead';
72
74
  export * from './hooks/useDeviceSize';
73
75
  export * from './components/theme-button/ThemeButton';
76
+ export * from './components/copy-button/CopyButton';
77
+ export * from './components/divider/Divider';
78
+ export * from './components/grid/Grid';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './components/stack/Stack';
1
2
  export * from './components/button/Button';
2
3
  export * from './components/button-select/ButtonSelect';
3
4
  export * from './components/nav-bar/NavBar';
@@ -8,6 +9,7 @@ export * from './components/icon/Icon';
8
9
  export * from './components/user-display/UserDisplay';
9
10
  export * from './components/tabs/Tabs';
10
11
  export * from './components/headline/Headline';
12
+ export * from './components/headline/CollapsibleHeadline';
11
13
  export * from './components/page-layout/PageLayout';
12
14
  export * from './components/page-layout/components/layout-footer/LayoutFooter';
13
15
  export * from './components/forms/input/Input';
@@ -71,3 +73,6 @@ export * from './components/sticky-footer-layout/StickyFooterLayout';
71
73
  export * from './components/forms/typeahead/Typeahead';
72
74
  export * from './hooks/useDeviceSize';
73
75
  export * from './components/theme-button/ThemeButton';
76
+ export * from './components/copy-button/CopyButton';
77
+ export * from './components/divider/Divider';
78
+ export * from './components/grid/Grid';
@@ -84,6 +84,18 @@
84
84
  gap: var(--spacing-xl);
85
85
  }
86
86
 
87
+ .dbc-gap-2xl {
88
+ gap: var(--spacing-2xl);
89
+ }
90
+
91
+ .dbc-gap-3xl {
92
+ gap: var(--spacing-3xl);
93
+ }
94
+
95
+ .dbc-gap-4xl {
96
+ gap: var(--spacing-4xl);
97
+ }
98
+
87
99
  .dbc-flex-grow {
88
100
  flex-grow: 1;
89
101
  }
@@ -1,4 +1,9 @@
1
1
  /* Margin - all axes */
2
+
3
+ .dbc-m-0 {
4
+ margin: 0;
5
+ }
6
+
2
7
  .dbc-m-xxs {
3
8
  margin: var(--spacing-xxs);
4
9
  }