@dbcdk/react-components 0.0.88 → 0.0.89
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/accordion/Accordion.d.ts +1 -0
- package/dist/components/accordion/components/AccordionRow.js +1 -1
- package/dist/components/button/Button.js +8 -1
- package/dist/components/button/Button.module.css +2 -1
- package/dist/components/card/Card.d.ts +1 -5
- package/dist/components/card/Card.js +29 -4
- package/dist/components/card/Card.module.css +85 -98
- package/dist/components/card-container/CardContainer.d.ts +2 -1
- package/dist/components/card-container/CardContainer.js +2 -2
- package/dist/components/card-container/CardContainer.module.css +10 -9
- package/dist/components/clear-button/ClearButton.d.ts +2 -1
- package/dist/components/clear-button/ClearButton.js +6 -2
- package/dist/components/clear-button/ClearButton.module.css +6 -0
- package/dist/components/divider/Divider.d.ts +5 -0
- package/dist/components/divider/Divider.js +12 -0
- package/dist/components/forms/input/Input.d.ts +2 -1
- package/dist/components/forms/input/Input.js +6 -2
- package/dist/components/forms/input/Input.module.css +32 -0
- package/dist/components/forms/select/Select.d.ts +2 -1
- package/dist/components/forms/select/Select.js +2 -2
- package/dist/components/forms/typeahead/Typeahead.d.ts +2 -1
- package/dist/components/forms/typeahead/Typeahead.js +180 -118
- package/dist/components/forms/typeahead/Typeahead.module.css +4 -0
- package/dist/components/grid/Grid.d.ts +21 -0
- package/dist/components/grid/Grid.js +21 -0
- package/dist/components/grid/Grid.module.css +20 -0
- package/dist/components/headline/Headline.d.ts +3 -3
- package/dist/components/headline/Headline.js +6 -6
- package/dist/components/headline/Headline.module.css +25 -6
- package/dist/components/nav-bar/NavBar.module.css +6 -2
- package/dist/components/overlay/modal/Modal.d.ts +2 -1
- package/dist/components/overlay/modal/Modal.js +5 -3
- package/dist/components/overlay/modal/provider/ModalProvider.js +2 -0
- package/dist/components/overlay/side-panel/SidePanel.d.ts +2 -1
- package/dist/components/overlay/side-panel/SidePanel.js +2 -2
- package/dist/components/page/Page.d.ts +5 -1
- package/dist/components/page/Page.js +6 -2
- package/dist/components/page/Page.module.css +54 -4
- package/dist/components/panel/Panel.d.ts +2 -1
- package/dist/components/panel/Panel.js +2 -2
- package/dist/components/stack/Stack.d.ts +16 -0
- package/dist/components/stack/Stack.js +19 -0
- package/dist/components/state-page/StatePage.d.ts +2 -1
- package/dist/components/state-page/StatePage.js +2 -2
- package/dist/components/table/Table.d.ts +1 -1
- package/dist/components/table/Table.js +22 -4
- package/dist/components/table/Table.module.css +14 -0
- package/dist/components/table/Table.types.d.ts +1 -0
- package/dist/components/tabs/Tabs.d.ts +3 -1
- package/dist/components/tabs/Tabs.js +4 -2
- package/dist/components/tabs/Tabs.module.css +4 -0
- package/dist/components/theme-button/ThemeButton.d.ts +1 -0
- package/dist/components/theme-button/ThemeButton.js +5 -1
- package/dist/components/toast/Toast.d.ts +2 -1
- package/dist/components/toast/Toast.js +2 -2
- package/dist/hooks/useViewportFill.d.ts +2 -6
- package/dist/hooks/useViewportFill.js +29 -24
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/styles/css-helper-classes/flex.css +12 -0
- package/dist/styles/css-helper-classes/spacing.css +5 -0
- package/dist/styles/styles.css +154 -66
- package/dist/styles/themes/dbc/colors.css +10 -0
- package/dist/styles.css +154 -66
- package/package.json +1 -1
|
@@ -49,5 +49,5 @@ export function AccordionRow({ uid, index, item, isOpen, onToggle, shouldAnimate
|
|
|
49
49
|
const buttonId = `${uid}-acc-btn-${index}`;
|
|
50
50
|
const panelId = `${uid}-acc-panel-${index}`;
|
|
51
51
|
const { innerRef, height, onTransitionEnd } = useCollapsibleHeight(isOpen, shouldAnimate);
|
|
52
|
-
return (_jsxs("section", { className: `${styles.item} ${isOpen ? styles.open : ''} ${isDisabled ? styles.disabled : ''}`, children: [_jsx("div", { children: _jsxs("button", { type: "button", id: buttonId, className: styles.trigger, "aria-expanded": isOpen, "aria-controls": panelId, onClick: () => onToggle(index), disabled: isDisabled, children: [_jsxs("span", { className: styles.title, children: [item.headerIcon ? _jsx("span", { className: styles.icon, children: item.headerIcon }) : null, _jsx(Headline, { disableMargin: true, size: 4, weight: 500, severity: item.severity, allowWrap: isOpen, children: item.header }), item.headerAddition] }), _jsx("span", { className: styles.chevron, "aria-hidden": "true", children: _jsx(ChevronDown, {}) })] }) }), _jsx("div", { id: panelId, role: "region", "aria-labelledby": buttonId, className: `${styles.panel} ${shouldAnimate ? styles.animate : styles.noAnimate}`, style: { height }, onTransitionEnd: onTransitionEnd, children: _jsx("div", { ref: innerRef, className: styles.content, children: item.children }) })] }));
|
|
52
|
+
return (_jsxs("section", { className: `${styles.item} ${isOpen ? styles.open : ''} ${isDisabled ? styles.disabled : ''}`, children: [_jsx("div", { children: _jsxs("button", { type: "button", id: buttonId, className: styles.trigger, "aria-expanded": isOpen, "aria-controls": panelId, onClick: () => onToggle(index), disabled: isDisabled, children: [_jsxs("span", { className: styles.title, children: [item.headerIcon ? _jsx("span", { className: styles.icon, children: item.headerIcon }) : null, _jsx(Headline, { disableMargin: true, size: 4, weight: 500, severity: item.severity, subheader: item.subheader, allowWrap: isOpen, children: item.header }), item.headerAddition] }), _jsx("span", { className: styles.chevron, "aria-hidden": "true", children: _jsx(ChevronDown, {}) })] }) }), _jsx("div", { id: panelId, role: "region", "aria-labelledby": buttonId, className: `${styles.panel} ${shouldAnimate ? styles.animate : styles.noAnimate}`, style: { height }, onTransitionEnd: onTransitionEnd, children: _jsx("div", { ref: innerRef, className: styles.content, children: item.children }) })] }));
|
|
53
53
|
}
|
|
@@ -67,7 +67,14 @@ export const Button = React.forwardRef(function Button({ variant = 'outlined', s
|
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
else {
|
|
70
|
-
|
|
70
|
+
const isDisabled = Boolean(buttonProps.disabled);
|
|
71
|
+
buttonEl = (_jsx("button", { className: computedClassName, type: type, ...buttonProps, ...(tooltipEnabled && !isDisabled ? triggerProps : {}), "aria-describedby": describedBy, children: content }));
|
|
72
|
+
if (tooltipEnabled && isDisabled) {
|
|
73
|
+
buttonEl = (_jsx("span", { ref: triggerProps.ref, onPointerEnter: triggerProps.onPointerEnter, onPointerLeave: triggerProps.onPointerLeave, style: {
|
|
74
|
+
display: fullWidth ? 'flex' : 'inline-flex',
|
|
75
|
+
cursor: 'not-allowed',
|
|
76
|
+
}, children: buttonEl }));
|
|
77
|
+
}
|
|
71
78
|
}
|
|
72
79
|
return buttonEl;
|
|
73
80
|
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
display: inline-flex;
|
|
3
3
|
align-items: center;
|
|
4
4
|
justify-content: center;
|
|
5
|
-
gap: var(--spacing-
|
|
5
|
+
gap: var(--spacing-xs);
|
|
6
6
|
|
|
7
7
|
font-family: var(--font-family);
|
|
8
8
|
font-size: var(--font-size-sm);
|
|
@@ -117,6 +117,7 @@
|
|
|
117
117
|
|
|
118
118
|
.button.lg {
|
|
119
119
|
height: var(--component-size-lg);
|
|
120
|
+
font-size: var(--font-size-md);
|
|
120
121
|
min-block-size: var(--component-size-lg);
|
|
121
122
|
padding-inline: var(--spacing-lg);
|
|
122
123
|
}
|
|
@@ -6,6 +6,7 @@ type CardSize = 'sm' | 'md' | 'lg';
|
|
|
6
6
|
type CardImagePlacement = 'left' | 'right' | 'top';
|
|
7
7
|
export interface CardProps {
|
|
8
8
|
title?: string;
|
|
9
|
+
subheader?: ReactNode;
|
|
9
10
|
loading?: boolean;
|
|
10
11
|
variant?: CardVariant;
|
|
11
12
|
size?: CardSize;
|
|
@@ -21,11 +22,6 @@ export interface CardProps {
|
|
|
21
22
|
sectionTitle?: string;
|
|
22
23
|
showSectionDivider?: boolean;
|
|
23
24
|
children?: ReactNode;
|
|
24
|
-
/**
|
|
25
|
-
* Keep current behavior: if provided, Card becomes "linked".
|
|
26
|
-
* NOTE: this assumes your Hyperlink component can render the passed element correctly.
|
|
27
|
-
* If Hyperlink expects an <a>, pass <a href="...">...</a> or whatever your existing pattern is.
|
|
28
|
-
*/
|
|
29
25
|
link?: ReactNode;
|
|
30
26
|
width?: 25 | 33 | 50 | 66 | 75 | 100;
|
|
31
27
|
headlineSize?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
@@ -4,6 +4,27 @@ import { CardMeta, CardMetaRow } from './components/CardMeta';
|
|
|
4
4
|
import { Headline } from '../headline/Headline';
|
|
5
5
|
import { Hyperlink } from '../hyperlink/Hyperlink';
|
|
6
6
|
import { SkeletonLoaderItem } from '../skeleton-loader/skeleton-loader-item/SkeletonLoaderItem';
|
|
7
|
+
/**
|
|
8
|
+
* Fix for flex gap issue:
|
|
9
|
+
* Distributes gap proportionally across cards
|
|
10
|
+
*/
|
|
11
|
+
function getGapShare(width) {
|
|
12
|
+
switch (width) {
|
|
13
|
+
case 25:
|
|
14
|
+
return 'calc(var(--card-container-gap, var(--spacing-md)) * 3 / 4)';
|
|
15
|
+
case 33:
|
|
16
|
+
return 'calc(var(--card-container-gap, var(--spacing-md)) * 2 / 3)';
|
|
17
|
+
case 50:
|
|
18
|
+
return 'calc(var(--card-container-gap, var(--spacing-md)) / 2)';
|
|
19
|
+
case 66:
|
|
20
|
+
return 'calc(var(--card-container-gap, var(--spacing-md)) * 2 / 3)';
|
|
21
|
+
case 75:
|
|
22
|
+
return 'calc(var(--card-container-gap, var(--spacing-md)) * 3 / 4)';
|
|
23
|
+
case 100:
|
|
24
|
+
default:
|
|
25
|
+
return '0px';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
7
28
|
function getInnerPlacementClass(imgPlacement, s) {
|
|
8
29
|
switch (imgPlacement) {
|
|
9
30
|
case 'top':
|
|
@@ -24,8 +45,13 @@ function getVariantClass(variant, s) {
|
|
|
24
45
|
return s.variantDefault;
|
|
25
46
|
}
|
|
26
47
|
}
|
|
27
|
-
function CardImpl({ title, loading = false, variant = 'default', size = 'md', headerMarker = true, headerIcon, headerAddition, severity, image, imgPlacement = 'left', mediaWidth, actions, headerMeta, sectionTitle, showSectionDivider = false, children, link, width, headlineSize = 4, }) {
|
|
28
|
-
const outerStyle = width
|
|
48
|
+
function CardImpl({ title, subheader, loading = false, variant = 'default', size = 'md', headerMarker = true, headerIcon, headerAddition, severity, image, imgPlacement = 'left', mediaWidth, actions, headerMeta, sectionTitle, showSectionDivider = false, children, link, width, headlineSize = 4, }) {
|
|
49
|
+
const outerStyle = width
|
|
50
|
+
? {
|
|
51
|
+
['--width']: `${width}%`,
|
|
52
|
+
['--gap-share']: getGapShare(width),
|
|
53
|
+
}
|
|
54
|
+
: undefined;
|
|
29
55
|
const mediaStyle = mediaWidth
|
|
30
56
|
? { ['--card-media-width']: `${mediaWidth}px` }
|
|
31
57
|
: undefined;
|
|
@@ -35,8 +61,7 @@ function CardImpl({ title, loading = false, variant = 'default', size = 'md', he
|
|
|
35
61
|
const showSection = !loading && (showSectionDivider || !!sectionTitle);
|
|
36
62
|
const showBody = !loading && !!children;
|
|
37
63
|
const showActions = !loading && !!actions;
|
|
38
|
-
const inner = (_jsxs("div", { className: `${styles.inner} ${innerPlacementClass}`, children: [image ? (_jsx("div", { className: styles.media, style: mediaStyle, children: image })) : null, _jsxs("div", { className: styles.content, children: [hasHeader ? (_jsxs("header", { className: styles.header, children: [title ? (_jsx(Headline, { severity: severity, marker: headerMarker, icon: headerIcon, addition: headerAddition, size: headlineSize, weight: 500, disableMargin: true, children: title })) : null, headerMeta ? _jsx("div", { className: styles.headerMeta, children: headerMeta }) : null] })) : null, loading ? (_jsx("div", { className: styles.loadingList, "aria-busy": "true", "aria-live": "polite", children: Array.from({ length: 4 }, (_, index) => (_jsxs("div", { className: styles.loadingRow, children: [_jsx(SkeletonLoaderItem, {}), _jsx(SkeletonLoaderItem, { width: "100%" })] }, index))) })) : null, showSection ? (_jsxs("div", { className: styles.section, children: [showSectionDivider ? _jsx("div", { className: styles.sectionDivider }) : null, sectionTitle ? _jsx("div", { className: styles.sectionTitle, children: sectionTitle }) : null] })) : null, showBody ? _jsx("div", { className: styles.body, children: children }) : null, showActions ? _jsx("div", { className: styles.actions, children: actions }) : null] })] }));
|
|
39
|
-
// keep existing behavior
|
|
64
|
+
const inner = (_jsxs("div", { className: `${styles.inner} ${innerPlacementClass}`, children: [image ? (_jsx("div", { className: styles.media, style: mediaStyle, children: image })) : null, _jsxs("div", { className: styles.content, children: [hasHeader ? (_jsxs("header", { className: styles.header, children: [title ? (_jsx(Headline, { severity: severity, marker: headerMarker, icon: headerIcon, addition: headerAddition, subheader: subheader, size: headlineSize, weight: 500, disableMargin: true, children: title })) : null, headerMeta ? _jsx("div", { className: styles.headerMeta, children: headerMeta }) : null] })) : null, loading ? (_jsx("div", { className: styles.loadingList, "aria-busy": "true", "aria-live": "polite", children: Array.from({ length: 4 }, (_, index) => (_jsxs("div", { className: styles.loadingRow, children: [_jsx(SkeletonLoaderItem, {}), _jsx(SkeletonLoaderItem, { width: "100%" })] }, index))) })) : null, showSection ? (_jsxs("div", { className: styles.section, children: [showSectionDivider ? _jsx("div", { className: styles.sectionDivider }) : null, sectionTitle ? _jsx("div", { className: styles.sectionTitle, children: sectionTitle }) : null] })) : null, showBody ? _jsx("div", { className: styles.body, children: children }) : null, showActions ? _jsx("div", { className: styles.actions, children: actions }) : null] })] }));
|
|
40
65
|
const cardContent = link ? _jsx(Hyperlink, { children: link }) : inner;
|
|
41
66
|
return (_jsx("div", { className: `${styles.outerContainer} ${styles[size]}`, style: outerStyle, children: _jsx("div", { className: `${styles.container} ${variantClass}`, children: cardContent }) }));
|
|
42
67
|
}
|
|
@@ -1,62 +1,53 @@
|
|
|
1
|
-
/* OUTER WRAPPER (optional width control) */
|
|
2
1
|
.outerContainer {
|
|
3
|
-
|
|
2
|
+
--width: 100%;
|
|
3
|
+
--gap-share: 0px;
|
|
4
|
+
|
|
5
|
+
flex: 0 1 calc(var(--width) - var(--gap-share));
|
|
6
|
+
min-width: 0;
|
|
7
|
+
box-sizing: border-box;
|
|
4
8
|
}
|
|
5
9
|
|
|
6
|
-
/*
|
|
10
|
+
/* Card surface */
|
|
7
11
|
.container {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
background-color: var(--card-bg-default, var(--color-bg-surface));
|
|
12
|
-
border-radius: var(--border-radius-md);
|
|
13
|
-
border: var(--border-width-thin) solid var(--color-border-subtle);
|
|
14
|
-
box-shadow: var(--shadow-xs);
|
|
15
|
-
transition:
|
|
16
|
-
color var(--transition-fast) var(--ease-standard),
|
|
17
|
-
box-shadow var(--transition-fast) var(--ease-standard),
|
|
18
|
-
transform var(--transition-fast) var(--ease-standard);
|
|
19
|
-
}
|
|
12
|
+
height: 100%;
|
|
13
|
+
border-radius: var(--border-radius-sm);
|
|
14
|
+
box-sizing: border-box;
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
/* ✅ Restore border */
|
|
17
|
+
border: 1px solid var(--color-border-subtle);
|
|
18
|
+
|
|
19
|
+
/* Optional: ensure background sits under border */
|
|
20
|
+
background-clip: padding-box;
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
/*
|
|
23
|
+
/* Variants */
|
|
26
24
|
.variantDefault {
|
|
27
|
-
background-color: var(--card-bg-default, var(--color-bg-surface));
|
|
25
|
+
background-color: var(--card-bg-default, var(--color-bg-surface, var(--color-bg-surface-subtle)));
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
.variantSubtle {
|
|
31
|
-
background-color: var(--card-bg-subtle, var(--color-bg-
|
|
29
|
+
background-color: var(--card-bg-subtle, var(--color-bg-surface-subtle, var(--color-bg-surface)));
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
/*
|
|
35
|
-
.sm {
|
|
36
|
-
|
|
37
|
-
--card-gap: var(--spacing-md);
|
|
32
|
+
/* Sizes */
|
|
33
|
+
.sm .container {
|
|
34
|
+
padding: var(--spacing-md);
|
|
38
35
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
|
|
37
|
+
.md .container {
|
|
38
|
+
padding: var(--spacing-lg);
|
|
42
39
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
|
|
41
|
+
.lg .container {
|
|
42
|
+
padding: var(--spacing-xl);
|
|
46
43
|
}
|
|
47
44
|
|
|
48
|
-
/*
|
|
45
|
+
/* Layout */
|
|
49
46
|
.inner {
|
|
50
|
-
margin-inline: auto;
|
|
51
47
|
display: flex;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/* Media placement */
|
|
58
|
-
.innerImgTop {
|
|
59
|
-
flex-direction: column;
|
|
48
|
+
gap: var(--spacing-lg);
|
|
49
|
+
height: 100%;
|
|
50
|
+
min-width: 0;
|
|
60
51
|
}
|
|
61
52
|
|
|
62
53
|
.innerImgLeft {
|
|
@@ -67,101 +58,97 @@
|
|
|
67
58
|
flex-direction: row-reverse;
|
|
68
59
|
}
|
|
69
60
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
flex: 0 0 auto;
|
|
73
|
-
display: flex;
|
|
74
|
-
align-items: flex-start;
|
|
75
|
-
justify-content: center;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.innerImgLeft .media,
|
|
79
|
-
.innerImgRight .media {
|
|
80
|
-
inline-size: var(--card-media-width, 56px);
|
|
81
|
-
max-inline-size: 25%;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.innerImgTop .media {
|
|
85
|
-
inline-size: 100%;
|
|
86
|
-
max-inline-size: 100%;
|
|
61
|
+
.innerImgTop {
|
|
62
|
+
flex-direction: column;
|
|
87
63
|
}
|
|
88
64
|
|
|
89
|
-
.media
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
.media svg {
|
|
93
|
-
display: block;
|
|
94
|
-
inline-size: 100%;
|
|
95
|
-
block-size: auto;
|
|
65
|
+
.media {
|
|
66
|
+
flex: 0 0 var(--card-media-width, auto);
|
|
67
|
+
min-width: 0;
|
|
96
68
|
}
|
|
97
69
|
|
|
98
|
-
/* CONTENT */
|
|
99
70
|
.content {
|
|
100
|
-
flex: 1 1 auto;
|
|
101
|
-
min-inline-size: 0;
|
|
102
71
|
display: flex;
|
|
72
|
+
flex: 1 1 auto;
|
|
103
73
|
flex-direction: column;
|
|
104
74
|
gap: var(--spacing-md);
|
|
75
|
+
min-width: 0;
|
|
105
76
|
}
|
|
106
77
|
|
|
107
|
-
/*
|
|
78
|
+
/* Header */
|
|
108
79
|
.header {
|
|
109
80
|
display: flex;
|
|
110
81
|
align-items: flex-start;
|
|
111
82
|
justify-content: space-between;
|
|
112
|
-
gap: var(--spacing-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
.header > :first-child {
|
|
116
|
-
flex: 1 1 auto;
|
|
117
|
-
min-inline-size: 0;
|
|
83
|
+
gap: var(--spacing-md);
|
|
84
|
+
min-width: 0;
|
|
118
85
|
}
|
|
119
86
|
|
|
120
87
|
.headerMeta {
|
|
121
|
-
|
|
122
|
-
align-items: center;
|
|
123
|
-
gap: var(--spacing-xs);
|
|
88
|
+
flex: 0 0 auto;
|
|
124
89
|
}
|
|
125
90
|
|
|
126
|
-
/*
|
|
127
|
-
.
|
|
128
|
-
|
|
129
|
-
gap: var(--spacing-sm);
|
|
91
|
+
/* Body */
|
|
92
|
+
.body {
|
|
93
|
+
min-width: 0;
|
|
130
94
|
}
|
|
131
95
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
96
|
+
/* Actions */
|
|
97
|
+
.actions {
|
|
98
|
+
display: flex;
|
|
99
|
+
flex-wrap: wrap;
|
|
135
100
|
gap: var(--spacing-sm);
|
|
136
|
-
|
|
101
|
+
margin-top: auto;
|
|
137
102
|
}
|
|
138
103
|
|
|
139
|
-
/*
|
|
104
|
+
/* Section */
|
|
140
105
|
.section {
|
|
141
106
|
display: flex;
|
|
142
107
|
flex-direction: column;
|
|
143
|
-
gap: var(--spacing-
|
|
108
|
+
gap: var(--spacing-sm);
|
|
144
109
|
}
|
|
145
110
|
|
|
146
111
|
.sectionDivider {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
background: var(--color-border-subtle);
|
|
112
|
+
width: 100%;
|
|
113
|
+
height: 1px;
|
|
114
|
+
background-color: var(--color-border-subtle);
|
|
150
115
|
}
|
|
151
116
|
|
|
152
117
|
.sectionTitle {
|
|
153
|
-
font-weight:
|
|
118
|
+
font-weight: 500;
|
|
154
119
|
}
|
|
155
120
|
|
|
156
|
-
/*
|
|
157
|
-
.
|
|
158
|
-
|
|
121
|
+
/* Loading */
|
|
122
|
+
.loadingList {
|
|
123
|
+
display: flex;
|
|
124
|
+
flex-direction: column;
|
|
125
|
+
gap: var(--spacing-md);
|
|
159
126
|
}
|
|
160
127
|
|
|
161
|
-
|
|
162
|
-
.actions {
|
|
163
|
-
margin-top: auto;
|
|
128
|
+
.loadingRow {
|
|
164
129
|
display: flex;
|
|
165
|
-
|
|
130
|
+
flex-direction: column;
|
|
166
131
|
gap: var(--spacing-sm);
|
|
167
132
|
}
|
|
133
|
+
|
|
134
|
+
/* Responsive */
|
|
135
|
+
@media screen and (max-width: 767px) {
|
|
136
|
+
.outerContainer {
|
|
137
|
+
--width: 100%;
|
|
138
|
+
--gap-share: 0px;
|
|
139
|
+
|
|
140
|
+
flex-basis: 100%;
|
|
141
|
+
max-width: 100%;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.inner,
|
|
145
|
+
.innerImgLeft,
|
|
146
|
+
.innerImgRight,
|
|
147
|
+
.innerImgTop {
|
|
148
|
+
flex-direction: column;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.header {
|
|
152
|
+
flex-direction: column;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -2,10 +2,11 @@ import type { JSX, ReactNode } from 'react';
|
|
|
2
2
|
import { Severity } from '../../constants/severity.types';
|
|
3
3
|
interface CardContainerProps {
|
|
4
4
|
headline?: string;
|
|
5
|
+
subheader?: ReactNode;
|
|
5
6
|
children?: ReactNode[];
|
|
6
7
|
expand?: boolean;
|
|
7
8
|
severity?: Severity;
|
|
8
9
|
displayHeaderMarker?: boolean;
|
|
9
10
|
}
|
|
10
|
-
export declare function CardContainer({ children, headline, expand, severity, displayHeaderMarker, }: CardContainerProps): JSX.Element;
|
|
11
|
+
export declare function CardContainer({ children, headline, subheader, expand, severity, displayHeaderMarker, }: CardContainerProps): JSX.Element;
|
|
11
12
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Headline } from '../../components/headline/Headline';
|
|
3
3
|
import styles from './CardContainer.module.css';
|
|
4
|
-
export function CardContainer({ children, headline, expand, severity, displayHeaderMarker, }) {
|
|
5
|
-
return (_jsxs("div", { className: styles.wrapper, children: [headline && (_jsx(Headline, { marker: displayHeaderMarker, severity: severity, disableMargin: true, children: headline })), _jsx("div", { className: styles.container, style: { ['--expand']: expand ? '1' : '0' }, children: children })] }));
|
|
4
|
+
export function CardContainer({ children, headline, subheader, expand, severity, displayHeaderMarker, }) {
|
|
5
|
+
return (_jsxs("div", { className: styles.wrapper, children: [headline && (_jsx(Headline, { marker: displayHeaderMarker, severity: severity, disableMargin: true, subheader: subheader, children: headline })), _jsx("div", { className: styles.container, style: { ['--expand']: expand ? '1' : '0' }, children: children })] }));
|
|
6
6
|
}
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
display: flex;
|
|
9
9
|
flex-wrap: wrap;
|
|
10
10
|
gap: var(--spacing-md);
|
|
11
|
+
--card-container-gap: var(--spacing-md);
|
|
11
12
|
border-radius: var(--border-radius-sm);
|
|
12
|
-
--width: 100%;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
.container.default {
|
|
@@ -47,14 +47,15 @@
|
|
|
47
47
|
padding: var(--spacing-lg);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
@media screen and (min-width: 768px) {
|
|
51
|
-
.container {
|
|
52
|
-
--width: 33.333%;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
50
|
.container > * {
|
|
57
|
-
|
|
58
|
-
flex-shrink: 1;
|
|
51
|
+
min-width: 0;
|
|
59
52
|
box-sizing: border-box;
|
|
60
53
|
}
|
|
54
|
+
|
|
55
|
+
/* Mobile: stack */
|
|
56
|
+
@media screen and (max-width: 767px) {
|
|
57
|
+
.container > * {
|
|
58
|
+
flex-basis: 100% !important;
|
|
59
|
+
max-width: 100%;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import * as React from 'react';
|
|
2
3
|
interface ClearButtonProps {
|
|
3
|
-
onClick
|
|
4
|
+
onClick?: (event?: React.MouseEvent | React.KeyboardEvent) => void;
|
|
4
5
|
absolute?: boolean;
|
|
5
6
|
}
|
|
6
7
|
export declare function ClearButton({ onClick, absolute }: ClearButtonProps): ReactNode;
|
|
@@ -2,8 +2,12 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { X } from 'lucide-react';
|
|
3
3
|
import styles from './ClearButton.module.css';
|
|
4
4
|
export function ClearButton({ onClick, absolute }) {
|
|
5
|
-
return (_jsx("span", { className: `${styles.clearButton} ${absolute ? styles.absolute : ''}`, children: _jsx("
|
|
5
|
+
return (_jsx("span", { className: `${styles.clearButton} ${absolute ? styles.absolute : ''}`, children: _jsx("button", { className: styles.button, type: "button", "data-input-role": "clear", onMouseDown: e => {
|
|
6
|
+
e.preventDefault();
|
|
6
7
|
e.stopPropagation();
|
|
7
|
-
|
|
8
|
+
}, onClick: e => {
|
|
9
|
+
e.preventDefault();
|
|
10
|
+
e.stopPropagation();
|
|
11
|
+
onClick === null || onClick === void 0 ? void 0 : onClick(e);
|
|
8
12
|
}, children: _jsx(X, { size: 16 }) }) }));
|
|
9
13
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
.clearButton .button {
|
|
2
|
+
appearance: none;
|
|
2
3
|
display: flex;
|
|
3
4
|
align-items: center;
|
|
4
5
|
justify-content: center;
|
|
6
|
+
margin: 0;
|
|
7
|
+
border: 0;
|
|
8
|
+
background: transparent;
|
|
5
9
|
color: var(--color-fg-subtle);
|
|
10
|
+
font: inherit;
|
|
11
|
+
line-height: 0;
|
|
6
12
|
padding: var(--spacing-xxs);
|
|
7
13
|
cursor: pointer;
|
|
8
14
|
border-radius: 100%;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const spacingMap = {
|
|
3
|
+
sm: 'var(--spacing-sm)',
|
|
4
|
+
md: 'var(--spacing-md)',
|
|
5
|
+
lg: 'var(--spacing-lg)',
|
|
6
|
+
};
|
|
7
|
+
export const Divider = ({ spacing = 'md' }) => {
|
|
8
|
+
return (_jsx("div", { style: {
|
|
9
|
+
borderTop: '1px solid var(--color-border-subtle)',
|
|
10
|
+
marginBlock: spacingMap[spacing],
|
|
11
|
+
} }));
|
|
12
|
+
};
|
|
@@ -10,10 +10,11 @@ export type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size
|
|
|
10
10
|
maxWidth?: string | number;
|
|
11
11
|
inputSize?: Exclude<Size, 'xl'>;
|
|
12
12
|
variant?: InputVariant;
|
|
13
|
-
onClear?: () => void;
|
|
13
|
+
onClear?: (event?: React.MouseEvent | React.KeyboardEvent) => void;
|
|
14
14
|
onButtonClick?: () => void;
|
|
15
15
|
buttonLabel?: string;
|
|
16
16
|
buttonIcon?: React.ReactNode;
|
|
17
|
+
trailingLabel?: string;
|
|
17
18
|
tooltip?: React.ReactNode;
|
|
18
19
|
tooltipPlacement?: 'top' | 'right' | 'bottom' | 'left';
|
|
19
20
|
tooltipOpenOnFocus?: boolean;
|
|
@@ -18,7 +18,7 @@ function mergeRefs(...refs) {
|
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
-
export const Input = forwardRef(function Input({ label, error, helpText, orientation = 'vertical', labelWidth = '160px', fullWidth = false, required, tooltip, tooltipPlacement = 'right', modified = false, icon, autoFocus, minWidth, width, maxWidth, inputSize = 'md', variant = 'outlined', onClear, onButtonClick, buttonLabel, buttonIcon, id, tooltipOpenOnFocus = true, style, className, fieldClassName, inputClassName, startAdornment, endAdornment, ...inputProps }, ref) {
|
|
21
|
+
export const Input = forwardRef(function Input({ label, error, helpText, orientation = 'vertical', labelWidth = '160px', fullWidth = false, required, tooltip, tooltipPlacement = 'right', modified = false, icon, autoFocus, minWidth, width, maxWidth, inputSize = 'md', variant = 'outlined', onClear, onButtonClick, buttonLabel, buttonIcon, trailingLabel, id, tooltipOpenOnFocus = true, style, className, fieldClassName, inputClassName, startAdornment, endAdornment, ...inputProps }, ref) {
|
|
22
22
|
const inputRef = useRef(null);
|
|
23
23
|
const reactId = useId();
|
|
24
24
|
const inputId = id !== null && id !== void 0 ? id : `input-${reactId}`;
|
|
@@ -28,6 +28,7 @@ export const Input = forwardRef(function Input({ label, error, helpText, orienta
|
|
|
28
28
|
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
29
29
|
}, [autoFocus]);
|
|
30
30
|
const hasButton = Boolean(onButtonClick || buttonLabel || buttonIcon);
|
|
31
|
+
const hasTrailingLabel = Boolean(trailingLabel);
|
|
31
32
|
const hasValue = Boolean(inputProps.value);
|
|
32
33
|
const hasVisibleClear = Boolean(onClear && hasValue);
|
|
33
34
|
const hasEndAdornment = Boolean(endAdornment);
|
|
@@ -54,6 +55,7 @@ export const Input = forwardRef(function Input({ label, error, helpText, orienta
|
|
|
54
55
|
onClear ? styles.withClear : '',
|
|
55
56
|
hasInlineClear ? styles.withInlineClear : '',
|
|
56
57
|
hasButton ? styles.withButton : '',
|
|
58
|
+
hasTrailingLabel ? styles.withTrailingLabel : '',
|
|
57
59
|
className !== null && className !== void 0 ? className : '',
|
|
58
60
|
]
|
|
59
61
|
.filter(Boolean)
|
|
@@ -68,6 +70,8 @@ export const Input = forwardRef(function Input({ label, error, helpText, orienta
|
|
|
68
70
|
.filter(Boolean)
|
|
69
71
|
.join(' '), "data-forminput": "field", "data-modified": modified ? 'true' : undefined, "aria-disabled": inputProps.disabled ? 'true' : undefined, ...(tooltip ? triggerProps : {}), children: [icon && (_jsx("span", { className: styles.icon, "data-input-role": "icon", children: icon })), startAdornment && (_jsx("span", { className: styles.startAdornment, "data-input-role": "start-adornment", children: startAdornment })), _jsx("input", { ...inputProps, id: inputId, ref: mergeRefs(inputRef, ref), className: [styles.input, inputSize ? styles[inputSize] : '', inputClassName !== null && inputClassName !== void 0 ? inputClassName : '']
|
|
70
72
|
.filter(Boolean)
|
|
71
|
-
.join(' ') }), (reservesInlineClearSlot || hasEndAdornment) && (_jsxs("span", { className: styles.endAdornment, "data-input-role": "end-adornment", children: [reservesInlineClearSlot ? (_jsx("span", { className: styles.clearSlot, "aria-hidden": hasVisibleClear ? undefined : 'true', children: hasVisibleClear && onClear ? _jsx(ClearButton, { onClick: onClear }) : null })) : null, endAdornment] })), hasVisibleClear && !hasEndAdornment && onClear ? (_jsx(ClearButton, { onClick: onClear, absolute: true })) : null] }),
|
|
73
|
+
.join(' ') }), (reservesInlineClearSlot || hasEndAdornment) && (_jsxs("span", { className: styles.endAdornment, "data-input-role": "end-adornment", children: [reservesInlineClearSlot ? (_jsx("span", { className: styles.clearSlot, "aria-hidden": hasVisibleClear ? undefined : 'true', children: hasVisibleClear && onClear ? _jsx(ClearButton, { onClick: onClear }) : null })) : null, endAdornment] })), hasVisibleClear && !hasEndAdornment && onClear ? (_jsx(ClearButton, { onClick: onClear, absolute: true })) : null] }), hasTrailingLabel && (_jsx("span", { className: [styles.trailingLabel, inputSize ? styles[inputSize] : '']
|
|
74
|
+
.filter(Boolean)
|
|
75
|
+
.join(' '), children: trailingLabel })), hasButton && (_jsxs(Button, { onClick: onButtonClick, className: styles.trailingButton, type: "button", variant: trailingButtonVariant, size: inputSize, children: [buttonIcon !== null && buttonIcon !== void 0 ? buttonIcon : null, buttonLabel !== null && buttonLabel !== void 0 ? buttonLabel : null] }))] }) }));
|
|
72
76
|
});
|
|
73
77
|
Input.displayName = 'Input';
|
|
@@ -375,6 +375,38 @@
|
|
|
375
375
|
block-size: var(--icon-size-md);
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
+
/* Trailing label (unit, currency, etc.) */
|
|
379
|
+
.withTrailingLabel .field {
|
|
380
|
+
border-top-right-radius: 0;
|
|
381
|
+
border-bottom-right-radius: 0;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.trailingLabel {
|
|
385
|
+
display: flex;
|
|
386
|
+
align-items: center;
|
|
387
|
+
flex: 0 0 auto;
|
|
388
|
+
padding-inline: var(--spacing-sm);
|
|
389
|
+
font-family: var(--font-family);
|
|
390
|
+
font-size: var(--font-size-sm);
|
|
391
|
+
color: var(--color-fg-muted);
|
|
392
|
+
background: var(--color-bg-toolbar);
|
|
393
|
+
border: var(--border-width-thin) solid var(--color-border-default);
|
|
394
|
+
margin-left: calc(-1 * var(--border-width-thin));
|
|
395
|
+
border-top-right-radius: var(--border-radius-default);
|
|
396
|
+
border-bottom-right-radius: var(--border-radius-default);
|
|
397
|
+
white-space: nowrap;
|
|
398
|
+
user-select: none;
|
|
399
|
+
box-sizing: border-box;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.withTrailingLabel:has(.standalone) .trailingLabel {
|
|
403
|
+
border-top-right-radius: var(--border-radius-rounded);
|
|
404
|
+
border-bottom-right-radius: var(--border-radius-rounded);
|
|
405
|
+
border-color: var(--color-border-subtle);
|
|
406
|
+
background-color: var(--color-bg-surface);
|
|
407
|
+
box-shadow: var(--shadow-xs), var(--shadow-sm);
|
|
408
|
+
}
|
|
409
|
+
|
|
378
410
|
/* Trailing action button (outside field) */
|
|
379
411
|
.trailingButton {
|
|
380
412
|
flex: 0 0 auto;
|
|
@@ -15,8 +15,9 @@ export type SelectProps<T> = Omit<InputContainerProps, 'children' | 'htmlFor' |
|
|
|
15
15
|
datakey?: string;
|
|
16
16
|
dataCy?: string;
|
|
17
17
|
disabled?: boolean;
|
|
18
|
+
minWidth?: string | number;
|
|
18
19
|
tooltip?: React.ReactNode;
|
|
19
20
|
tooltipPlacement?: 'top' | 'right' | 'bottom' | 'left';
|
|
20
21
|
};
|
|
21
|
-
export declare function Select<T extends string | number | Record<string, any>>({ label, error, helpText, orientation, labelWidth, fullWidth, required, tooltip, tooltipPlacement, modified, id, options, selectedValue, onChange, placeholder, size, variant, onClear, datakey, dataCy, disabled, }: SelectProps<T>): React.ReactNode;
|
|
22
|
+
export declare function Select<T extends string | number | Record<string, any>>({ label, error, helpText, orientation, labelWidth, fullWidth, required, tooltip, tooltipPlacement, modified, id, options, selectedValue, onChange, placeholder, size, variant, onClear, datakey, dataCy, disabled, minWidth, }: SelectProps<T>): React.ReactNode;
|
|
22
23
|
export {};
|
|
@@ -9,7 +9,7 @@ import { ClearButton } from '../../clear-button/ClearButton';
|
|
|
9
9
|
import { Menu } from '../../menu/Menu';
|
|
10
10
|
import { Popover } from '../../popover/Popover';
|
|
11
11
|
import { InputContainer } from '../input-container/InputContainer';
|
|
12
|
-
export function Select({ label, error, helpText, orientation = 'vertical', labelWidth = '160px', fullWidth = true, required, tooltip, tooltipPlacement = 'right', modified = false, id, options, selectedValue, onChange, placeholder = 'Vælg', size, variant = 'outlined', onClear, datakey, dataCy, disabled, }) {
|
|
12
|
+
export function Select({ label, error, helpText, orientation = 'vertical', labelWidth = '160px', fullWidth = true, required, tooltip, tooltipPlacement = 'right', modified = false, id, options, selectedValue, onChange, placeholder = 'Vælg', size, variant = 'outlined', onClear, datakey, dataCy, disabled, minWidth, }) {
|
|
13
13
|
const generatedId = useId();
|
|
14
14
|
const controlId = id !== null && id !== void 0 ? id : `select-${generatedId}`;
|
|
15
15
|
const describedById = `${controlId}-desc`;
|
|
@@ -169,7 +169,7 @@ export function Select({ label, error, helpText, orientation = 'vertical', label
|
|
|
169
169
|
returnFocus: true, trigger: (toggle, icon, isOpen) => (_jsx(Button, { disabled: disabled, ...(tooltipEnabled ? triggerProps : {}), id: controlId, "data-cy": dataCy !== null && dataCy !== void 0 ? dataCy : 'select-button', onKeyDown: handleKeyDown, fullWidth: fullWidth, variant: variant, onClick: e => {
|
|
170
170
|
resetActiveToSelected();
|
|
171
171
|
toggle(e);
|
|
172
|
-
}, size: size, type: "button", "data-forminput": true, "aria-haspopup": "listbox", "aria-expanded": !!isOpen, "aria-controls": listboxId, "aria-invalid": Boolean(error) || undefined, "aria-describedby": describedBy, className: modified ? styles.triggerModified : undefined, children: _jsxs("span", { className: "dbc-flex dbc-justify-between dbc-items-center dbc-gap-xxs", style: { width: '100%' }, children: [_jsx("span", { children: selected ? selected.label : _jsx("span", { className: "dbc-muted-text", children: placeholder }) }), _jsxs("span", { className: "dbc-flex dbc-items-center dbc-gap-xxs", children: [onClear && selected && _jsx(ClearButton, { onClick: onClear }), _jsx("span", { style: { color: 'var(--color-fg-subtle)', display: 'inline-flex' }, children: icon })] })] }) })), children: _jsx(Menu, { onKeyDown: handleKeyDown, role: "listbox", children: options.map((opt, index) => {
|
|
172
|
+
}, size: size, style: minWidth != null ? { minWidth } : undefined, type: "button", "data-forminput": true, "aria-haspopup": "listbox", "aria-expanded": !!isOpen, "aria-controls": listboxId, "aria-invalid": Boolean(error) || undefined, "aria-describedby": describedBy, className: modified ? styles.triggerModified : undefined, children: _jsxs("span", { className: "dbc-flex dbc-justify-between dbc-items-center dbc-gap-xxs", style: { width: '100%' }, children: [_jsx("span", { children: selected ? selected.label : _jsx("span", { className: "dbc-muted-text", children: placeholder }) }), _jsxs("span", { className: "dbc-flex dbc-items-center dbc-gap-xxs", children: [onClear && selected && _jsx(ClearButton, { onClick: onClear }), _jsx("span", { style: { color: 'var(--color-fg-subtle)', display: 'inline-flex' }, children: icon })] })] }) })), children: _jsx(Menu, { onKeyDown: handleKeyDown, role: "listbox", children: options.map((opt, index) => {
|
|
173
173
|
const isSelected = typeof opt.value === 'object' && typeof selectedValue === 'object' && datakey
|
|
174
174
|
? (selectedValue === null || selectedValue === void 0 ? void 0 : selectedValue[datakey]) === opt.value[datakey]
|
|
175
175
|
: opt.value === selectedValue;
|
|
@@ -33,6 +33,7 @@ interface TypeaheadProps<T> {
|
|
|
33
33
|
spellCheck?: InputProps['spellCheck'];
|
|
34
34
|
popoverAnchorRef?: React.RefObject<HTMLElement | null>;
|
|
35
35
|
fitContent?: boolean;
|
|
36
|
+
enableHotkey?: boolean;
|
|
36
37
|
}
|
|
37
|
-
export declare function Typeahead<T extends string | number>({ options, mode, multiValueDisplayMode, multiSelectedValuesDisplayMode, multiSelectedValueChipContent, selectedValue, onChange, placeholder, variant, disabled, fullWidth, onClear, emptyMessage, filterOptions, inputProps, inputSize, width, minWidth, popoverWidth, autoComplete, autoCorrect, autoCapitalize, spellCheck, popoverAnchorRef, fitContent, }: TypeaheadProps<T>): React.ReactElement;
|
|
38
|
+
export declare function Typeahead<T extends string | number>({ options, mode, multiValueDisplayMode, multiSelectedValuesDisplayMode, multiSelectedValueChipContent, selectedValue, onChange, placeholder, variant, disabled, fullWidth, onClear, emptyMessage, filterOptions, inputProps, inputSize, width, minWidth, popoverWidth, autoComplete, autoCorrect, autoCapitalize, spellCheck, popoverAnchorRef, fitContent, enableHotkey, }: TypeaheadProps<T>): React.ReactElement;
|
|
38
39
|
export {};
|