@dbcdk/react-components 0.0.180 → 0.0.182
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/clear-button/ClearButton.cjs +34 -11
- package/dist/components/clear-button/ClearButton.d.ts +12 -1
- package/dist/components/clear-button/ClearButton.js +34 -11
- package/dist/components/clear-button/ClearButton.module.css +9 -0
- package/dist/components/forms/input/Input.cjs +8 -1
- package/dist/components/forms/input/Input.js +8 -1
- package/dist/components/forms/multi-select/MultiSelect.cjs +8 -1
- package/dist/components/forms/multi-select/MultiSelect.js +8 -1
- package/dist/components/forms/select/Select.cjs +8 -1
- package/dist/components/forms/select/Select.js +8 -1
- package/dist/components/interval-select/IntervalSelect.cjs +8 -1
- package/dist/components/interval-select/IntervalSelect.js +8 -1
- package/dist/components/json-viewer/JsonViewer.cjs +196 -83
- package/dist/components/json-viewer/JsonViewer.d.ts +1 -1
- package/dist/components/json-viewer/JsonViewer.js +197 -84
- package/dist/components/json-viewer/JsonViewer.module.css +37 -44
- package/dist/components/json-viewer/types.d.ts +8 -0
- package/dist/components/search-box/SearchBox.cjs +9 -1
- package/dist/components/search-box/SearchBox.d.ts +3 -3
- package/dist/components/search-box/SearchBox.js +9 -1
- package/dist/components/tabs/Tabs.cjs +50 -21
- package/dist/components/tabs/Tabs.d.ts +7 -1
- package/dist/components/tabs/Tabs.js +50 -21
- package/dist/components/tabs/Tabs.module.css +91 -11
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ export type TabItem = {
|
|
|
8
8
|
disabled?: boolean;
|
|
9
9
|
hidden?: boolean;
|
|
10
10
|
badge?: number | string;
|
|
11
|
+
removable?: boolean;
|
|
11
12
|
};
|
|
12
13
|
type TabsVariant = 'filled' | 'outlined';
|
|
13
14
|
export interface TabsProps {
|
|
@@ -27,6 +28,10 @@ export interface TabsProps {
|
|
|
27
28
|
*/
|
|
28
29
|
storageKey?: string;
|
|
29
30
|
onValueChange?: (id: TabId, tab: TabItem, index: number) => void;
|
|
31
|
+
/** Called when a removable tab's remove button is pressed. The caller owns removing the tab. */
|
|
32
|
+
onRemoveTab?: (id: TabId, tab: TabItem, index: number) => void;
|
|
33
|
+
/** Shows an add-tab button and notifies the caller. The caller owns creating and selecting the tab. */
|
|
34
|
+
onAddTab?: () => void;
|
|
30
35
|
addition?: ReactNode;
|
|
31
36
|
loading?: boolean;
|
|
32
37
|
/** Composition API */
|
|
@@ -39,13 +44,14 @@ export interface TabsItemProps {
|
|
|
39
44
|
disabled?: boolean;
|
|
40
45
|
hidden?: boolean;
|
|
41
46
|
badge?: number;
|
|
47
|
+
removable?: boolean;
|
|
42
48
|
children?: ReactNode;
|
|
43
49
|
}
|
|
44
50
|
type SlotName = 'Item';
|
|
45
51
|
type TabsItemComponent = ((props: TabsItemProps) => JSX.Element) & {
|
|
46
52
|
__TABS_SLOT__?: SlotName;
|
|
47
53
|
};
|
|
48
|
-
export declare function Tabs({ header, subheader, variant, panelStyle, tabs, value, defaultValue, storageKey, onValueChange, addition, loading, children, }: TabsProps): JSX.Element;
|
|
54
|
+
export declare function Tabs({ header, subheader, variant, panelStyle, tabs, value, defaultValue, storageKey, onValueChange, onRemoveTab, onAddTab, addition, loading, children, }: TabsProps): JSX.Element;
|
|
49
55
|
export declare namespace Tabs {
|
|
50
56
|
var Item: TabsItemComponent;
|
|
51
57
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { X, Plus } from 'lucide-react';
|
|
2
3
|
import { useId, useMemo, useCallback, useEffect, Children, isValidElement } from 'react';
|
|
3
4
|
import { usePersistentState } from '../../hooks/usePersistentState';
|
|
4
5
|
import styles from './Tabs.module.css';
|
|
@@ -31,6 +32,7 @@ function normalizeFromChildren(children) {
|
|
|
31
32
|
disabled: props.disabled,
|
|
32
33
|
hidden: props.hidden,
|
|
33
34
|
badge: props.badge,
|
|
35
|
+
removable: props.removable,
|
|
34
36
|
content: props.children
|
|
35
37
|
});
|
|
36
38
|
});
|
|
@@ -46,6 +48,8 @@ function Tabs({
|
|
|
46
48
|
defaultValue,
|
|
47
49
|
storageKey,
|
|
48
50
|
onValueChange,
|
|
51
|
+
onRemoveTab,
|
|
52
|
+
onAddTab,
|
|
49
53
|
addition,
|
|
50
54
|
loading = false,
|
|
51
55
|
children
|
|
@@ -138,31 +142,56 @@ function Tabs({
|
|
|
138
142
|
}
|
|
139
143
|
) : null,
|
|
140
144
|
/* @__PURE__ */ jsxs("div", { className: `${styles.tabs} ${styles[variant]} ${panelStyle ? styles.panelStyle : ""}`, children: [
|
|
141
|
-
/* @__PURE__ */
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
/* @__PURE__ */ jsxs("div", { className: styles.tabList, children: [
|
|
146
|
+
/* @__PURE__ */ jsx("div", { className: styles.tabButtons, role: "tablist", "aria-label": header != null ? header : "Tabs", children: visibleTabs.map((tab, index) => {
|
|
147
|
+
const selected = index === activeIndex;
|
|
148
|
+
const tabDomId = `${uid}-tab-${String(tab.id)}`;
|
|
149
|
+
const panelDomId = `${uid}-panel-${String(tab.id)}`;
|
|
150
|
+
return /* @__PURE__ */ jsxs("div", { className: `${styles.tab} ${selected ? styles.active : ""}`, children: [
|
|
151
|
+
/* @__PURE__ */ jsxs(
|
|
152
|
+
"button",
|
|
153
|
+
{
|
|
154
|
+
id: tabDomId,
|
|
155
|
+
type: "button",
|
|
156
|
+
className: styles.tabButton,
|
|
157
|
+
role: "tab",
|
|
158
|
+
"aria-selected": selected,
|
|
159
|
+
"aria-controls": panelDomId,
|
|
160
|
+
tabIndex: selected ? 0 : -1,
|
|
161
|
+
disabled: tab.disabled,
|
|
162
|
+
onClick: () => setValue(tab.id),
|
|
163
|
+
onKeyDown: (e) => onKeyDownTab(e, index),
|
|
164
|
+
children: [
|
|
165
|
+
tab.headerIcon ? /* @__PURE__ */ jsx("span", { className: styles.icon, children: tab.headerIcon }) : null,
|
|
166
|
+
/* @__PURE__ */ jsx("span", { className: styles.label, children: tab.header }),
|
|
167
|
+
tab.badge ? /* @__PURE__ */ jsx("span", { className: styles.badge, children: /* @__PURE__ */ jsx(Chip, { size: "sm", children: tab.badge.toLocaleString("da-DK") }) }) : null
|
|
168
|
+
]
|
|
169
|
+
}
|
|
170
|
+
),
|
|
171
|
+
tab.removable && onRemoveTab ? /* @__PURE__ */ jsx(
|
|
172
|
+
"button",
|
|
173
|
+
{
|
|
174
|
+
type: "button",
|
|
175
|
+
className: styles.removeTabButton,
|
|
176
|
+
"aria-label": `Fjern fane ${tab.header}`,
|
|
177
|
+
disabled: tab.disabled,
|
|
178
|
+
onClick: () => onRemoveTab(tab.id, tab, index),
|
|
179
|
+
children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
|
|
180
|
+
}
|
|
181
|
+
) : null
|
|
182
|
+
] }, tab.id);
|
|
183
|
+
}) }),
|
|
184
|
+
onAddTab ? /* @__PURE__ */ jsx(
|
|
146
185
|
"button",
|
|
147
186
|
{
|
|
148
|
-
id: tabDomId,
|
|
149
187
|
type: "button",
|
|
150
|
-
className: styles.
|
|
151
|
-
|
|
152
|
-
"aria-
|
|
153
|
-
"aria-
|
|
154
|
-
tabIndex: selected ? 0 : -1,
|
|
155
|
-
disabled: tab.disabled,
|
|
156
|
-
onClick: () => setValue(tab.id),
|
|
157
|
-
onKeyDown: (e) => onKeyDownTab(e, index),
|
|
158
|
-
children: [
|
|
159
|
-
tab.headerIcon ? /* @__PURE__ */ jsx("span", { className: styles.icon, children: tab.headerIcon }) : null,
|
|
160
|
-
/* @__PURE__ */ jsx("span", { className: styles.label, children: tab.header }),
|
|
161
|
-
tab.badge ? /* @__PURE__ */ jsx("span", { className: styles.badge, children: /* @__PURE__ */ jsx(Chip, { size: "sm", children: tab.badge.toLocaleString("da-DK") }) }) : null
|
|
162
|
-
]
|
|
188
|
+
className: styles.addTabButton,
|
|
189
|
+
onClick: onAddTab,
|
|
190
|
+
"aria-label": "Tilf\xF8j fane",
|
|
191
|
+
children: /* @__PURE__ */ jsx(Plus, { "aria-hidden": "true" })
|
|
163
192
|
}
|
|
164
|
-
)
|
|
165
|
-
|
|
193
|
+
) : null
|
|
194
|
+
] }),
|
|
166
195
|
/* @__PURE__ */ jsx(
|
|
167
196
|
"div",
|
|
168
197
|
{
|
|
@@ -26,6 +26,11 @@
|
|
|
26
26
|
|
|
27
27
|
/* Tablist */
|
|
28
28
|
.tabList {
|
|
29
|
+
display: flex;
|
|
30
|
+
min-width: 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.tabButtons {
|
|
29
34
|
display: flex;
|
|
30
35
|
flex-wrap: wrap;
|
|
31
36
|
min-width: 0;
|
|
@@ -34,7 +39,7 @@
|
|
|
34
39
|
/* Individual tab wrapper */
|
|
35
40
|
.tab {
|
|
36
41
|
display: flex;
|
|
37
|
-
|
|
42
|
+
align-items: stretch;
|
|
38
43
|
border-radius: 0;
|
|
39
44
|
border-block-end: 2px solid var(--color-border-default);
|
|
40
45
|
}
|
|
@@ -82,6 +87,68 @@
|
|
|
82
87
|
color: var(--color-disabled-fg);
|
|
83
88
|
}
|
|
84
89
|
|
|
90
|
+
.removeTabButton {
|
|
91
|
+
display: inline-flex;
|
|
92
|
+
align-items: center;
|
|
93
|
+
justify-content: center;
|
|
94
|
+
align-self: stretch;
|
|
95
|
+
|
|
96
|
+
color: inherit;
|
|
97
|
+
background: none;
|
|
98
|
+
border: 0;
|
|
99
|
+
border-radius: 0;
|
|
100
|
+
padding-inline: var(--spacing-xs);
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.removeTabButton:hover {
|
|
105
|
+
color: var(--color-brand);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.removeTabButton:focus-visible {
|
|
109
|
+
outline: none;
|
|
110
|
+
box-shadow: var(--focus-ring);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.removeTabButton:disabled {
|
|
114
|
+
cursor: not-allowed;
|
|
115
|
+
color: var(--color-disabled-fg);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.removeTabButton svg {
|
|
119
|
+
inline-size: var(--icon-size-sm);
|
|
120
|
+
block-size: var(--icon-size-sm);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.addTabButton {
|
|
124
|
+
display: inline-flex;
|
|
125
|
+
align-items: center;
|
|
126
|
+
justify-content: center;
|
|
127
|
+
align-self: stretch;
|
|
128
|
+
|
|
129
|
+
color: var(--color-fg-muted);
|
|
130
|
+
background: none;
|
|
131
|
+
border: 0;
|
|
132
|
+
border-radius: 0;
|
|
133
|
+
padding-inline: var(--spacing-md);
|
|
134
|
+
cursor: pointer;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.addTabButton:hover {
|
|
138
|
+
color: var(--color-fg-default);
|
|
139
|
+
background: var(--color-bg-hover-subtle);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.addTabButton:focus-visible {
|
|
143
|
+
outline: none;
|
|
144
|
+
box-shadow: var(--focus-ring);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.addTabButton svg {
|
|
148
|
+
inline-size: var(--icon-size-sm);
|
|
149
|
+
block-size: var(--icon-size-sm);
|
|
150
|
+
}
|
|
151
|
+
|
|
85
152
|
/* Icon + label */
|
|
86
153
|
.icon {
|
|
87
154
|
display: inline-flex;
|
|
@@ -125,7 +192,7 @@
|
|
|
125
192
|
gap: 0;
|
|
126
193
|
}
|
|
127
194
|
|
|
128
|
-
/*
|
|
195
|
+
/* Filled tabs mimic a browser tab strip: a muted toolbar with a raised active page. */
|
|
129
196
|
.tabs.filled {
|
|
130
197
|
border-radius: var(--border-radius-md);
|
|
131
198
|
background: var(--color-bg-surface);
|
|
@@ -134,12 +201,26 @@
|
|
|
134
201
|
|
|
135
202
|
.filled .tabList {
|
|
136
203
|
border-block-end: 1px solid var(--color-border-subtle);
|
|
137
|
-
background: var(--color-bg-
|
|
204
|
+
background: var(--color-bg-toolbar);
|
|
138
205
|
inline-size: 100%;
|
|
139
206
|
}
|
|
140
207
|
|
|
208
|
+
.filled .tabButtons {
|
|
209
|
+
display: flex;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.filled .addTabButton {
|
|
213
|
+
border: 1px solid transparent;
|
|
214
|
+
border-block-end: 0;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.filled .addTabButton:hover {
|
|
218
|
+
background: var(--color-bg-toolbar-hover);
|
|
219
|
+
}
|
|
220
|
+
|
|
141
221
|
.filled .tab {
|
|
142
222
|
border: 1px solid transparent;
|
|
223
|
+
border-block-end: 0;
|
|
143
224
|
color: var(--color-fg-muted);
|
|
144
225
|
position: relative;
|
|
145
226
|
transition:
|
|
@@ -149,22 +230,21 @@
|
|
|
149
230
|
}
|
|
150
231
|
|
|
151
232
|
.filled .tab:not(.active):hover {
|
|
152
|
-
|
|
233
|
+
background: var(--color-bg-toolbar-hover);
|
|
234
|
+
color: var(--color-fg-default);
|
|
153
235
|
}
|
|
154
236
|
|
|
155
237
|
/* Active tab physically overlaps the tabList separator by 1px so its
|
|
156
|
-
erased bottom border seamlessly merges with the panel below.
|
|
157
|
-
No top border — the outer container already provides the top edge. */
|
|
238
|
+
erased bottom border seamlessly merges with the panel below. */
|
|
158
239
|
.filled .tab.active {
|
|
159
|
-
background: var(--
|
|
160
|
-
border-
|
|
161
|
-
border-block-
|
|
162
|
-
border-block-end-color: var(--opac-bg-brand);
|
|
240
|
+
background: var(--color-bg-surface);
|
|
241
|
+
border-color: var(--color-border-subtle);
|
|
242
|
+
border-block-end-color: var(--color-bg-surface);
|
|
163
243
|
border-start-start-radius: var(--border-radius-md);
|
|
164
244
|
border-start-end-radius: var(--border-radius-md);
|
|
165
245
|
margin-block-end: -1px;
|
|
166
246
|
z-index: 1;
|
|
167
|
-
color: var(--color-
|
|
247
|
+
color: var(--color-fg-default);
|
|
168
248
|
}
|
|
169
249
|
|
|
170
250
|
.filled .tabContent {
|