@dbcdk/react-components 0.0.54 → 0.0.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/card/Card.d.ts +1 -1
- package/dist/components/card/Card.js +0 -2
- package/dist/components/card/Card.module.css +0 -5
- package/dist/components/filter-field/FilterField.js +3 -2
- package/dist/components/forms/typeahead/Typeahead.d.ts +2 -1
- package/dist/components/forms/typeahead/Typeahead.js +2 -2
- package/dist/components/menu/Menu.module.css +14 -6
- package/dist/components/popover/Popover.d.ts +1 -0
- package/dist/components/popover/Popover.js +23 -8
- package/dist/components/popover/Popover.module.css +3 -1
- package/dist/components/toast/Toast.module.css +4 -0
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { JSX, ReactNode } from 'react';
|
|
2
2
|
import type { Severity } from '../../constants/severity.types';
|
|
3
3
|
import { CardMeta, CardMetaRow } from './components/CardMeta';
|
|
4
|
-
type CardVariant = 'default' | 'subtle'
|
|
4
|
+
type CardVariant = 'default' | 'subtle';
|
|
5
5
|
type CardSize = 'sm' | 'md' | 'lg';
|
|
6
6
|
type CardImagePlacement = 'left' | 'right' | 'top';
|
|
7
7
|
export interface CardProps {
|
|
@@ -31,11 +31,6 @@
|
|
|
31
31
|
background-color: var(--card-bg-subtle, var(--color-bg-contextual-subtle));
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
.variantStrong {
|
|
35
|
-
background-color: var(--card-bg-strong, var(--color-bg-surface-strong));
|
|
36
|
-
color: var(--card-fg-on-strong, var(--color-fg-on-strong));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
34
|
/* SIZE VARIANTS (define vars once; inner uses them) */
|
|
40
35
|
.sm {
|
|
41
36
|
--card-pad: var(--spacing-md);
|
|
@@ -71,6 +71,7 @@ function isFilterActive(value) {
|
|
|
71
71
|
}
|
|
72
72
|
export function FilterField({ field, control, operator, value, onChange, operators, options = [], single = true, size = 'md', variant = 'surface', label, placeholder = 'Type value…', disabled, 'data-cy': dataCy, minWidth, width, maxWidth, debounceTime = INPUT_DEBOUNCE_MS, ...inputProps }) {
|
|
73
73
|
var _a, _b, _c, _d, _e, _f;
|
|
74
|
+
const filterFieldRef = useRef(null);
|
|
74
75
|
const ops = useMemo(() => operators !== null && operators !== void 0 ? operators : DEFAULT_TEXT_OPERATORS, [operators]);
|
|
75
76
|
const [selectedOperator, setSelectedOperator] = useState(operator);
|
|
76
77
|
const active = isFilterActive(value);
|
|
@@ -156,7 +157,7 @@ export function FilterField({ field, control, operator, value, onChange, operato
|
|
|
156
157
|
clearDebounce();
|
|
157
158
|
};
|
|
158
159
|
}, []);
|
|
159
|
-
return (_jsxs("div", { ...(dataCy ? { 'data-cy': dataCy } : {}), className: [styles.filterField, styles[size], styles[variant], active ? styles.active : '']
|
|
160
|
+
return (_jsxs("div", { ref: filterFieldRef, ...(dataCy ? { 'data-cy': dataCy } : {}), className: [styles.filterField, styles[size], styles[variant], active ? styles.active : '']
|
|
160
161
|
.filter(Boolean)
|
|
161
162
|
.join(' '), children: [label ? _jsx("span", { className: `${styles.label} ${styles[size]}`, children: label }) : null, _jsx(OperatorDropdown, { value: selectedOperator, onChange: handleOperatorChange, operators: ops, size: size, disabled: disabled }), _jsx("div", { className: [styles.valueWrapper, control === 'input' ? 'dbc-flex dbc-flex-grow' : '']
|
|
162
163
|
.filter(Boolean)
|
|
@@ -171,7 +172,7 @@ export function FilterField({ field, control, operator, value, onChange, operato
|
|
|
171
172
|
pendingValueRef.current = '';
|
|
172
173
|
setLocalValue('');
|
|
173
174
|
emit({ value: '' });
|
|
174
|
-
} })) : (_jsx(Typeahead, { options: options, mode: single ? 'single' : 'multi', selectedValue: single ? ((_f = value) !== null && _f !== void 0 ? _f : null) : Array.isArray(value) ? value : [], onChange: v => emit({ value: v }), minWidth: minWidth, placeholder: placeholder, variant: "embedded", inputProps: {
|
|
175
|
+
} })) : (_jsx(Typeahead, { options: options, mode: single ? 'single' : 'multi', selectedValue: single ? ((_f = value) !== null && _f !== void 0 ? _f : null) : Array.isArray(value) ? value : [], onChange: v => emit({ value: v }), minWidth: minWidth, popoverAnchorRef: filterFieldRef, placeholder: placeholder, variant: "embedded", inputProps: {
|
|
175
176
|
inputSize: size,
|
|
176
177
|
fieldClassName: styles.embeddedInputField,
|
|
177
178
|
inputClassName: styles.embeddedInputElement,
|
|
@@ -30,6 +30,7 @@ interface TypeaheadProps<T> {
|
|
|
30
30
|
autoCorrect?: InputProps['autoCorrect'];
|
|
31
31
|
autoCapitalize?: InputProps['autoCapitalize'];
|
|
32
32
|
spellCheck?: InputProps['spellCheck'];
|
|
33
|
+
popoverAnchorRef?: React.RefObject<HTMLElement | null>;
|
|
33
34
|
}
|
|
34
|
-
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, autoComplete, autoCorrect, autoCapitalize, spellCheck, }: TypeaheadProps<T>): React.ReactElement;
|
|
35
|
+
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, autoComplete, autoCorrect, autoCapitalize, spellCheck, popoverAnchorRef, }: TypeaheadProps<T>): React.ReactElement;
|
|
35
36
|
export {};
|
|
@@ -7,7 +7,7 @@ import { Input } from '../../../components/forms/input/Input';
|
|
|
7
7
|
import { Menu } from '../../../components/menu/Menu';
|
|
8
8
|
import { Popover } from '../../../components/popover/Popover';
|
|
9
9
|
import styles from './Typeahead.module.css';
|
|
10
|
-
export function Typeahead({ options, mode = 'single', multiValueDisplayMode = 'chips', multiSelectedValuesDisplayMode = 'hidden', multiSelectedValueChipContent = 'label', selectedValue = null, onChange, placeholder, variant = 'outlined', disabled = false, fullWidth = false, onClear, emptyMessage = 'Ingen resultater', filterOptions, inputProps, inputSize, width, minWidth, autoComplete, autoCorrect, autoCapitalize, spellCheck, }) {
|
|
10
|
+
export function Typeahead({ options, mode = 'single', multiValueDisplayMode = 'chips', multiSelectedValuesDisplayMode = 'hidden', multiSelectedValueChipContent = 'label', selectedValue = null, onChange, placeholder, variant = 'outlined', disabled = false, fullWidth = false, onClear, emptyMessage = 'Ingen resultater', filterOptions, inputProps, inputSize, width, minWidth, autoComplete, autoCorrect, autoCapitalize, spellCheck, popoverAnchorRef, }) {
|
|
11
11
|
var _a;
|
|
12
12
|
const inputRef = useRef(null);
|
|
13
13
|
const listboxRef = useRef(null);
|
|
@@ -270,7 +270,7 @@ export function Typeahead({ options, mode = 'single', multiValueDisplayMode = 'c
|
|
|
270
270
|
? 8
|
|
271
271
|
: 0,
|
|
272
272
|
width: fullWidth ? '100%' : undefined,
|
|
273
|
-
}, children: [_jsx(Popover, { open: open, minWidth: minWidth, onOpenChange: nextOpen => {
|
|
273
|
+
}, children: [_jsx(Popover, { open: open, minWidth: minWidth, anchorRef: popoverAnchorRef, onOpenChange: nextOpen => {
|
|
274
274
|
setOpen(nextOpen);
|
|
275
275
|
if (nextOpen) {
|
|
276
276
|
if (mode === 'single' && selectedOption) {
|
|
@@ -95,15 +95,10 @@
|
|
|
95
95
|
cursor: pointer;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
.row + .row .interactive,
|
|
99
|
-
.row + .row > .interactiveChild {
|
|
100
|
-
box-shadow: inset 0 1px 0 var(--color-border-subtle);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
98
|
/* Hover: support both cases (interactive element, or wrapper child) */
|
|
104
99
|
.interactive:hover:not(.selected),
|
|
105
100
|
.row:hover > .interactiveChild:not(.selected) {
|
|
106
|
-
background-color: var(--color-bg-hover
|
|
101
|
+
background-color: var(--color-bg-toolbar-hover);
|
|
107
102
|
}
|
|
108
103
|
|
|
109
104
|
/* Focus ring: support both cases */
|
|
@@ -134,6 +129,19 @@
|
|
|
134
129
|
color: var(--color-fg-default);
|
|
135
130
|
}
|
|
136
131
|
|
|
132
|
+
.selected:hover,
|
|
133
|
+
.interactive.selected:hover,
|
|
134
|
+
.interactive[aria-selected='true']:hover,
|
|
135
|
+
.row:hover > .interactiveChild.selected,
|
|
136
|
+
.row:hover > .interactiveChild[aria-selected='true'],
|
|
137
|
+
.active.selected,
|
|
138
|
+
.interactive.active.selected,
|
|
139
|
+
.interactive.active[aria-selected='true'],
|
|
140
|
+
.row > .interactiveChild.active.selected,
|
|
141
|
+
.row > .interactiveChild.active[aria-selected='true'] {
|
|
142
|
+
background-color: var(--color-bg-selected-hover);
|
|
143
|
+
}
|
|
144
|
+
|
|
137
145
|
/* Checked (legacy support; kept in case any interactive element still uses aria-checked) */
|
|
138
146
|
.interactive[aria-checked='true'],
|
|
139
147
|
.row > .interactiveChild[aria-checked='true'] {
|
|
@@ -37,7 +37,7 @@ function parseMinWidthPx(minWidth, elForEm) {
|
|
|
37
37
|
}
|
|
38
38
|
return 0;
|
|
39
39
|
}
|
|
40
|
-
export const Popover = forwardRef(function Popover({ trigger: Trigger, children, open, defaultOpen = false, onOpenChange, contentId, minWidth = '200px', matchTriggerWidth = true, viewportPadding = 8, edgeBuffer = 100, dataCy, fullWidth = false, autoFocusContent = false, returnFocus = true, }, ref) {
|
|
40
|
+
export const Popover = forwardRef(function Popover({ trigger: Trigger, children, open, defaultOpen = false, onOpenChange, contentId, minWidth = '200px', matchTriggerWidth = true, viewportPadding = 8, edgeBuffer = 100, dataCy, fullWidth = false, autoFocusContent = false, returnFocus = true, anchorRef, }, ref) {
|
|
41
41
|
const internalId = useId();
|
|
42
42
|
const resolvedContentId = contentId !== null && contentId !== void 0 ? contentId : `popover-${internalId}`;
|
|
43
43
|
const isControlled = open !== undefined;
|
|
@@ -66,7 +66,9 @@ export const Popover = forwardRef(function Popover({ trigger: Trigger, children,
|
|
|
66
66
|
setOpen(false);
|
|
67
67
|
}, [setOpen]);
|
|
68
68
|
const togglePopover = useCallback((e) => {
|
|
69
|
-
|
|
69
|
+
var _a, _b;
|
|
70
|
+
triggerElRef.current =
|
|
71
|
+
(_b = (_a = anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current) !== null && _a !== void 0 ? _a : containerRef.current) !== null && _b !== void 0 ? _b : e.currentTarget;
|
|
70
72
|
if (isOpen)
|
|
71
73
|
closePopover('trigger');
|
|
72
74
|
else
|
|
@@ -78,19 +80,22 @@ export const Popover = forwardRef(function Popover({ trigger: Trigger, children,
|
|
|
78
80
|
isOpen: () => isOpen,
|
|
79
81
|
}), [closePopover, openPopover, isOpen]);
|
|
80
82
|
const computeAndSetPosition = useCallback(() => {
|
|
81
|
-
var _a;
|
|
83
|
+
var _a, _b;
|
|
82
84
|
const content = contentRef.current;
|
|
83
85
|
if (!content)
|
|
84
86
|
return;
|
|
85
|
-
const triggerEl = (_a =
|
|
87
|
+
const triggerEl = (_b = (_a = anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current) !== null && _a !== void 0 ? _a : triggerElRef.current) !== null && _b !== void 0 ? _b : containerRef.current;
|
|
86
88
|
if (!triggerEl)
|
|
87
89
|
return;
|
|
88
90
|
const triggerRect = triggerEl.getBoundingClientRect();
|
|
91
|
+
const overlayWidthBuffer = 8;
|
|
89
92
|
// Only compute a forced width when requested.
|
|
90
93
|
let forcedWidthPx = null;
|
|
91
94
|
if (matchTriggerWidth) {
|
|
92
95
|
const minWidthPx = parseMinWidthPx(minWidth, triggerEl);
|
|
93
|
-
|
|
96
|
+
// Make the overlay slightly wider than the trigger so it reads as a
|
|
97
|
+
// floating layer instead of blending into adjacent form fields.
|
|
98
|
+
forcedWidthPx = Math.max(triggerRect.width + overlayWidthBuffer, minWidthPx || 0);
|
|
94
99
|
setTriggerWidth(forcedWidthPx);
|
|
95
100
|
}
|
|
96
101
|
else {
|
|
@@ -154,15 +159,16 @@ export const Popover = forwardRef(function Popover({ trigger: Trigger, children,
|
|
|
154
159
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
155
160
|
}, [isOpen]);
|
|
156
161
|
useEffect(() => {
|
|
157
|
-
var _a;
|
|
162
|
+
var _a, _b, _c;
|
|
158
163
|
if (!isOpen)
|
|
159
164
|
return;
|
|
160
165
|
const content = contentRef.current;
|
|
161
166
|
if (!content)
|
|
162
167
|
return;
|
|
168
|
+
const triggerEl = (_b = (_a = anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current) !== null && _a !== void 0 ? _a : triggerElRef.current) !== null && _b !== void 0 ? _b : containerRef.current;
|
|
163
169
|
if (autoFocusContent) {
|
|
164
170
|
const focusables = getFocusable(content);
|
|
165
|
-
(
|
|
171
|
+
(_c = focusables[0]) === null || _c === void 0 ? void 0 : _c.focus();
|
|
166
172
|
}
|
|
167
173
|
const handlePointerDownCapture = (e) => {
|
|
168
174
|
const container = containerRef.current;
|
|
@@ -179,17 +185,26 @@ export const Popover = forwardRef(function Popover({ trigger: Trigger, children,
|
|
|
179
185
|
closePopover('escape');
|
|
180
186
|
};
|
|
181
187
|
const handleReposition = () => computeAndSetPosition();
|
|
188
|
+
const resizeObserver = typeof ResizeObserver !== 'undefined'
|
|
189
|
+
? new ResizeObserver(() => {
|
|
190
|
+
handleReposition();
|
|
191
|
+
})
|
|
192
|
+
: null;
|
|
182
193
|
document.addEventListener('pointerdown', handlePointerDownCapture, true);
|
|
183
194
|
document.addEventListener('keydown', handleEscape, true);
|
|
184
195
|
window.addEventListener('resize', handleReposition);
|
|
185
196
|
window.addEventListener('scroll', handleReposition, true);
|
|
197
|
+
resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.observe(content);
|
|
198
|
+
if (triggerEl)
|
|
199
|
+
resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.observe(triggerEl);
|
|
186
200
|
return () => {
|
|
187
201
|
document.removeEventListener('pointerdown', handlePointerDownCapture, true);
|
|
188
202
|
document.removeEventListener('keydown', handleEscape, true);
|
|
189
203
|
window.removeEventListener('resize', handleReposition);
|
|
190
204
|
window.removeEventListener('scroll', handleReposition, true);
|
|
205
|
+
resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect();
|
|
191
206
|
};
|
|
192
|
-
}, [isOpen, closePopover, computeAndSetPosition, autoFocusContent]);
|
|
207
|
+
}, [isOpen, closePopover, computeAndSetPosition, autoFocusContent, anchorRef]);
|
|
193
208
|
useEffect(() => {
|
|
194
209
|
var _a, _b;
|
|
195
210
|
if (isOpen)
|