@dbcdk/react-components 0.0.10 → 0.0.12

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 (52) hide show
  1. package/dist/components/card/Card.d.ts +21 -3
  2. package/dist/components/card/Card.js +17 -2
  3. package/dist/components/card/Card.module.css +59 -0
  4. package/dist/components/circle/Circle.d.ts +2 -1
  5. package/dist/components/circle/Circle.js +2 -2
  6. package/dist/components/circle/Circle.module.css +6 -2
  7. package/dist/components/code-block/CodeBlock.js +1 -1
  8. package/dist/components/code-block/CodeBlock.module.css +30 -17
  9. package/dist/components/copy-button/CopyButton.d.ts +1 -0
  10. package/dist/components/copy-button/CopyButton.js +10 -2
  11. package/dist/components/filter-field/FilterField.js +16 -11
  12. package/dist/components/filter-field/FilterField.module.css +133 -12
  13. package/dist/components/forms/checkbox/Checkbox.d.ts +2 -2
  14. package/dist/components/forms/checkbox-group/CheckboxGroup.js +1 -1
  15. package/dist/components/forms/checkbox-group/CheckboxGroup.module.css +1 -1
  16. package/dist/components/forms/input/Input.js +1 -1
  17. package/dist/components/forms/input/Input.module.css +1 -0
  18. package/dist/components/forms/input-container/InputContainer.module.css +1 -1
  19. package/dist/components/hyperlink/Hyperlink.d.ts +19 -7
  20. package/dist/components/hyperlink/Hyperlink.js +35 -11
  21. package/dist/components/hyperlink/Hyperlink.module.css +50 -2
  22. package/dist/components/menu/Menu.d.ts +32 -0
  23. package/dist/components/menu/Menu.js +73 -13
  24. package/dist/components/menu/Menu.module.css +72 -4
  25. package/dist/components/overlay/modal/Modal.module.css +2 -2
  26. package/dist/components/overlay/side-panel/SidePanel.js +17 -0
  27. package/dist/components/overlay/side-panel/SidePanel.module.css +0 -2
  28. package/dist/components/overlay/tooltip/useTooltipTrigger.js +4 -2
  29. package/dist/components/popover/Popover.js +1 -1
  30. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.js +22 -18
  31. package/dist/components/sidebar/providers/SidebarProvider.d.ts +4 -1
  32. package/dist/components/sidebar/providers/SidebarProvider.js +66 -18
  33. package/dist/components/split-button/SplitButton.d.ts +1 -1
  34. package/dist/components/split-button/SplitButton.js +3 -1
  35. package/dist/components/split-button/SplitButton.module.css +4 -4
  36. package/dist/components/state-page/StatePage.module.css +1 -1
  37. package/dist/components/table/Table.d.ts +9 -4
  38. package/dist/components/table/Table.js +3 -6
  39. package/dist/components/table/Table.module.css +18 -5
  40. package/dist/components/table/components/table-settings/TableSettings.d.ts +13 -3
  41. package/dist/components/table/components/table-settings/TableSettings.js +55 -4
  42. package/dist/components/table/tanstack.d.ts +12 -1
  43. package/dist/components/table/tanstack.js +75 -23
  44. package/dist/hooks/useTableSettings.d.ts +23 -4
  45. package/dist/hooks/useTableSettings.js +64 -17
  46. package/dist/src/styles/styles.css +38 -22
  47. package/dist/styles/animation.d.ts +5 -0
  48. package/dist/styles/animation.js +5 -0
  49. package/dist/styles/styles.css +38 -22
  50. package/dist/utils/localStorage.utils.d.ts +19 -0
  51. package/dist/utils/localStorage.utils.js +78 -0
  52. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
+ import type { ReactNode, JSX, HTMLAttributes } from 'react';
1
2
  import { JSXElementConstructor, ReactElement } from 'react';
2
- import type { ReactNode, JSX } from 'react';
3
3
  import { Severity } from '../../constants/severity.types';
4
4
  type CardVariant = 'default' | 'subtle' | 'strong';
5
5
  type CardSize = 'sm' | 'md' | 'lg';
6
6
  type CardImagePlacement = 'left' | 'right' | 'top';
7
- interface CardProps {
7
+ export interface CardProps {
8
8
  title?: string;
9
9
  loading?: boolean;
10
10
  variant?: CardVariant;
@@ -23,5 +23,23 @@ interface CardProps {
23
23
  link?: ReactElement<any, string | JSXElementConstructor<any>>;
24
24
  width?: 25 | 33 | 50 | 66 | 75 | 100;
25
25
  }
26
- export declare function Card({ title, loading, variant, size, headerMarker, headerIcon, severity, image, imgPlacement, mediaWidth, actions, headerMeta, sectionTitle, showSectionDivider, children, link, width, }: CardProps): JSX.Element;
26
+ type CardMetaProps = {
27
+ columns?: 1 | 2 | 3;
28
+ className?: string;
29
+ children: ReactNode;
30
+ } & Omit<HTMLAttributes<HTMLDListElement>, 'children'>;
31
+ type CardMetaRowProps = {
32
+ label: ReactNode;
33
+ labelWidth?: string;
34
+ value: ReactNode;
35
+ className?: string;
36
+ nowrapValue?: boolean;
37
+ };
38
+ declare function CardMeta({ columns, className, children, ...rest }: CardMetaProps): JSX.Element;
39
+ declare function CardMetaRow({ label, value, className, nowrapValue, labelWidth, }: CardMetaRowProps): JSX.Element;
40
+ type CardComponent = ((props: CardProps) => JSX.Element) & {
41
+ Meta: typeof CardMeta;
42
+ MetaRow: typeof CardMetaRow;
43
+ };
44
+ export declare const Card: CardComponent;
27
45
  export {};
@@ -4,7 +4,7 @@ import styles from './Card.module.css';
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
- export function Card({ title, loading, variant = 'default', size = 'md', headerMarker = true, headerIcon, severity, image, imgPlacement = 'left', mediaWidth, actions, headerMeta, sectionTitle, showSectionDivider = false, children, link, width, }) {
7
+ function CardImpl({ title, loading, variant = 'default', size = 'md', headerMarker = true, headerIcon, severity, image, imgPlacement = 'left', mediaWidth, actions, headerMeta, sectionTitle, showSectionDivider = false, children, link, width, }) {
8
8
  const outerContainerStyle = width
9
9
  ? { ['--width']: `${width}%` }
10
10
  : undefined;
@@ -17,6 +17,21 @@ export function Card({ title, loading, variant = 'default', size = 'md', headerM
17
17
  ? styles.innerImgRight
18
18
  : styles.innerImgLeft;
19
19
  const inner = (_jsxs("div", { className: `${styles.inner} ${innerPlacementClass}`, children: [image && (_jsx("div", { className: styles.media, style: mediaStyle, children: image })), _jsxs("div", { className: styles.content, children: [(title || headerMeta) && (_jsxs("header", { className: styles.header, children: [title && (_jsx(Headline, { severity: severity, marker: headerMarker, icon: headerIcon, size: 4, weight: 500, disableMargin: true, children: title })), headerMeta && _jsx("div", { className: styles.headerMeta, children: headerMeta })] })), loading && (_jsx("div", { className: styles.loadingList, children: Array.from({ length: 4 }).map((_, index) => (_jsxs("div", { className: styles.loadingRow, children: [_jsx(SkeletonLoaderItem, {}), _jsx(SkeletonLoaderItem, { width: "100%" })] }, index))) })), !loading && (showSectionDivider || sectionTitle) && (_jsxs("div", { className: styles.section, children: [showSectionDivider && _jsx("div", { className: styles.sectionDivider }), sectionTitle && _jsx("div", { className: styles.sectionTitle, children: sectionTitle })] })), !loading && children && _jsx("div", { className: styles.body, children: children }), !loading && actions && _jsx("div", { className: styles.actions, children: actions })] })] }));
20
- const cardWithLink = link ? _jsx(Hyperlink, { component: link }) : inner;
20
+ // keep existing behavior
21
+ const cardWithLink = link ? _jsx(Hyperlink, { children: link }) : inner;
21
22
  return (_jsx("div", { className: `${styles.outerContainer} ${styles[size]}`, style: outerContainerStyle, children: _jsx("div", { className: [styles.container, styles[variant]].filter(Boolean).join(' '), children: cardWithLink }) }));
22
23
  }
24
+ // ---- subcomponents (declared normally) ----
25
+ function CardMeta({ columns = 2, className, children, ...rest }) {
26
+ const colsClass = columns === 1 ? styles.metaCols1 : columns === 2 ? styles.metaCols2 : styles.metaCols3;
27
+ return (_jsx("dl", { ...rest, className: [styles.metaGrid, colsClass, className].filter(Boolean).join(' '), children: children }));
28
+ }
29
+ function CardMetaRow({ label, value, className, nowrapValue, labelWidth, }) {
30
+ return (_jsxs("div", { className: [styles.metaRow, className].filter(Boolean).join(' '), style: { '--label-width': labelWidth }, children: [_jsx("dt", { className: styles.metaLabel, children: label }), _jsx("dd", { className: [styles.metaValue, nowrapValue ? styles.metaNowrap : undefined]
31
+ .filter(Boolean)
32
+ .join(' '), children: value })] }));
33
+ }
34
+ export const Card = Object.assign(CardImpl, {
35
+ Meta: CardMeta,
36
+ MetaRow: CardMetaRow,
37
+ });
@@ -171,3 +171,62 @@
171
171
  justify-content: flex-end; /* right-align buttons */
172
172
  gap: var(--spacing-sm);
173
173
  }
174
+
175
+ /* --- Meta grid primitives (optional) --- */
176
+
177
+ .metaGrid {
178
+ margin: 0;
179
+ display: grid;
180
+ gap: var(--spacing-xs) var(--spacing-lg);
181
+ }
182
+
183
+ .metaCols1 {
184
+ grid-template-columns: 1fr;
185
+ }
186
+
187
+ .metaCols2 {
188
+ grid-template-columns: 1fr;
189
+ }
190
+
191
+ .metaCols3 {
192
+ grid-template-columns: 1fr;
193
+ }
194
+
195
+ @media (min-width: 640px) {
196
+ .metaCols2 {
197
+ grid-template-columns: 1fr 1fr;
198
+ }
199
+ .metaCols3 {
200
+ grid-template-columns: 1fr 1fr 1fr;
201
+ }
202
+ }
203
+
204
+ .metaRow {
205
+ --label-width: 120px;
206
+ display: grid;
207
+ grid-template-columns: var(--label-width, auto) 1fr;
208
+ gap: var(--spacing-xs);
209
+ align-items: baseline;
210
+ min-inline-size: 0;
211
+ }
212
+
213
+ .metaLabel {
214
+ font-size: var(--font-size-xs);
215
+ color: var(--color-fg-subtle);
216
+ letter-spacing: var(--letter-spacing-wide);
217
+ text-transform: uppercase;
218
+ margin: 0;
219
+ }
220
+
221
+ .metaValue {
222
+ margin: 0;
223
+ font-size: var(--font-size-sm);
224
+ color: var(--color-fg-default);
225
+ font-weight: var(--font-weight-medium);
226
+ min-inline-size: 0;
227
+ word-break: break-word;
228
+ }
229
+
230
+ .metaNowrap {
231
+ white-space: nowrap;
232
+ }
@@ -5,8 +5,9 @@ interface CircleProps {
5
5
  severity: Severity;
6
6
  children?: ReactNode;
7
7
  glow?: boolean;
8
+ muted?: boolean;
8
9
  pulse?: boolean;
9
10
  size?: CircleSize;
10
11
  }
11
- export declare function Circle({ severity, children, glow, pulse, size }: CircleProps): JSX.Element;
12
+ export declare function Circle({ severity, children, glow, muted, pulse, size, }: CircleProps): JSX.Element;
12
13
  export {};
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import styles from './Circle.module.css';
3
- export function Circle({ severity, children, glow, pulse, size = 'sm' }) {
4
- return (_jsxs("span", { className: styles.container, children: [_jsx("span", { "data-glow": glow, "data-pulse": pulse, "data-size": size, className: `${styles.circle} ${styles[severity]}` }), children] }));
3
+ export function Circle({ severity, children, glow, muted, pulse, size = 'sm', }) {
4
+ return (_jsxs("span", { className: styles.container, children: [_jsx("span", { "data-glow": glow, "data-pulse": pulse, "data-size": size, "data-muted": muted, className: `${styles.circle} ${styles[severity]}` }), children] }));
5
5
  }
@@ -16,10 +16,10 @@
16
16
  block-size: var(--component-size-sm);
17
17
  border-radius: var(--border-radius-round);
18
18
  flex-shrink: 0;
19
-
20
19
  transition:
21
20
  background-color var(--transition-fast) var(--ease-standard),
22
- box-shadow var(--transition-fast) var(--ease-standard);
21
+ box-shadow var(--transition-fast) var(--ease-standard),
22
+ opacity var(--transition-normal) var(--ease-standard);
23
23
  }
24
24
 
25
25
  /* Density modifier (optional) */
@@ -77,6 +77,10 @@
77
77
  block-size: 18px;
78
78
  }
79
79
 
80
+ .circle[data-muted='true'] {
81
+ opacity: 0.4;
82
+ }
83
+
80
84
  .circle[data-size='lg'] {
81
85
  inline-size: 22px;
82
86
  block-size: 22px;
@@ -2,5 +2,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import styles from './CodeBlock.module.css';
3
3
  import { CopyButton } from '../copy-button/CopyButton';
4
4
  export function CodeBlock({ code, copyButton, size = 'md' }) {
5
- return (_jsxs("pre", { className: `${styles.container} ${styles[size]}`, children: [copyButton && (_jsx("span", { className: styles.copyButton, children: _jsx(CopyButton, { text: code }) })), _jsx("code", { className: styles.code, children: code })] }));
5
+ return (_jsxs("pre", { className: `${styles.container} ${styles[size]}`, tabIndex: 0, children: [copyButton && (_jsx("span", { className: styles.copyButton, children: _jsx(CopyButton, { style: "link", text: code }) })), _jsx("code", { className: styles.code, children: code })] }));
6
6
  }
@@ -1,21 +1,33 @@
1
1
  .container {
2
- background-color: var(--color-bg-contextual);
3
2
  position: relative;
4
- padding: var(--spacing-sm);
5
- border-radius: var(--border-radius-default);
6
- border: var(--border-width-thin) solid var(--color-border-default);
7
3
  margin-block: 0;
8
- font-family: var(--font-family-mono);
9
- white-space: pre-wrap;
10
- overflow-wrap: anywhere;
11
- word-break: break-word;
4
+
5
+ background: var(--color-bg-contextual-subtle);
6
+ border: var(--border-width-thin) solid var(--color-border-default);
7
+ border-radius: var(--border-radius-lg);
8
+ box-shadow: var(--shadow-xs);
9
+
10
+ padding: var(--spacing-sm);
12
11
  padding-inline-end: calc(var(--spacing-sm) + 40px);
12
+
13
+ font-family: var(--font-family-mono);
14
+ line-height: var(--line-height-relaxed);
15
+
16
+ overflow-x: auto;
17
+ overflow-y: hidden;
18
+
19
+ /* Nice: avoids layout shift if/when scrollbars appear (supported in modern browsers) */
20
+ scrollbar-gutter: stable;
21
+ }
22
+
23
+ .container:focus-within {
24
+ border-color: var(--color-border-selected);
25
+ box-shadow: var(--shadow-xs), var(--focus-ring);
13
26
  }
14
27
 
15
28
  .container.sm {
16
29
  padding: var(--spacing-xs);
17
- padding-inline-end: calc(var(--spacing-xxs) + 40px);
18
- min-height: 0;
30
+ padding-inline-end: calc(var(--spacing-xs) + 40px);
19
31
  }
20
32
 
21
33
  .container.sm .code {
@@ -25,6 +37,7 @@
25
37
  .container.md .code {
26
38
  font-size: var(--font-size-sm);
27
39
  }
40
+
28
41
  .container.lg .code {
29
42
  font-size: var(--font-size-base);
30
43
  }
@@ -33,11 +46,15 @@
33
46
  display: block;
34
47
  margin: 0;
35
48
  font-family: var(--font-family-mono);
36
- font-size: var(--font-size-xs);
37
- line-break: anywhere;
38
- word-break: break-all;
49
+ color: var(--color-fg-default);
50
+
51
+ /* ✅ Preserve formatting but avoid ugly breaking */
52
+ white-space: pre-wrap;
53
+ overflow-wrap: anywhere;
54
+ word-break: normal; /* <- not break-all */
39
55
  }
40
56
 
57
+ /* Copy button stays overlayed; does not affect layout */
41
58
  .copyButton {
42
59
  position: absolute;
43
60
  top: var(--spacing-xs);
@@ -54,7 +71,3 @@
54
71
  opacity: 1;
55
72
  pointer-events: auto;
56
73
  }
57
-
58
- .copyButton button {
59
- pointer-events: auto;
60
- }
@@ -5,6 +5,7 @@ interface CopyButtonProps {
5
5
  variant?: ButtonVariant;
6
6
  size?: ButtonSize;
7
7
  children?: ReactNode;
8
+ style?: 'button' | 'link';
8
9
  }
9
10
  export declare function CopyButton(props: CopyButtonProps & ComponentProps<typeof Button>): ReactNode;
10
11
  export {};
@@ -4,8 +4,9 @@ import { Check, Copy } from 'lucide-react';
4
4
  import { useState } from 'react';
5
5
  import styles from './CopyButton.module.css';
6
6
  import { Button } from '../button/Button';
7
+ import { Hyperlink } from '../hyperlink/Hyperlink';
7
8
  export function CopyButton(props) {
8
- var _a;
9
+ var _a, _b;
9
10
  const { text, variant = 'outlined', size = 'sm', children, ...rest } = props;
10
11
  const [copied, setCopied] = useState(false);
11
12
  const handleCopy = async () => {
@@ -18,5 +19,12 @@ export function CopyButton(props) {
18
19
  console.error('Failed to copy: ', err);
19
20
  }
20
21
  };
21
- return (_jsxs(Button, { ...rest, "aria-label": children ? '' : ((_a = rest['aria-label']) !== null && _a !== void 0 ? _a : 'Kopier til udklipsholder'), onClick: handleCopy, variant: variant, size: size, children: [_jsx("span", { className: `${styles.container} ${copied ? styles.copied : ''}`, children: copied ? _jsx(Check, {}) : _jsx(Copy, {}) }), children] }));
22
+ if (props.style === 'link') {
23
+ return (_jsx(Hyperlink, { asChild: true, variant: "secondary", inline: props.variant === 'inline', children: _jsxs("button", { "aria-label": children ? '' : ((_a = rest['aria-label']) !== null && _a !== void 0 ? _a : 'Kopier til udklipsholder'), onClick: e => {
24
+ e.preventDefault();
25
+ e.stopPropagation();
26
+ handleCopy();
27
+ }, className: `${styles.link} ${copied ? styles.copied : ''}`, children: [children, copied ? _jsx(Check, {}) : _jsx(Copy, {})] }) }));
28
+ }
29
+ return (_jsxs(Button, { ...rest, "aria-label": children ? '' : ((_b = rest['aria-label']) !== null && _b !== void 0 ? _b : 'Kopier til udklipsholder'), onClick: handleCopy, variant: variant, size: size, children: [_jsx("span", { className: `${styles.container} ${copied ? styles.copied : ''}`, children: copied ? _jsx(Check, {}) : _jsx(Copy, {}) }), children] }));
22
30
  }
@@ -61,10 +61,18 @@ function OperatorDropdown({ value, onChange, operators, size = 'sm', disabled, }
61
61
  return (_jsx(Menu.Item, { active: selected, children: _jsxs("button", { type: "button", onClick: () => handleSelect(op), disabled: disabled, children: [_jsx("span", { style: { width: 16, display: 'inline-flex', justifyContent: 'center' }, children: selected ? _jsx(Check, { size: 16 }) : null }), LABELS[op]] }) }, op));
62
62
  }) }) }));
63
63
  }
64
+ function isFilterActive(value) {
65
+ if (Array.isArray(value))
66
+ return value.length > 0;
67
+ if (typeof value === 'string')
68
+ return value.trim().length > 0;
69
+ return value != null;
70
+ }
64
71
  export function FilterField({ field, control, operator, value, onChange, operators, options = [], single = true, size = 'md', label, placeholder = 'Type value…', disabled, 'data-cy': dataCy, ...inputProps }) {
65
72
  var _a, _b;
66
73
  const [selectedOperator, setSelectedOperator] = useState(operator);
67
74
  const ops = useMemo(() => operators !== null && operators !== void 0 ? operators : DEFAULT_TEXT_OPERATORS, [operators]);
75
+ const active = isFilterActive(value);
68
76
  // Local state ONLY for input control (to avoid URL->props lag)
69
77
  const [localValue, setLocalValue] = useState((_a = value) !== null && _a !== void 0 ? _a : '');
70
78
  const debounceRef = useRef(null);
@@ -92,7 +100,7 @@ export function FilterField({ field, control, operator, value, onChange, operato
92
100
  debounceRef.current = setTimeout(() => {
93
101
  isTypingRef.current = false;
94
102
  emit({ value: nextVal });
95
- }, 250); // tweak debounce as needed
103
+ }, 250);
96
104
  };
97
105
  // Sync internal value when parent value changes (e.g. URL updates)
98
106
  useEffect(() => {
@@ -100,7 +108,6 @@ export function FilterField({ field, control, operator, value, onChange, operato
100
108
  if (control !== 'input')
101
109
  return;
102
110
  const incoming = (_a = value) !== null && _a !== void 0 ? _a : '';
103
- // don't fight the user mid-typing; once parent catches up, we allow sync again
104
111
  if (!isTypingRef.current && incoming !== localValue) {
105
112
  setLocalValue(incoming);
106
113
  }
@@ -115,25 +122,23 @@ export function FilterField({ field, control, operator, value, onChange, operato
115
122
  clearTimeout(debounceRef.current);
116
123
  };
117
124
  }, []);
118
- return (_jsxs("div", { ...(dataCy ? { 'data-cy': dataCy } : {}), className: ` ${styles.filterField} ${styles[size]} ${value ? styles.active : ''}`, children: [label ? _jsx("span", { className: `${styles.label} ${styles[size]}`, children: label }) : null, _jsx(OperatorDropdown, { value: selectedOperator, onChange: op => emit({ operator: op }), operators: ops, size: size, disabled: disabled }), _jsx("div", { className: `${control === 'input' ? 'dbc-flex' : styles.valueWrapper}`, children: control === 'input' ? (_jsx(Input, { ...inputProps, value: localValue, onChange: e => {
125
+ return (_jsxs("div", { ...(dataCy ? { 'data-cy': dataCy } : {}), className: `${styles.filterField} ${styles[size]} ${active ? styles.active : ''}`, children: [label ? _jsx("span", { className: `${styles.label} ${styles[size]}`, children: label }) : null, _jsx(OperatorDropdown, { value: selectedOperator, onChange: op => emit({ operator: op }), operators: ops, size: size, disabled: disabled }), _jsx("div", { className: `${control === 'input' ? 'dbc-flex dbc-flex-grow' : styles.valueWrapper}`, children: control === 'input' ? (_jsx(Input, { ...inputProps, value: localValue, onChange: e => {
119
126
  const next = e.currentTarget.value;
120
127
  isTypingRef.current = true;
121
- setLocalValue(next); // immediate UI update
122
- scheduleEmitValue(next); // debounced parent update
123
- }, inputSize: size, placeholder: placeholder, width: "160px", minWidth: "120px", disabled: disabled, onClear: () => {
128
+ setLocalValue(next);
129
+ scheduleEmitValue(next);
130
+ }, fullWidth: true, inputSize: size, placeholder: placeholder, width: "160px", minWidth: "120px", disabled: disabled, onClear: () => {
124
131
  isTypingRef.current = false;
125
132
  if (debounceRef.current)
126
133
  clearTimeout(debounceRef.current);
127
134
  setLocalValue('');
128
- emit({ value: '' }); // clear should be immediate
135
+ emit({ value: '' });
129
136
  } })) : single ? (_jsx(Select, { options: options, selectedValue: (_b = value) !== null && _b !== void 0 ? _b : null, onChange: v => emit({ value: v }), placeholder: placeholder, size: size, variant: "inline", onClear: () => emit({ value: '' }) })) : (_jsx(MultiSelect, { options: options, size: size, variant: "inline", selectedValues: (Array.isArray(value) ? value : []), onChange: v => {
130
137
  const current = new Set((Array.isArray(value) ? value : []));
131
- if (current.has(v)) {
138
+ if (current.has(v))
132
139
  current.delete(v);
133
- }
134
- else {
140
+ else
135
141
  current.add(v);
136
- }
137
142
  emit({ value: Array.from(current) });
138
143
  }, onClear: () => emit({ value: [] }), children: placeholder })) })] }));
139
144
  }
@@ -10,16 +10,22 @@
10
10
  border: var(--border-width-thin) solid var(--color-border-default);
11
11
  border-radius: var(--border-radius-default);
12
12
 
13
+ position: relative;
14
+
13
15
  transition:
14
16
  border-color var(--transition-fast) var(--ease-standard),
15
17
  box-shadow var(--transition-fast) var(--ease-standard),
16
18
  background-color var(--transition-fast) var(--ease-standard);
17
19
  }
18
20
 
19
- /* .filterField.active {
20
- border-color: var(--color-border-selected);
21
- background: var(--color-bg-selected);
22
- } */
21
+ /* More comfortable active state:
22
+ - less "blue outline" noise
23
+ - slightly warmer surface hint
24
+ */
25
+ .filterField.active {
26
+ border-color: color-mix(in srgb, var(--color-border-default) 75%, var(--color-border-selected));
27
+ background: color-mix(in srgb, var(--color-bg-surface) 96%, var(--color-bg-selected));
28
+ }
23
29
 
24
30
  .filterField.sm {
25
31
  block-size: calc(var(--component-size-sm) + var(--density));
@@ -39,6 +45,7 @@
39
45
  user-select: none;
40
46
  }
41
47
 
48
+ /* Operator trigger */
42
49
  .filterField .operatorTrigger {
43
50
  display: inline-flex;
44
51
  align-items: center;
@@ -68,30 +75,139 @@
68
75
  color: var(--color-disabled-fg);
69
76
  background: var(--color-disabled-bg);
70
77
  }
71
-
72
78
  .filterField .operatorText {
73
79
  white-space: nowrap;
74
80
  }
75
81
 
82
+ /* When active, operator is less dominant (calmer + more "token"-like) */
83
+ .filterField.active .operatorTrigger {
84
+ background: transparent;
85
+ color: var(--color-fg-muted);
86
+ }
87
+ .filterField.active .operatorTrigger:hover {
88
+ background: var(--opac-bg-dark);
89
+ color: var(--color-fg-default);
90
+ }
91
+
92
+ /* Wrapper for the select / multiselect control */
76
93
  .filterField .valueWrapper {
77
94
  display: inline-flex;
78
95
  align-items: center;
79
96
  padding: 0;
80
97
  height: 100%;
98
+
99
+ flex: 1;
100
+ min-width: 0;
81
101
  }
82
102
 
83
- .valueWrapper > * {
103
+ /* Ensure the control inside can stretch/shrink */
104
+ .filterField .valueWrapper > * {
84
105
  height: 100%;
85
- & > * {
86
- height: 100% !important;
87
- }
106
+ width: 100%;
107
+ min-width: 0;
88
108
  }
89
-
90
- .valueWrapper button {
109
+ .filterField .valueWrapper > * > * {
91
110
  height: 100% !important;
111
+ }
112
+
113
+ /* Active: emphasize VALUE area (but keep it soft) */
114
+ .filterField.active .valueWrapper {
115
+ background: color-mix(in srgb, var(--color-bg-surface) 88%, var(--color-bg-selected));
116
+ border-left: var(--border-width-thin) solid
117
+ color-mix(in srgb, var(--color-border-default) 80%, var(--color-border-selected));
118
+ border-top-right-radius: calc(var(--border-radius-default) - 1px);
119
+ border-bottom-right-radius: calc(var(--border-radius-default) - 1px);
120
+ }
121
+
122
+ /* =========================
123
+ TRIGGER BUTTON TARGETING
124
+ ========================= */
125
+
126
+ /* Select trigger button */
127
+ .filterField .valueWrapper :global(button[data-forminput]) {
128
+ width: 100%;
129
+ height: 100%;
130
+ border: 0 !important;
131
+
132
+ /* slightly more breathing room than before */
133
+ padding-inline: calc(var(--spacing-sm) + var(--spacing-2xs)) !important;
134
+
135
+ text-align: left;
136
+ justify-content: flex-start;
137
+ }
138
+
139
+ /* MultiSelect trigger button (Popover container is a div; trigger is its direct child button) */
140
+ .filterField .valueWrapper > div > button {
141
+ width: 100%;
142
+ height: 100%;
92
143
  border: 0 !important;
93
- padding-inline: var(--spacing-sm) !important;
144
+ padding-inline: calc(var(--spacing-sm) + var(--spacing-2xs)) !important;
145
+
146
+ text-align: left;
147
+ justify-content: flex-start;
148
+ }
149
+
150
+ /* Slight spacing between clear (×) and chevron for Select + MultiSelect
151
+ (feels less cramped / more intentional) */
152
+ .filterField .valueWrapper :global(button[data-forminput]) :global(.dbc-flex),
153
+ .filterField .valueWrapper > div > button {
154
+ column-gap: var(--spacing-xs);
155
+ }
156
+
157
+ /* Make the internal Select layout behave */
158
+ .filterField .valueWrapper :global(.dbc-flex) {
159
+ width: 100% !important;
160
+ min-width: 0;
161
+ }
162
+
163
+ .filterField .valueWrapper :global(.dbc-flex > span:first-child) {
164
+ flex: 1;
165
+ min-width: 0;
166
+ overflow: hidden;
167
+ text-overflow: ellipsis;
168
+ white-space: nowrap;
169
+ }
170
+
171
+ /* Keep ClearButton + chevron from stretching */
172
+ .filterField .valueWrapper :global(.dbc-flex) > *:not(span:first-child) {
173
+ flex: 0 0 auto;
174
+ }
175
+
176
+ /* For MultiSelect: label + chip should truncate nicely */
177
+ .filterField .valueWrapper > div > button > span:first-child {
178
+ display: inline-flex;
179
+ align-items: center;
180
+ gap: var(--spacing-xxs);
181
+
182
+ flex: 1;
183
+ min-width: 0;
184
+ overflow: hidden;
185
+ text-overflow: ellipsis;
186
+ white-space: nowrap;
187
+ }
188
+
189
+ /* Emphasize chosen value text in active state (but slightly less "boldy") */
190
+ .filterField.active .valueWrapper input {
191
+ font-weight: 550;
94
192
  }
193
+ .filterField.active .valueWrapper :global(button[data-forminput]),
194
+ .filterField.active .valueWrapper > div > button {
195
+ font-weight: 550 !important;
196
+ }
197
+
198
+ /* Icons calmer by default; crisp on hover/focus */
199
+ .filterField.active .valueWrapper svg {
200
+ opacity: 0.72;
201
+ }
202
+ .filterField.active .valueWrapper:hover svg,
203
+ .filterField.active .valueWrapper :global(button[data-forminput]):focus-visible svg,
204
+ .filterField.active .valueWrapper > div > button:focus-visible svg {
205
+ opacity: 1;
206
+ }
207
+
208
+ /* =========================
209
+ INPUT styling
210
+ ========================= */
95
211
 
96
212
  .filterField input {
97
213
  appearance: none;
@@ -103,6 +219,11 @@
103
219
  inline-size: auto;
104
220
  min-inline-size: 10ch;
105
221
  block-size: 100%;
222
+ border-top-left-radius: 0;
223
+ border-bottom-left-radius: 0;
224
+
225
+ /* a tiny bit more comfort */
226
+ padding-block: calc(var(--spacing-3xs) + var(--density));
106
227
  }
107
228
 
108
229
  .filterField button {
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { JSX } from 'react';
2
+ import type { JSX, ReactNode } from 'react';
3
3
  type Variant = 'default' | 'primary' | 'outlined';
4
4
  type Size = 'sm' | 'md' | 'lg';
5
5
  interface CheckboxProps {
@@ -8,7 +8,7 @@ interface CheckboxProps {
8
8
  variant?: Variant;
9
9
  disabled?: boolean;
10
10
  modified?: boolean;
11
- label?: string;
11
+ label?: ReactNode;
12
12
  size?: Size;
13
13
  containerLabel?: string;
14
14
  error?: string;
@@ -66,7 +66,7 @@ export function CheckboxGroup({ label, options, selectedValues, onChange, onTogg
66
66
  return (_jsxs("div", { className: wrapperClassName, "data-cy": dataCy, style: { ['--checkboxgroup-action-min-width']: actionMinWidth }, children: [label && _jsx("span", { className: styles.groupLabel, children: label }), _jsx("div", { className: itemsClassName, role: "group", "aria-label": label, children: options.map(opt => {
67
67
  const isChecked = selectedSet.has(opt.value);
68
68
  const isDisabled = disabled || !!opt.disabled;
69
- return (_jsx(Checkbox, { label: opt.label, checked: isChecked, disabled: isDisabled, variant: variant, size: size, onChange: () => {
69
+ return (_jsx(Checkbox, { label: opt.label, checked: isChecked, disabled: isDisabled, variant: variant, size: "sm", onChange: () => {
70
70
  if (isDisabled)
71
71
  return;
72
72
  toggleValue(opt.value);
@@ -30,7 +30,7 @@
30
30
  .contained {
31
31
  padding: 0 var(--spacing-xs);
32
32
  border: var(--border-width-thin) solid var(--color-border-subtle);
33
- border-radius: var(--border-radius-md);
33
+ border-radius: var(--border-radius-default);
34
34
  background: var(--color-bg-surface);
35
35
  }
36
36
 
@@ -23,7 +23,7 @@ function mergeRefs(...refs) {
23
23
  */
24
24
  export const Input = forwardRef(function Input({
25
25
  // InputContainer props
26
- label, error, helpText, orientation = 'horizontal', labelWidth = '160px', fullWidth = false, required, tooltip, tooltipPlacement = 'right', modified,
26
+ label, error, helpText, orientation = 'vertical', labelWidth = '160px', fullWidth = false, required, tooltip, tooltipPlacement = 'right', modified,
27
27
  // Input-only props
28
28
  icon, autoFocus, minWidth, width, inputSize = 'md', variant = 'outlined', onClear, onButtonClick, buttonLabel, buttonIcon,
29
29
  // Native input props
@@ -3,6 +3,7 @@
3
3
  /* inline-flex makes width behave weird in parents */
4
4
  display: inline-flex;
5
5
  align-items: stretch;
6
+ flex-grow: 1;
6
7
  gap: 0;
7
8
  /* width control */
8
9
  inline-size: var(--input-width, auto);
@@ -80,7 +80,7 @@
80
80
  */
81
81
  .inputContainer[data-modified] label:not(.label) {
82
82
  background-color: color-mix(in srgb, var(--color-status-warning-bg) 35%, transparent);
83
- border-radius: var(--border-radius-md);
83
+ border-radius: var(--border-radius-default);
84
84
  padding: 2px 6px;
85
85
  }
86
86
 
@@ -1,10 +1,22 @@
1
1
  import * as React from 'react';
2
- interface HyperlinkProps {
3
- component: React.ReactElement;
4
- className?: string;
2
+ type BaseProps = {
3
+ children: React.ReactNode;
5
4
  icon?: React.ReactNode;
6
- disableIcon?: boolean;
7
- onClick?: (e: React.MouseEvent) => void;
8
- }
9
- export declare function Hyperlink({ component, icon }: HyperlinkProps): React.ReactElement;
5
+ className?: string;
6
+ /**
7
+ * If true, Hyperlink will NOT render <a>.
8
+ * Instead, it will clone its only child (e.g. Next <Link>) and apply styling/props to it.
9
+ */
10
+ asChild?: boolean;
11
+ variant?: 'primary' | 'secondary';
12
+ inline?: boolean;
13
+ };
14
+ type AnchorProps = BaseProps & React.AnchorHTMLAttributes<HTMLAnchorElement> & {
15
+ as?: 'a';
16
+ };
17
+ type ButtonProps = BaseProps & React.ButtonHTMLAttributes<HTMLButtonElement> & {
18
+ as: 'button';
19
+ };
20
+ type HyperlinkProps = AnchorProps | ButtonProps;
21
+ export declare function Hyperlink(props: HyperlinkProps): React.ReactElement;
10
22
  export {};