@dbcdk/react-components 0.0.209 → 0.0.211

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 (58) hide show
  1. package/dist/client.cjs +10 -0
  2. package/dist/client.d.ts +4 -0
  3. package/dist/client.js +2 -0
  4. package/dist/components/forms/markdown-editor/MarkdownEditor.cjs +475 -0
  5. package/dist/components/forms/markdown-editor/MarkdownEditor.d.ts +68 -0
  6. package/dist/components/forms/markdown-editor/MarkdownEditor.js +468 -0
  7. package/dist/components/forms/markdown-editor/MarkdownEditor.module.css +202 -0
  8. package/dist/components/forms/markdown-editor/MarkdownViewer.cjs +29 -0
  9. package/dist/components/forms/markdown-editor/MarkdownViewer.d.ts +27 -0
  10. package/dist/components/forms/markdown-editor/MarkdownViewer.js +23 -0
  11. package/dist/components/forms/markdown-editor/MarkdownViewer.module.css +97 -0
  12. package/dist/components/forms/markdown-editor/markdown.utils.cjs +325 -0
  13. package/dist/components/forms/markdown-editor/markdown.utils.d.ts +66 -0
  14. package/dist/components/forms/markdown-editor/markdown.utils.js +310 -0
  15. package/dist/components/listbox/Listbox.cjs +2 -2
  16. package/dist/components/listbox/Listbox.d.ts +2 -2
  17. package/dist/components/listbox/Listbox.js +2 -2
  18. package/dist/components/meta-bar/MetaBar.cjs +2 -2
  19. package/dist/components/meta-bar/MetaBar.d.ts +2 -1
  20. package/dist/components/meta-bar/MetaBar.js +2 -2
  21. package/dist/components/meta-bar/MetaBar.module.css +7 -0
  22. package/dist/components/nav-bar/NavBar.d.ts +2 -1
  23. package/dist/components/overlay/tooltip/TooltipProvider.cjs +10 -1
  24. package/dist/components/overlay/tooltip/TooltipProvider.js +11 -2
  25. package/dist/components/overlay/tooltip/useTooltipTrigger.cjs +9 -2
  26. package/dist/components/overlay/tooltip/useTooltipTrigger.js +9 -2
  27. package/dist/components/sidebar/Sidebar.cjs +2 -1
  28. package/dist/components/sidebar/Sidebar.js +2 -1
  29. package/dist/components/sidebar/components/SidebarItem.cjs +34 -13
  30. package/dist/components/sidebar/components/SidebarItem.d.ts +4 -2
  31. package/dist/components/sidebar/components/SidebarItem.js +30 -13
  32. package/dist/components/sidebar/components/SidebarItem.module.css +16 -0
  33. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.cjs +41 -116
  34. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.d.ts +4 -5
  35. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.js +42 -117
  36. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.module.css +17 -25
  37. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.cjs +1 -1
  38. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.js +1 -1
  39. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.module.css +0 -1
  40. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.cjs +1 -2
  41. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.d.ts +1 -2
  42. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.js +1 -2
  43. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.module.css +4 -10
  44. package/dist/components/sidebar/components/sidebar-items/SidebarItems.cjs +11 -19
  45. package/dist/components/sidebar/components/sidebar-items/SidebarItems.js +11 -19
  46. package/dist/components/sidebar/components/sidebar-items/SidebarItems.module.css +0 -1
  47. package/dist/components/sidebar/providers/SidebarProvider.cjs +9 -7
  48. package/dist/components/sidebar/providers/SidebarProvider.d.ts +2 -1
  49. package/dist/components/sidebar/providers/SidebarProvider.js +9 -7
  50. package/dist/components/tabs/Tabs.cjs +83 -69
  51. package/dist/components/tabs/Tabs.d.ts +5 -1
  52. package/dist/components/tabs/Tabs.js +83 -69
  53. package/dist/components/tabs/Tabs.module.css +39 -0
  54. package/dist/index.cjs +213 -208
  55. package/dist/index.css +2 -0
  56. package/dist/index.d.ts +2 -0
  57. package/dist/index.js +1 -0
  58. package/package.json +4 -1
@@ -0,0 +1,310 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import MarkdownIt from 'markdown-it';
3
+ import React from 'react';
4
+
5
+ const ESCAPE_PATTERN = /\\[!-/:-@[-`{-~]/;
6
+ const LINK_PATTERN = /\[((?:\\[^\n]|[^\]\\\n])+)\]\(((?:[^()\s]|\([^()\s]*\))+)\)/;
7
+ const escapeRegExp = (text) => text.replace(/[.*+?^$()|[\]\\{}]/g, "\\$&");
8
+ const linkPattern = (urlPlaceholder) => new RegExp(LINK_PATTERN.source.replace(/\)\\\)$/, `|${escapeRegExp(urlPlaceholder)})\\)`));
9
+ const LINK_PLACEHOLDER_TEXT = "linktekst";
10
+ const LINK_PLACEHOLDER_URL = "inds\xE6t url";
11
+ const parser = new MarkdownIt();
12
+ parser.validateLink = (url) => getSafeHref(url) !== void 0;
13
+ function getSafeHref(url) {
14
+ if ([...url].some((character) => character < " " || character === "\x7F")) return void 0;
15
+ const hasScheme = /^[a-z][a-z0-9+.-]*:/i.test(url);
16
+ return !hasScheme || /^(https?|mailto|tel):/i.test(url) ? url : void 0;
17
+ }
18
+ function findLinkAt(value, selectionStart, selectionEnd, urlPlaceholder = LINK_PLACEHOLDER_URL) {
19
+ const pattern = new RegExp(`${ESCAPE_PATTERN.source}|${linkPattern(urlPlaceholder).source}`, "g");
20
+ let match;
21
+ while ((match = pattern.exec(value)) !== null) {
22
+ if (match.index > selectionStart) return void 0;
23
+ const end = match.index + match[0].length;
24
+ if (match[1] !== void 0 && selectionEnd <= end) {
25
+ return { start: match.index, end, text: match[1] };
26
+ }
27
+ }
28
+ return void 0;
29
+ }
30
+ function escapeMarkdown(value) {
31
+ return value.replace(/[!-/:-@[-`{-~]/g, "\\$&");
32
+ }
33
+ function unescapeMarkdown(value) {
34
+ return value.replace(/\\([!-/:-@[-`{-~])/g, "$1");
35
+ }
36
+ const INLINE_SYNTAX = /\\(?=[!-/:-@[-`{-~]|$)|[`*_[<~|]|&(?=#?[a-z0-9]+;)/gi;
37
+ const BLOCK_SYNTAX = /^(\s*)(#{1,6}(?=\s|$)|>|[-+=](?=\s|$)|[-=]+\s*$)|^(\s*\d+)([.)])(?=\s|$)/;
38
+ const INDENT_ENTITIES = { " ": "&nbsp;", " ": "&#9;" };
39
+ const ENCODED_INDENT = /^(?:&nbsp;|&#9;)+/gm;
40
+ function escapePlainLine(line) {
41
+ if (!line.trim()) return line;
42
+ const indent = /^[ \t]*/.exec(line)[0];
43
+ const escaped = line.slice(indent.length).replace(INLINE_SYNTAX, "\\$&");
44
+ if (indent) return `${indent.replace(/[ \t]/g, (space) => INDENT_ENTITIES[space])}${escaped}`;
45
+ return escaped.replace(
46
+ BLOCK_SYNTAX,
47
+ (_, indent2, marker, number, delimiter) => marker === void 0 ? `${number}\\${delimiter}` : `${indent2}\\${marker}`
48
+ );
49
+ }
50
+ function plainTextToMarkdown(text) {
51
+ const lines = text.split("\n");
52
+ return lines.map((line, index) => {
53
+ const escaped = escapePlainLine(line);
54
+ return index < lines.length - 1 && line.trim() && lines[index + 1].trim() ? `${escaped}\\` : escaped;
55
+ }).join("\n");
56
+ }
57
+ function limitPlainText(previous, next, maxLength) {
58
+ if (maxLength === void 0 || next.length < previous.length || plainTextToMarkdown(next).length <= maxLength) {
59
+ return { text: next, caret: -1 };
60
+ }
61
+ let start = 0;
62
+ while (start < previous.length && start < next.length && previous[start] === next[start]) start++;
63
+ let end = 0;
64
+ while (end < previous.length - start && end < next.length - start && previous[previous.length - 1 - end] === next[next.length - 1 - end]) {
65
+ end++;
66
+ }
67
+ const inserted = next.slice(start, next.length - end);
68
+ const withInserted = (length) => `${next.slice(0, start)}${inserted.slice(0, length)}${next.slice(next.length - end)}`;
69
+ let low = 0;
70
+ let high = inserted.length;
71
+ while (low < high) {
72
+ const middle = Math.ceil((low + high) / 2);
73
+ if (plainTextToMarkdown(withInserted(middle)).length <= maxLength) low = middle;
74
+ else high = middle - 1;
75
+ }
76
+ const text = withInserted(low);
77
+ return text === previous ? void 0 : { text, caret: start + low };
78
+ }
79
+ function markdownToPlainText(markdown) {
80
+ return markdown.replace(ENCODED_INDENT, (indent) => indent.replace(/&nbsp;/g, " ").replace(/&#9;/g, " ")).replace(/\\([!-/:-@[-`{-~\n])/g, "$1");
81
+ }
82
+ function isPlainMarkdown(markdown) {
83
+ const normalize = (html) => html.replace(/<br>\n/g, "\n").replace(/(^|>|\n)[\u00a0\t]+/g, "$1");
84
+ return normalize(parser.render(markdown)) === normalize(parser.render(plainTextToMarkdown(markdownToPlainText(markdown))));
85
+ }
86
+ const SELECTION_SYNTAX = /\\[!-/:-@[-`{-~]|[`*_[<~|]|&(?=#?[a-z0-9]+;)/gi;
87
+ function escapeSyntax(text, startsLine) {
88
+ return text.split("\n").map((line, index) => {
89
+ const escaped = line.replace(
90
+ SELECTION_SYNTAX,
91
+ (part) => part.length === 2 ? part : `\\${part}`
92
+ );
93
+ if (index === 0 && !startsLine) return escaped;
94
+ return escaped.replace(
95
+ BLOCK_SYNTAX,
96
+ (_, indent, marker, number, delimiter) => marker === void 0 ? `${number}\\${delimiter}` : `${indent}\\${marker}`
97
+ );
98
+ }).join("\n");
99
+ }
100
+ function isSelectionEscaped(value, selectionStart, selectionEnd) {
101
+ const selectedText = value.slice(selectionStart, selectionEnd);
102
+ const startsLine = selectionStart === 0 || value[selectionStart - 1] === "\n";
103
+ return ESCAPE_PATTERN.test(selectedText) && escapeSyntax(selectedText, startsLine) === selectedText;
104
+ }
105
+ function isEscaped(value, index) {
106
+ let backslashes = 0;
107
+ while (index > 0 && value[--index] === "\\") backslashes++;
108
+ return backslashes % 2 === 1;
109
+ }
110
+ function formatMarkdownSelection(value, selectionStart, selectionEnd, format) {
111
+ var _a, _b;
112
+ if (format.type === "link") {
113
+ const textPlaceholder = (_a = format.textPlaceholder) != null ? _a : LINK_PLACEHOLDER_TEXT;
114
+ const urlPlaceholder = (_b = format.urlPlaceholder) != null ? _b : LINK_PLACEHOLDER_URL;
115
+ const link = findLinkAt(value, selectionStart, selectionEnd, urlPlaceholder);
116
+ if (link) {
117
+ return {
118
+ value: `${value.slice(0, link.start)}${link.text}${value.slice(link.end)}`,
119
+ selectionStart: link.start,
120
+ selectionEnd: link.start + link.text.length
121
+ };
122
+ }
123
+ const selectedText = value.slice(selectionStart, selectionEnd);
124
+ const textStart = selectionStart + 1;
125
+ if (/^(https?:\/\/|mailto:)\S+$/i.test(selectedText)) {
126
+ return {
127
+ value: `${value.slice(0, selectionStart)}[${textPlaceholder}](${selectedText})${value.slice(selectionEnd)}`,
128
+ selectionStart: textStart,
129
+ selectionEnd: textStart + textPlaceholder.length
130
+ };
131
+ }
132
+ const text = selectedText || textPlaceholder;
133
+ const urlStart = textStart + text.length + 2;
134
+ return {
135
+ value: `${value.slice(0, selectionStart)}[${text}](${urlPlaceholder})${value.slice(selectionEnd)}`,
136
+ selectionStart: selectedText ? urlStart : textStart,
137
+ selectionEnd: selectedText ? urlStart + urlPlaceholder.length : textStart + text.length
138
+ };
139
+ }
140
+ if (format.type === "escape") {
141
+ const selectedText = value.slice(selectionStart, selectionEnd);
142
+ const startsLine = selectionStart === 0 || value[selectionStart - 1] === "\n";
143
+ const replacement2 = isSelectionEscaped(value, selectionStart, selectionEnd) ? unescapeMarkdown(selectedText) : escapeSyntax(selectedText, startsLine);
144
+ return {
145
+ value: `${value.slice(0, selectionStart)}${replacement2}${value.slice(selectionEnd)}`,
146
+ selectionStart,
147
+ selectionEnd: selectionStart + replacement2.length
148
+ };
149
+ }
150
+ if (format.type === "wrap") {
151
+ const selectedText = value.slice(selectionStart, selectionEnd);
152
+ const markerStart = selectionStart - format.marker.length;
153
+ const isAlreadyWrapped = isMarkdownFormatActive(value, selectionStart, selectionEnd, format);
154
+ if (isAlreadyWrapped) {
155
+ return {
156
+ value: `${value.slice(0, markerStart)}${selectedText}${value.slice(selectionEnd + format.marker.length)}`,
157
+ selectionStart: markerStart,
158
+ selectionEnd: markerStart + selectedText.length
159
+ };
160
+ }
161
+ const replacement2 = `${format.marker}${selectedText}${format.marker}`;
162
+ const innerStart = selectionStart + format.marker.length;
163
+ return {
164
+ value: `${value.slice(0, selectionStart)}${replacement2}${value.slice(selectionEnd)}`,
165
+ selectionStart: innerStart,
166
+ selectionEnd: innerStart + selectedText.length
167
+ };
168
+ }
169
+ const previousNewline = selectionStart > 0 ? value.lastIndexOf("\n", selectionStart - 1) : -1;
170
+ const lineStart = previousNewline + 1;
171
+ const selectedEnd = selectionEnd > selectionStart && value[selectionEnd - 1] === "\n" ? selectionEnd - 1 : selectionEnd;
172
+ const lineEndIndex = value.indexOf("\n", selectedEnd);
173
+ const lineEnd = lineEndIndex === -1 ? value.length : lineEndIndex;
174
+ const selectedLines = value.slice(lineStart, lineEnd).split("\n");
175
+ const removePrefix = format.toggle && isMarkdownFormatActive(value, selectionStart, selectionEnd, format);
176
+ const formattedLines = selectedLines.map((line) => {
177
+ if (removePrefix) return line.slice(format.prefix.length);
178
+ if (format.prefix.startsWith("#")) return `${format.prefix}${line.replace(/^#{1,6}\s+/, "")}`;
179
+ return `${format.prefix}${line}`;
180
+ });
181
+ const replacement = formattedLines.join("\n");
182
+ return {
183
+ value: `${value.slice(0, lineStart)}${replacement}${value.slice(lineEnd)}`,
184
+ selectionStart: lineStart,
185
+ selectionEnd: lineStart + replacement.length
186
+ };
187
+ }
188
+ function isMarkdownFormatActive(value, selectionStart, selectionEnd, format) {
189
+ if (format.type === "link") {
190
+ return findLinkAt(value, selectionStart, selectionEnd, format.urlPlaceholder) !== void 0;
191
+ }
192
+ if (format.type === "escape") return isSelectionEscaped(value, selectionStart, selectionEnd);
193
+ if (format.type === "wrap") {
194
+ const character = format.marker[0];
195
+ let start = selectionStart;
196
+ let end = selectionEnd;
197
+ while (start > 0 && value[start - 1] === character && !isEscaped(value, start - 1)) start--;
198
+ while (end < value.length && value[end] === character && !isEscaped(value, end)) end++;
199
+ const markerCount = Math.min(selectionStart - start, end - selectionEnd);
200
+ return format.marker.length === 1 ? markerCount % 2 === 1 : markerCount >= 2;
201
+ }
202
+ const previousNewline = selectionStart > 0 ? value.lastIndexOf("\n", selectionStart - 1) : -1;
203
+ const lineStart = previousNewline + 1;
204
+ const selectedEnd = selectionEnd > selectionStart && value[selectionEnd - 1] === "\n" ? selectionEnd - 1 : selectionEnd;
205
+ const lineEndIndex = value.indexOf("\n", selectedEnd);
206
+ const lineEnd = lineEndIndex === -1 ? value.length : lineEndIndex;
207
+ const lines = value.slice(lineStart, lineEnd).split("\n");
208
+ if (format.prefix.startsWith("#")) {
209
+ return lines.every((line) => {
210
+ var _a;
211
+ return ((_a = /^(#{1,6}\s+)/.exec(line)) == null ? void 0 : _a[0]) === format.prefix;
212
+ });
213
+ }
214
+ return lines.every((line) => line.startsWith(format.prefix));
215
+ }
216
+ function getAttr(token, name) {
217
+ const value = token.attrGet(name);
218
+ return value === null ? void 0 : String(value);
219
+ }
220
+ function toStyle(style) {
221
+ var _a;
222
+ const align = style && ((_a = /^text-align:\s*(left|right|center)$/.exec(style)) == null ? void 0 : _a[1]);
223
+ return align ? { textAlign: align } : void 0;
224
+ }
225
+ function renderLeaf(token, key, options) {
226
+ var _a, _b;
227
+ switch (token.type) {
228
+ case "text":
229
+ return token.content;
230
+ case "softbreak":
231
+ return "\n";
232
+ case "hardbreak":
233
+ return /* @__PURE__ */ jsx("br", {}, key);
234
+ case "code_inline":
235
+ return /* @__PURE__ */ jsx("code", { children: token.content }, key);
236
+ case "code_block":
237
+ return /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: token.content }) }, key);
238
+ case "fence": {
239
+ const language = token.info.trim().split(/\s+/)[0];
240
+ return /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { className: language ? `language-${language}` : void 0, children: token.content }) }, key);
241
+ }
242
+ case "hr":
243
+ return /* @__PURE__ */ jsx("hr", {}, key);
244
+ case "image":
245
+ return parser.renderer.renderInlineAsText((_a = token.children) != null ? _a : [], parser.options, {});
246
+ case "inline":
247
+ return renderTokens((_b = token.children) != null ? _b : [], options);
248
+ default:
249
+ return token.content || null;
250
+ }
251
+ }
252
+ function renderElement(open, children, key, options) {
253
+ var _a;
254
+ if (open.hidden) return /* @__PURE__ */ jsx(React.Fragment, { children }, key);
255
+ if (/^h[1-6]$/.test(open.tag)) {
256
+ const level = Math.min(6, Math.max(1, Number(open.tag[1]) + ((_a = options.headingOffset) != null ? _a : 0)));
257
+ return React.createElement(`h${level}`, { key }, children);
258
+ }
259
+ if (open.tag === "a") {
260
+ const href = getAttr(open, "href");
261
+ const newTab = options.openLinksInNewTab && !/^(mailto|tel):/i.test(href != null ? href : "");
262
+ return /* @__PURE__ */ jsxs(
263
+ "a",
264
+ {
265
+ href,
266
+ title: getAttr(open, "title"),
267
+ target: newTab ? "_blank" : void 0,
268
+ rel: newTab ? "noopener noreferrer" : void 0,
269
+ children: [
270
+ children,
271
+ newTab && options.newTabHint
272
+ ]
273
+ },
274
+ key
275
+ );
276
+ }
277
+ if (open.tag === "ol") {
278
+ const start = getAttr(open, "start");
279
+ return /* @__PURE__ */ jsx("ol", { start: start ? Number(start) : void 0, children }, key);
280
+ }
281
+ if (open.tag === "th" || open.tag === "td") {
282
+ return React.createElement(open.tag, { key, style: toStyle(getAttr(open, "style")) }, children);
283
+ }
284
+ return React.createElement(open.tag, { key }, children);
285
+ }
286
+ function renderTokens(tokens, options) {
287
+ const root = [];
288
+ const stack = [];
289
+ tokens.forEach((token, index) => {
290
+ const siblings = stack.length ? stack[stack.length - 1].children : root;
291
+ if (token.nesting === 1) {
292
+ stack.push({ open: token, children: [] });
293
+ } else if (token.nesting === -1) {
294
+ const element = stack.pop();
295
+ if (!element) return;
296
+ const parent = stack.length ? stack[stack.length - 1].children : root;
297
+ parent.push(renderElement(element.open, element.children, index, options));
298
+ } else {
299
+ const leaf = renderLeaf(token, index, options);
300
+ if (Array.isArray(leaf)) siblings.push(/* @__PURE__ */ jsx(React.Fragment, { children: leaf }, index));
301
+ else if (leaf !== null) siblings.push(leaf);
302
+ }
303
+ });
304
+ return root;
305
+ }
306
+ function renderMarkdown(value, options = {}) {
307
+ return renderTokens(parser.parse(value, {}), options);
308
+ }
309
+
310
+ export { escapeMarkdown, formatMarkdownSelection, getSafeHref, isMarkdownFormatActive, isPlainMarkdown, limitPlainText, markdownToPlainText, plainTextToMarkdown, renderMarkdown };
@@ -111,9 +111,9 @@ function Listbox({
111
111
  ].filter(Boolean).join(" "),
112
112
  disabled: option.disabled,
113
113
  onFocus: () => setActiveValue(option.value),
114
- onClick: () => {
114
+ onClick: (event) => {
115
115
  setActiveValue(option.value);
116
- onOptionSelect(option.value);
116
+ onOptionSelect(option.value, event);
117
117
  },
118
118
  children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.optionContent, children: [
119
119
  option.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.icon, "aria-hidden": "true", children: option.icon }) : null,
@@ -1,4 +1,4 @@
1
- import { type HTMLAttributes, type ReactNode } from 'react';
1
+ import { type HTMLAttributes, type MouseEvent, type ReactNode } from 'react';
2
2
  export type ListboxOption<T extends string | number = string> = {
3
3
  value: T;
4
4
  label: ReactNode;
@@ -15,7 +15,7 @@ export type ListboxProps<T extends string | number = string> = Omit<HTMLAttribut
15
15
  selectedValues: readonly T[];
16
16
  selectionMode?: 'single' | 'multiple';
17
17
  autoFocusValue?: T;
18
- onOptionSelect: (value: T) => void;
18
+ onOptionSelect: (value: T, event: MouseEvent<HTMLButtonElement>) => void;
19
19
  onActiveChange?: (value: T) => void;
20
20
  renderAction?: (option: ListboxOption<T>, selected: boolean) => ReactNode;
21
21
  };
@@ -104,9 +104,9 @@ function Listbox({
104
104
  ].filter(Boolean).join(" "),
105
105
  disabled: option.disabled,
106
106
  onFocus: () => setActiveValue(option.value),
107
- onClick: () => {
107
+ onClick: (event) => {
108
108
  setActiveValue(option.value);
109
- onOptionSelect(option.value);
109
+ onOptionSelect(option.value, event);
110
110
  },
111
111
  children: /* @__PURE__ */ jsxs("span", { className: styles.optionContent, children: [
112
112
  option.icon ? /* @__PURE__ */ jsx("span", { className: styles.icon, "aria-hidden": "true", children: option.icon }) : null,
@@ -8,12 +8,12 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
8
 
9
9
  var styles__default = /*#__PURE__*/_interopDefault(styles);
10
10
 
11
- function MetaBar({ items, separator = "\u2022" }) {
11
+ function MetaBar({ items, separator = "\u2022", size = "sm" }) {
12
12
  const visibleItems = items.filter(
13
13
  (item) => item.value !== null && item.value !== void 0 && item.value !== ""
14
14
  );
15
15
  if (visibleItems.length === 0) return null;
16
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.meta, children: visibleItems.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
16
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${styles__default.default.meta} ${styles__default.default[size]}`, children: visibleItems.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
17
17
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: item.muted === false ? styles__default.default.itemDefault : styles__default.default.itemMuted, children: [
18
18
  item.label && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
19
19
  item.label,
@@ -6,7 +6,8 @@ export interface MetaItem {
6
6
  }
7
7
  interface MetaBarProps {
8
8
  items: MetaItem[];
9
+ size?: 'sm' | 'md';
9
10
  separator?: ReactNode;
10
11
  }
11
- export declare function MetaBar({ items, separator }: MetaBarProps): JSX.Element | null;
12
+ export declare function MetaBar({ items, separator, size }: MetaBarProps): JSX.Element | null;
12
13
  export {};
@@ -2,12 +2,12 @@ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { Fragment } from 'react';
3
3
  import styles from './MetaBar.module.css';
4
4
 
5
- function MetaBar({ items, separator = "\u2022" }) {
5
+ function MetaBar({ items, separator = "\u2022", size = "sm" }) {
6
6
  const visibleItems = items.filter(
7
7
  (item) => item.value !== null && item.value !== void 0 && item.value !== ""
8
8
  );
9
9
  if (visibleItems.length === 0) return null;
10
- return /* @__PURE__ */ jsx("div", { className: styles.meta, children: visibleItems.map((item, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
10
+ return /* @__PURE__ */ jsx("div", { className: `${styles.meta} ${styles[size]}`, children: visibleItems.map((item, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
11
11
  /* @__PURE__ */ jsxs("span", { className: item.muted === false ? styles.itemDefault : styles.itemMuted, children: [
12
12
  item.label && /* @__PURE__ */ jsxs("span", { children: [
13
13
  item.label,
@@ -3,9 +3,16 @@
3
3
  flex-wrap: wrap;
4
4
  align-items: center;
5
5
  gap: var(--spacing-xs);
6
+ }
7
+
8
+ .sm {
6
9
  font-size: var(--font-size-xs);
7
10
  }
8
11
 
12
+ .md {
13
+ font-size: var(--font-size-sm);
14
+ }
15
+
9
16
  .itemMuted,
10
17
  .itemDefault {
11
18
  display: inline-flex;
@@ -18,7 +18,8 @@ export type NavBarLinkItem = NavBarBase & {
18
18
  active?: boolean;
19
19
  external?: boolean;
20
20
  };
21
- /** Clickable + expandable item (has href AND children) */
21
+ /** Expandable container. In Sidebar, href is a stable expansion key, not a destination.
22
+ * Legacy component/active/external props are accepted but ignored by Sidebar groups. */
22
23
  export type NavBarExpandableItem = NavBarBase & {
23
24
  type: 'expandable';
24
25
  href: string;
@@ -64,10 +64,18 @@ function shallowEqualActive(a, b) {
64
64
  function TooltipProvider({ children }) {
65
65
  const [active, setActive] = react.useState(null);
66
66
  const showTimerRef = react.useRef(null);
67
+ const pendingIdRef = react.useRef(null);
68
+ react.useEffect(() => {
69
+ return () => {
70
+ if (showTimerRef.current) clearTimeout(showTimerRef.current);
71
+ };
72
+ }, []);
67
73
  const show = react.useCallback((next) => {
68
74
  if (showTimerRef.current) clearTimeout(showTimerRef.current);
75
+ pendingIdRef.current = next.id;
69
76
  showTimerRef.current = setTimeout(() => {
70
77
  showTimerRef.current = null;
78
+ pendingIdRef.current = null;
71
79
  setActive((curr) => {
72
80
  const proposed = { ...next, open: true };
73
81
  return shallowEqualActive(curr, proposed) ? curr : proposed;
@@ -75,9 +83,10 @@ function TooltipProvider({ children }) {
75
83
  }, SHOW_DELAY_MS);
76
84
  }, []);
77
85
  const hide = react.useCallback((id) => {
78
- if (showTimerRef.current) {
86
+ if (showTimerRef.current && pendingIdRef.current === id) {
79
87
  clearTimeout(showTimerRef.current);
80
88
  showTimerRef.current = null;
89
+ pendingIdRef.current = null;
81
90
  }
82
91
  setActive((curr) => {
83
92
  if (!curr || curr.id !== id) return curr;
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { createContext, useState, useRef, useCallback, useMemo, useContext, useEffect, useLayoutEffect } from 'react';
3
+ import { createContext, useState, useRef, useEffect, useCallback, useMemo, useContext, useLayoutEffect } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
5
  import styles from './Tooltip.module.css';
6
6
 
@@ -58,10 +58,18 @@ function shallowEqualActive(a, b) {
58
58
  function TooltipProvider({ children }) {
59
59
  const [active, setActive] = useState(null);
60
60
  const showTimerRef = useRef(null);
61
+ const pendingIdRef = useRef(null);
62
+ useEffect(() => {
63
+ return () => {
64
+ if (showTimerRef.current) clearTimeout(showTimerRef.current);
65
+ };
66
+ }, []);
61
67
  const show = useCallback((next) => {
62
68
  if (showTimerRef.current) clearTimeout(showTimerRef.current);
69
+ pendingIdRef.current = next.id;
63
70
  showTimerRef.current = setTimeout(() => {
64
71
  showTimerRef.current = null;
72
+ pendingIdRef.current = null;
65
73
  setActive((curr) => {
66
74
  const proposed = { ...next, open: true };
67
75
  return shallowEqualActive(curr, proposed) ? curr : proposed;
@@ -69,9 +77,10 @@ function TooltipProvider({ children }) {
69
77
  }, SHOW_DELAY_MS);
70
78
  }, []);
71
79
  const hide = useCallback((id) => {
72
- if (showTimerRef.current) {
80
+ if (showTimerRef.current && pendingIdRef.current === id) {
73
81
  clearTimeout(showTimerRef.current);
74
82
  showTimerRef.current = null;
83
+ pendingIdRef.current = null;
75
84
  }
76
85
  setActive((curr) => {
77
86
  if (!curr || curr.id !== id) return curr;
@@ -26,12 +26,19 @@ function useTooltipTrigger(options) {
26
26
  const openTimer = react.useRef(null);
27
27
  const closeTimer = react.useRef(null);
28
28
  const openedByFocusRef = react.useRef(false);
29
- const clearTimers = () => {
29
+ const clearTimers = react.useCallback(() => {
30
30
  if (openTimer.current) window.clearTimeout(openTimer.current);
31
31
  if (closeTimer.current) window.clearTimeout(closeTimer.current);
32
32
  openTimer.current = null;
33
33
  closeTimer.current = null;
34
- };
34
+ }, []);
35
+ const hideTooltip = ctx.hide;
36
+ react.useEffect(() => {
37
+ return () => {
38
+ clearTimers();
39
+ hideTooltip(id);
40
+ };
41
+ }, [clearTimers, hideTooltip, id]);
35
42
  const lastSentRef = react.useRef(null);
36
43
  const show = react.useCallback(() => {
37
44
  if (!content) return;
@@ -24,12 +24,19 @@ function useTooltipTrigger(options) {
24
24
  const openTimer = useRef(null);
25
25
  const closeTimer = useRef(null);
26
26
  const openedByFocusRef = useRef(false);
27
- const clearTimers = () => {
27
+ const clearTimers = useCallback(() => {
28
28
  if (openTimer.current) window.clearTimeout(openTimer.current);
29
29
  if (closeTimer.current) window.clearTimeout(closeTimer.current);
30
30
  openTimer.current = null;
31
31
  closeTimer.current = null;
32
- };
32
+ }, []);
33
+ const hideTooltip = ctx.hide;
34
+ useEffect(() => {
35
+ return () => {
36
+ clearTimers();
37
+ hideTooltip(id);
38
+ };
39
+ }, [clearTimers, hideTooltip, id]);
33
40
  const lastSentRef = useRef(null);
34
41
  const show = useCallback(() => {
35
42
  if (!content) return;
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  'use strict';
2
3
 
3
4
  var jsxRuntime = require('react/jsx-runtime');
@@ -19,7 +20,7 @@ function Sidebar({
19
20
  minWidth,
20
21
  storageKey
21
22
  }) {
22
- return /* @__PURE__ */ jsxRuntime.jsx(SidebarProvider.SidebarProvider, { items, children: /* @__PURE__ */ jsxRuntime.jsx(
23
+ return /* @__PURE__ */ jsxRuntime.jsx(SidebarProvider.SidebarProvider, { items, initialActiveLink: activeLink, children: /* @__PURE__ */ jsxRuntime.jsx(
23
24
  SidebarContainer.SidebarContainer,
24
25
  {
25
26
  productName,
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx } from 'react/jsx-runtime';
2
3
  import { SidebarContainer } from './components/sidebar-container/SidebarContainer';
3
4
  import { SidebarProvider } from './providers/SidebarProvider';
@@ -17,7 +18,7 @@ function Sidebar({
17
18
  minWidth,
18
19
  storageKey
19
20
  }) {
20
- return /* @__PURE__ */ jsx(SidebarProvider, { items, children: /* @__PURE__ */ jsx(
21
+ return /* @__PURE__ */ jsx(SidebarProvider, { items, initialActiveLink: activeLink, children: /* @__PURE__ */ jsx(
21
22
  SidebarContainer,
22
23
  {
23
24
  productName,
@@ -1,31 +1,52 @@
1
+ 'use client';
1
2
  'use strict';
2
3
 
3
4
  var jsxRuntime = require('react/jsx-runtime');
5
+ var styles = require('./SidebarItem.module.css');
6
+ var SidebarProvider = require('../providers/SidebarProvider');
4
7
  var SidebarItemContent = require('./sidebar-item-content/SidebarItemContent');
5
8
 
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var styles__default = /*#__PURE__*/_interopDefault(styles);
12
+
6
13
  function SidebarItem({
7
- component: Component,
14
+ component: Component = "a",
8
15
  label,
9
16
  icon,
10
17
  badge,
11
18
  href,
12
19
  iconWidth,
13
- truncateLabel
20
+ truncateLabel,
21
+ enabled = true,
22
+ external
14
23
  }) {
15
- if (!Component) {
16
- return null;
17
- }
18
- return /* @__PURE__ */ jsxRuntime.jsx(Component, { children: /* @__PURE__ */ jsxRuntime.jsx(
19
- SidebarItemContent.SidebarItemContent,
24
+ const { activeLink, isSidebarCollapsed } = SidebarProvider.useSidebar();
25
+ return /* @__PURE__ */ jsxRuntime.jsx(
26
+ Component,
20
27
  {
21
- icon,
22
- badge,
23
- iconWidth,
24
- label,
25
28
  href,
26
- truncateLabel
29
+ className: styles__default.default.link,
30
+ "aria-label": isSidebarCollapsed ? label : void 0,
31
+ "aria-current": enabled && activeLink === href ? "page" : void 0,
32
+ "aria-disabled": !enabled || void 0,
33
+ tabIndex: enabled ? void 0 : -1,
34
+ onClick: enabled ? void 0 : (event) => event.preventDefault(),
35
+ ...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
36
+ children: /* @__PURE__ */ jsxRuntime.jsx(
37
+ SidebarItemContent.SidebarItemContent,
38
+ {
39
+ icon,
40
+ badge,
41
+ iconWidth,
42
+ label,
43
+ href,
44
+ disableActiveStyles: !enabled,
45
+ truncateLabel
46
+ }
47
+ )
27
48
  }
28
- ) });
49
+ );
29
50
  }
30
51
 
31
52
  exports.SidebarItem = SidebarItem;
@@ -2,11 +2,13 @@ import React from 'react';
2
2
  interface SidebarItemProps {
3
3
  component?: React.ElementType;
4
4
  label: string;
5
- icon: React.ReactNode;
5
+ icon?: React.ReactNode;
6
6
  badge?: number | string;
7
7
  href?: string;
8
8
  iconWidth?: string | number;
9
+ enabled?: boolean;
10
+ external?: boolean;
9
11
  truncateLabel?: boolean;
10
12
  }
11
- export declare function SidebarItem({ component: Component, label, icon, badge, href, iconWidth, truncateLabel, }: SidebarItemProps): React.ReactNode;
13
+ export declare function SidebarItem({ component: Component, label, icon, badge, href, iconWidth, truncateLabel, enabled, external, }: SidebarItemProps): React.ReactNode;
12
14
  export {};