@dbcdk/react-components 0.0.15 → 0.0.16

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.
@@ -21,6 +21,7 @@ interface ChipMultiToggleProps {
21
21
  showAllOption?: boolean;
22
22
  allLabel?: string;
23
23
  allIcon?: React.ReactNode;
24
+ dataCy?: string;
24
25
  /**
25
26
  * If true, clicking "All" toggles between:
26
27
  * - All (no filtering) => []
@@ -33,5 +34,5 @@ interface ChipMultiToggleProps {
33
34
  */
34
35
  noneValue?: string;
35
36
  }
36
- export declare function ChipMultiToggle({ label, options, selectedValues, onChange, onToggle, size, selectedSeverity, unselectedSeverity, fullWidth, disabled, showAllOption, allLabel, allIcon, showSelectedIcon, allTogglesNone, noneValue, }: ChipMultiToggleProps): JSX.Element;
37
+ export declare function ChipMultiToggle({ label, options, selectedValues, onChange, onToggle, size, selectedSeverity, unselectedSeverity, fullWidth, disabled, showAllOption, allLabel, allIcon, showSelectedIcon, allTogglesNone, noneValue, dataCy, }: ChipMultiToggleProps): JSX.Element;
37
38
  export {};
@@ -4,7 +4,7 @@ import { Check } from 'lucide-react';
4
4
  import React from 'react';
5
5
  import { Chip } from '../../../components/chip/Chip';
6
6
  import styles from './ChipMultiToggle.module.css';
7
- export function ChipMultiToggle({ label, options, selectedValues = [], onChange, onToggle, size = 'sm', selectedSeverity = 'info', unselectedSeverity = null, fullWidth = false, disabled = false, showAllOption = false, allLabel = 'Alle', allIcon, showSelectedIcon = false, allTogglesNone = false, noneValue = '__none__', }) {
7
+ export function ChipMultiToggle({ label, options, selectedValues = [], onChange, onToggle, size = 'sm', selectedSeverity = 'info', unselectedSeverity = null, fullWidth = false, disabled = false, showAllOption = false, allLabel = 'Alle', allIcon, showSelectedIcon = false, allTogglesNone = false, noneValue = '__none__', dataCy, }) {
8
8
  const selectedSet = React.useMemo(() => new Set(selectedValues), [selectedValues]);
9
9
  const isNoneSelected = allTogglesNone && selectedSet.has(noneValue);
10
10
  const isAllSelected = showAllOption && !isNoneSelected && selectedSet.size === 0;
@@ -46,7 +46,7 @@ export function ChipMultiToggle({ label, options, selectedValues = [], onChange,
46
46
  onChange([]);
47
47
  }
48
48
  };
49
- return (_jsxs("div", { className: `${styles.wrapper} ${fullWidth ? styles.fullWidth : ''}`, children: [label && _jsx("span", { className: styles.label, children: label }), _jsxs("div", { className: styles.container, children: [showAllOption && (_jsx("button", { type: "button", className: styles.chipButton, onClick: toggleAll, "aria-pressed": isAllSelected || isNoneSelected, disabled: disabled, children: _jsx(Chip, { size: size, severity: (isAllSelected || isNoneSelected ? selectedSeverity : unselectedSeverity), customIcon: allIcon, type: unselectedSeverity === null ? 'outlined' : 'rounded', children: isNoneSelected ? `${allLabel} (ingen)` : allLabel }) }, "__all__")), options.map(opt => {
49
+ return (_jsxs("div", { className: `${styles.wrapper} ${fullWidth ? styles.fullWidth : ''}`, "data-cy": dataCy, children: [label && _jsx("span", { className: styles.label, children: label }), _jsxs("div", { className: styles.container, children: [showAllOption && (_jsx("button", { type: "button", className: styles.chipButton, onClick: toggleAll, "aria-pressed": isAllSelected || isNoneSelected, disabled: disabled, children: _jsx(Chip, { size: size, severity: (isAllSelected || isNoneSelected ? selectedSeverity : unselectedSeverity), customIcon: allIcon, type: unselectedSeverity === null ? 'outlined' : 'rounded', children: isNoneSelected ? `${allLabel} (ingen)` : allLabel }) }, "__all__")), options.map(opt => {
50
50
  // If none-state is active, everything else should look unselected
51
51
  const isSelected = !isNoneSelected && selectedSet.has(opt.value);
52
52
  return (_jsx("button", { type: "button", className: styles.chipButton, onClick: () => toggleValue(opt.value), "aria-pressed": isSelected, disabled: disabled, children: _jsx(Chip, { size: size, severity: (isSelected ? selectedSeverity : unselectedSeverity), customIcon: showSelectedIcon ? isSelected ? _jsx(Check, {}) : null : opt.icon, type: unselectedSeverity === null ? 'outlined' : 'rounded', children: opt.label }) }, opt.value));
@@ -28,12 +28,24 @@ export function Table({ data, columns, selectedRows, onRowSelect, selectionMode
28
28
  const nextDir = getNextSortDirection(column.sortable, active, sortDirection !== null && sortDirection !== void 0 ? sortDirection : null);
29
29
  onSortChange(column, nextDir);
30
30
  };
31
- return (_jsx("th", { style: getColumnStyle(column.id, columnStyles, column.align, 'middle'), "aria-sort": ariaSort, className: `${styles.th}`, children: _jsxs("div", { className: styles.thInner, children: [column.sortable ? (_jsxs("button", { type: "button", className: `${styles.thButton} ${column.align ? styles[`thButton${column.align}`] : ''}`, onClick: toggleSort, onKeyDown: e => {
31
+ return (_jsx("th", { style: getColumnStyle(column.id, columnStyles, column.align, 'middle'), "aria-sort": ariaSort, className: `${styles.th}`, children: _jsxs("div", { className: styles.thInner, children: [column.sortable ? (_jsxs("button", { type: "button", className: [
32
+ styles.thButton,
33
+ column.align === 'right' ? styles.thButtonRight : '',
34
+ column.align === 'center' ? styles.thButtonCenter : '',
35
+ ].join(' '), onClick: toggleSort, onKeyDown: e => {
32
36
  if (shouldToggleOnKey(e.key)) {
33
37
  e.preventDefault();
34
38
  toggleSort();
35
39
  }
36
- }, children: [_jsx("span", { className: styles.thLabel, children: getHeaderLabel(column.header) }), _jsxs("span", { className: styles.sortIndicator, "aria-hidden": "true", children: [active && sortDirection === 'asc' && _jsx(ArrowUp, {}), active && sortDirection === 'desc' && (_jsx(ArrowDown, { className: styles.descending })), !active && (_jsx(ArrowDown, { className: `${styles.descending} ${styles.inActiveSort}` }))] })] })) : (_jsx("span", { className: styles.thLabel, children: getHeaderLabel(column.header) })), headerExtras ? (_jsx("div", { className: styles.thExtras, children: headerExtras({ column, index }) })) : null] }) }, column.id));
40
+ }, children: [_jsx("span", { className: [
41
+ styles.thLabel,
42
+ column.align === 'right' ? styles.thLabelRight : '',
43
+ column.align === 'center' ? styles.thLabelCenter : '',
44
+ ].join(' '), children: getHeaderLabel(column.header) }), _jsxs("span", { className: styles.sortIndicator, "aria-hidden": "true", children: [active && sortDirection === 'asc' && _jsx(ArrowUp, {}), active && sortDirection === 'desc' && (_jsx(ArrowDown, { className: styles.descending })), !active && (_jsx(ArrowDown, { className: `${styles.descending} ${styles.inActiveSort}` }))] })] })) : (_jsx("span", { className: [
45
+ styles.thLabel,
46
+ column.align === 'right' ? styles.thLabelRight : '',
47
+ column.align === 'center' ? styles.thLabelCenter : '',
48
+ ].join(' '), children: getHeaderLabel(column.header) })), headerExtras ? (_jsx("div", { className: styles.thExtras, children: headerExtras({ column, index }) })) : null] }) }, column.id));
37
49
  })] }) }), loading && !data.length ? (_jsx("tbody", { className: `${styles.tBody} ${striped ? styles.striped : ''}`, children: Array.from({ length: take !== null && take !== void 0 ? take : 5 }).map((_, rowIndex) => (_jsx("tr", { children: filteredColumns.map((column, colIndex) => (_jsx("td", { style: getColumnStyle(column.id, columnStyles, column.align, 'middle'), className: `${styles.tableCell}`, children: _jsx(SkeletonLoaderItem, { height: 20, width: "100%" }) }, `${column.id}-${colIndex}`))) }, `loading-row-${rowIndex}`))) })) : (_jsx("tbody", { className: `${styles.tBody} ${striped ? styles.striped : ''}`, children: data === null || data === void 0 ? void 0 : data.map(row => {
38
50
  const rowSeverity = getRowSeverity === null || getRowSeverity === void 0 ? void 0 : getRowSeverity(row);
39
51
  const rowId = row[dataKey];
@@ -78,57 +78,59 @@
78
78
  inline-size: 100%;
79
79
  }
80
80
 
81
- /* Actual interactive control for sorting */
81
+ /* Sort button (full width click target, but content aligns via modifiers) */
82
82
  .thButton {
83
83
  all: unset;
84
- display: inline-flex;
84
+ display: flex;
85
85
  align-items: center;
86
86
  gap: var(--spacing-xxs);
87
87
  inline-size: 100%;
88
88
  cursor: pointer;
89
89
  user-select: none;
90
- /* make it feel like a button */
91
90
  border-radius: var(--border-radius-default);
92
91
  padding-block: 2px;
93
92
  padding-inline: 2px;
93
+
94
+ /* default */
95
+ justify-content: flex-start;
94
96
  }
95
97
 
96
- .thButtonright {
98
+ /* IMPORTANT: use consistent PascalCase suffixes */
99
+ .thButtonRight {
97
100
  justify-content: flex-end;
98
101
  }
99
102
 
100
- .thButtoncenter {
103
+ .thButtonCenter {
101
104
  justify-content: center;
102
105
  }
103
106
 
104
- .thButton:hover {
105
- color: var(--color-fg-default);
106
- }
107
-
108
- .thButton:focus-visible {
109
- outline: none;
110
- box-shadow: var(--focus-ring);
111
- }
112
-
107
+ /* Label should NOT grow to fill space (it breaks alignment) */
113
108
  .thLabel {
114
109
  overflow: hidden;
115
110
  text-overflow: ellipsis;
116
111
  white-space: nowrap;
112
+ flex: 0 1 auto;
113
+ min-width: 0;
114
+ }
115
+
116
+ /* Match label text alignment to column alignment */
117
+ .thLabelRight {
118
+ text-align: right;
119
+ }
120
+
121
+ .thLabelCenter {
122
+ text-align: center;
117
123
  }
118
124
 
119
125
  .thExtras {
120
- margin-inline-start: auto;
121
126
  display: inline-flex;
122
127
  align-items: center;
123
128
  }
124
129
 
125
- .inActiveSort {
126
- color: var(--color-fg-subtle);
127
- opacity: 0.4;
128
- }
129
-
130
130
  .sortIndicator {
131
- display: flex;
131
+ display: inline-flex;
132
+ flex: 0 0 auto;
133
+ align-items: center;
132
134
  }
133
135
 
134
136
  .sortIndicator svg {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dbcdk/react-components",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "Reusable React components for DBC projects",
5
5
  "license": "ISC",
6
6
  "author": "",