@hellboy/ds 0.1.2

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 (137) hide show
  1. package/README.md +111 -0
  2. package/dist/index.css +3699 -0
  3. package/dist/index.css.map +1 -0
  4. package/dist/index.d.mts +1087 -0
  5. package/dist/index.d.ts +1087 -0
  6. package/dist/index.js +3391 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/index.mjs +3287 -0
  9. package/dist/index.mjs.map +1 -0
  10. package/dist/theme.css +55 -0
  11. package/hellboy-ds-0.1.2.tgz +0 -0
  12. package/package.json +42 -0
  13. package/src/components/badge/Badge.tsx +29 -0
  14. package/src/components/badge/index.ts +1 -0
  15. package/src/components/banner/Banner.tsx +48 -0
  16. package/src/components/banner/banner.css +44 -0
  17. package/src/components/banner/index.ts +1 -0
  18. package/src/components/button/button.tsx +127 -0
  19. package/src/components/button/index.ts +1 -0
  20. package/src/components/card/card.tsx +57 -0
  21. package/src/components/card/index.ts +1 -0
  22. package/src/components/checkbox/Checkbox.tsx +98 -0
  23. package/src/components/checkbox/index.ts +1 -0
  24. package/src/components/code-block/code-block.tsx +44 -0
  25. package/src/components/code-block/index.ts +1 -0
  26. package/src/components/color-control/color-control.tsx +322 -0
  27. package/src/components/color-control/index.ts +1 -0
  28. package/src/components/drag-handle/DragHandle.tsx +78 -0
  29. package/src/components/drag-handle/index.ts +1 -0
  30. package/src/components/drawer/drawer.tsx +82 -0
  31. package/src/components/drawer/index.ts +1 -0
  32. package/src/components/floating-bar/floating-bar.tsx +52 -0
  33. package/src/components/floating-bar/index.ts +2 -0
  34. package/src/components/footer/footer.tsx +28 -0
  35. package/src/components/footer/index.ts +1 -0
  36. package/src/components/grid/Grid.tsx +53 -0
  37. package/src/components/grid/index.ts +1 -0
  38. package/src/components/header/header.tsx +57 -0
  39. package/src/components/header/index.ts +1 -0
  40. package/src/components/icons/icons.tsx +44 -0
  41. package/src/components/icons/index.ts +1 -0
  42. package/src/components/index.ts +29 -0
  43. package/src/components/input/DatePicker.tsx +133 -0
  44. package/src/components/input/Input.tsx +220 -0
  45. package/src/components/input/InputDate.tsx +10 -0
  46. package/src/components/input/InputDateTime.tsx +10 -0
  47. package/src/components/input/InputEmail.tsx +10 -0
  48. package/src/components/input/InputField.tsx +137 -0
  49. package/src/components/input/InputNumber.tsx +10 -0
  50. package/src/components/input/InputPassword.tsx +10 -0
  51. package/src/components/input/InputSearch.tsx +10 -0
  52. package/src/components/input/InputTel.tsx +10 -0
  53. package/src/components/input/InputText.tsx +10 -0
  54. package/src/components/input/InputTime.tsx +10 -0
  55. package/src/components/input/InputUrl.tsx +10 -0
  56. package/src/components/input/TimePicker.tsx +151 -0
  57. package/src/components/input/index.ts +11 -0
  58. package/src/components/layout/Layout.tsx +244 -0
  59. package/src/components/layout/index.ts +1 -0
  60. package/src/components/list/List.tsx +159 -0
  61. package/src/components/list/index.ts +1 -0
  62. package/src/components/navbar/MenuCategory.tsx +20 -0
  63. package/src/components/navbar/MenuGroup.tsx +288 -0
  64. package/src/components/navbar/MenuItem.tsx +65 -0
  65. package/src/components/navbar/Navbar.tsx +23 -0
  66. package/src/components/navbar/index.ts +4 -0
  67. package/src/components/page/index.ts +1 -0
  68. package/src/components/page/page.tsx +46 -0
  69. package/src/components/page-index/PageIndex.tsx +275 -0
  70. package/src/components/page-index/index.ts +1 -0
  71. package/src/components/popover/index.ts +1 -0
  72. package/src/components/popover/popover.tsx +199 -0
  73. package/src/components/radio/Radio.tsx +176 -0
  74. package/src/components/radio/index.ts +1 -0
  75. package/src/components/section/index.ts +1 -0
  76. package/src/components/section/section.tsx +66 -0
  77. package/src/components/select/Select.tsx +212 -0
  78. package/src/components/select/index.ts +1 -0
  79. package/src/components/slider/Slider.tsx +267 -0
  80. package/src/components/slider/index.ts +1 -0
  81. package/src/components/switch/index.ts +1 -0
  82. package/src/components/switch/switch.tsx +99 -0
  83. package/src/components/table/Table.tsx +147 -0
  84. package/src/components/table/index.ts +1 -0
  85. package/src/components/theme-control/index.ts +1 -0
  86. package/src/components/theme-control/theme-control.tsx +78 -0
  87. package/src/components/tooltip/index.ts +1 -0
  88. package/src/components/tooltip/tooltip.tsx +207 -0
  89. package/src/contexts/NavbarTooltipContext.tsx +48 -0
  90. package/src/contexts/index.ts +1 -0
  91. package/src/foundations/motion.md +136 -0
  92. package/src/index.ts +40 -0
  93. package/src/style/_shared/field.css +69 -0
  94. package/src/style/components/badge/badge.css +74 -0
  95. package/src/style/components/button/button.css +244 -0
  96. package/src/style/components/card/card.css +69 -0
  97. package/src/style/components/checkbox.css +142 -0
  98. package/src/style/components/code-block/code-block.css +34 -0
  99. package/src/style/components/color-control/color-control.css +126 -0
  100. package/src/style/components/drag-handle/drag-handle.css +68 -0
  101. package/src/style/components/drawer/drawer.css +210 -0
  102. package/src/style/components/floating-bar/floating-bar.css +39 -0
  103. package/src/style/components/footer/footer.css +108 -0
  104. package/src/style/components/grid/grid.css +33 -0
  105. package/src/style/components/header/header.css +44 -0
  106. package/src/style/components/icons/icons.css +44 -0
  107. package/src/style/components/input/input.css +393 -0
  108. package/src/style/components/layout/layout.css +205 -0
  109. package/src/style/components/list/list.css +140 -0
  110. package/src/style/components/navbar/navbar.css +342 -0
  111. package/src/style/components/page/page.css +46 -0
  112. package/src/style/components/page-index/page-index.css +158 -0
  113. package/src/style/components/popover/popover.css +44 -0
  114. package/src/style/components/radio.css +178 -0
  115. package/src/style/components/section/section.css +67 -0
  116. package/src/style/components/select/select.css +143 -0
  117. package/src/style/components/slider/slider.css +159 -0
  118. package/src/style/components/switch/switch.css +267 -0
  119. package/src/style/components/table/table.css +108 -0
  120. package/src/style/components/theme-control/theme-control.css +35 -0
  121. package/src/style/components/tooltip/tooltip.css +52 -0
  122. package/src/style/foundations/global.css +316 -0
  123. package/src/style/foundations/motion.css +164 -0
  124. package/src/style/foundations/spacing.css +51 -0
  125. package/src/style/foundations/typography.css +39 -0
  126. package/src/style/foundations/z-index.css +81 -0
  127. package/src/style/modes/dark.css +146 -0
  128. package/src/style/modes/light.css +147 -0
  129. package/src/style/semantic.css +52 -0
  130. package/src/style/styles.css +51 -0
  131. package/src/style/themes/theme.json +37 -0
  132. package/src/utils/README.md +305 -0
  133. package/src/utils/USER_PREFERENCES.md +558 -0
  134. package/src/utils/theme.ts +127 -0
  135. package/src/utils/user-preferences.ts +577 -0
  136. package/tsconfig.json +25 -0
  137. package/tsup.config.ts +52 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,3287 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+
5
+ // src/contexts/NavbarTooltipContext.tsx
6
+ import * as React from "react";
7
+ import { jsx } from "react/jsx-runtime";
8
+ var NavbarTooltipContext = React.createContext(void 0);
9
+ var NavbarTooltipProvider = ({ children }) => {
10
+ const [hasOpenPopover, setHasOpenPopover] = React.useState(false);
11
+ const [activePopoverId, setActivePopoverId] = React.useState(null);
12
+ const openPopover = React.useCallback((id) => {
13
+ setActivePopoverId(id);
14
+ setHasOpenPopover(true);
15
+ }, []);
16
+ const closePopover = React.useCallback((id) => {
17
+ if (activePopoverId === id) {
18
+ setActivePopoverId(null);
19
+ setHasOpenPopover(false);
20
+ }
21
+ }, [activePopoverId]);
22
+ return /* @__PURE__ */ jsx(NavbarTooltipContext.Provider, { value: {
23
+ hasOpenPopover,
24
+ setHasOpenPopover,
25
+ openPopover,
26
+ closePopover,
27
+ activePopoverId
28
+ }, children });
29
+ };
30
+ var useNavbarTooltip = () => {
31
+ const context = React.useContext(NavbarTooltipContext);
32
+ if (!context) {
33
+ throw new Error("useNavbarTooltip must be used within a NavbarTooltipProvider");
34
+ }
35
+ return context;
36
+ };
37
+
38
+ // src/components/button/button.tsx
39
+ import React2 from "react";
40
+ import { Button as AriakitButton } from "@ariakit/react";
41
+
42
+ // src/components/icons/icons.tsx
43
+ import { Icon as IconifyIcon } from "@iconify/react";
44
+ import { jsx as jsx2 } from "react/jsx-runtime";
45
+ var Icon = ({ name, size = 24, className, loading = false, ...rest }) => {
46
+ const iconName = name.startsWith("famicons:") ? name : `famicons:${name}`;
47
+ const classes = ["icon", className].filter(Boolean).join(" ");
48
+ if (loading) {
49
+ const style = { width: size, height: size };
50
+ return /* @__PURE__ */ jsx2(
51
+ "span",
52
+ {
53
+ className: `${classes} icon--skeleton`,
54
+ style,
55
+ "aria-hidden": rest["aria-label"] ? "false" : "true",
56
+ ...rest["aria-label"] ? { "aria-label": rest["aria-label"] } : {}
57
+ }
58
+ );
59
+ }
60
+ return /* @__PURE__ */ jsx2(
61
+ IconifyIcon,
62
+ {
63
+ icon: iconName,
64
+ width: size,
65
+ height: size,
66
+ className: classes,
67
+ ...rest
68
+ }
69
+ );
70
+ };
71
+
72
+ // src/components/button/button.tsx
73
+ import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
74
+ var Button = React2.forwardRef(
75
+ ({
76
+ variant = "primary",
77
+ size = "md",
78
+ children,
79
+ isLoading = false,
80
+ disabled = false,
81
+ fullWidth = false,
82
+ startIcon,
83
+ endIcon,
84
+ iconOnly = false,
85
+ href,
86
+ className,
87
+ onClick,
88
+ ...props
89
+ }, ref) => {
90
+ const buttonClasses = [
91
+ "btn",
92
+ `btn--${variant}`,
93
+ `btn--${size}`,
94
+ fullWidth && "btn--full-width",
95
+ iconOnly && "btn--icon-only",
96
+ className
97
+ ].filter(Boolean).join(" ");
98
+ const iconSize = size === "xs" ? 14 : size === "sm" ? 16 : size === "lg" ? 24 : 20;
99
+ const buttonContent = /* @__PURE__ */ jsxs(Fragment, { children: [
100
+ isLoading && /* @__PURE__ */ jsx3("span", { className: "btn__spinner" }),
101
+ startIcon && (isLoading ? /* @__PURE__ */ jsx3("span", { className: "btn__icon-placeholder", style: { width: iconSize, height: iconSize } }) : /* @__PURE__ */ jsx3(Icon, { name: startIcon, size: iconSize, className: "btn__icon" })),
102
+ !iconOnly && children,
103
+ endIcon && /* @__PURE__ */ jsx3(Icon, { name: endIcon, size: iconSize, className: "btn__icon" })
104
+ ] });
105
+ const handleClick = (e) => {
106
+ if (href && !isLoading && !disabled) {
107
+ window.location.href = href;
108
+ }
109
+ onClick?.(e);
110
+ };
111
+ return /* @__PURE__ */ jsx3(
112
+ AriakitButton,
113
+ {
114
+ ref,
115
+ disabled: disabled || isLoading,
116
+ className: buttonClasses,
117
+ onClick: handleClick,
118
+ ...props,
119
+ children: buttonContent
120
+ }
121
+ );
122
+ }
123
+ );
124
+ Button.displayName = "Button";
125
+
126
+ // src/components/badge/Badge.tsx
127
+ import { jsx as jsx4 } from "react/jsx-runtime";
128
+ var Badge = ({
129
+ variant = "primary",
130
+ size = "md",
131
+ className = "",
132
+ children,
133
+ ...props
134
+ }) => {
135
+ const classes = ["badge", `badge--${variant}`, `badge--${size}`, className].filter(Boolean).join(" ");
136
+ return /* @__PURE__ */ jsx4("span", { className: classes, ...props, children });
137
+ };
138
+
139
+ // src/components/checkbox/Checkbox.tsx
140
+ import React3 from "react";
141
+ import { Checkbox as AriakitCheckbox } from "@ariakit/react";
142
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
143
+ var Checkbox = React3.forwardRef(
144
+ ({
145
+ size = "md",
146
+ label,
147
+ error,
148
+ helperText,
149
+ indeterminate = false,
150
+ disabled = false,
151
+ className,
152
+ checked,
153
+ ...props
154
+ }, ref) => {
155
+ const checkboxClasses = [
156
+ "checkbox",
157
+ `checkbox--${size}`,
158
+ error && "checkbox--error",
159
+ disabled && "checkbox--disabled",
160
+ className
161
+ ].filter(Boolean).join(" ");
162
+ const iconSize = size === "sm" ? 14 : size === "lg" ? 20 : 16;
163
+ const isChecked = checked === true;
164
+ const isIndeterminate = indeterminate && !isChecked;
165
+ return /* @__PURE__ */ jsxs2("div", { className: checkboxClasses, children: [
166
+ /* @__PURE__ */ jsxs2("label", { className: "checkbox__container", children: [
167
+ /* @__PURE__ */ jsx5(
168
+ AriakitCheckbox,
169
+ {
170
+ ref,
171
+ checked,
172
+ disabled,
173
+ className: "checkbox__input",
174
+ ...props
175
+ }
176
+ ),
177
+ /* @__PURE__ */ jsxs2("span", { className: "checkbox__box", children: [
178
+ isChecked && /* @__PURE__ */ jsx5(Icon, { name: "checkmark-sharp", size: iconSize, className: "checkbox__icon" }),
179
+ isIndeterminate && /* @__PURE__ */ jsx5(Icon, { name: "minus", size: iconSize, className: "checkbox__icon" })
180
+ ] }),
181
+ label && /* @__PURE__ */ jsx5("span", { className: "checkbox__label", children: label })
182
+ ] }),
183
+ (error || helperText) && /* @__PURE__ */ jsxs2("div", { className: "checkbox__feedback", children: [
184
+ error && /* @__PURE__ */ jsx5("span", { className: "checkbox__error-text", children: error }),
185
+ !error && helperText && /* @__PURE__ */ jsx5("span", { className: "checkbox__helper-text", children: helperText })
186
+ ] })
187
+ ] });
188
+ }
189
+ );
190
+ Checkbox.displayName = "Checkbox";
191
+
192
+ // src/components/switch/switch.tsx
193
+ import React4 from "react";
194
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
195
+ var Switch = React4.forwardRef(
196
+ ({
197
+ size = "md",
198
+ label,
199
+ onIcon,
200
+ offIcon,
201
+ error,
202
+ helperText,
203
+ disabled = false,
204
+ className,
205
+ checked,
206
+ ...props
207
+ }, ref) => {
208
+ const switchClasses = [
209
+ "switch",
210
+ `switch--${size}`,
211
+ checked && "switch--checked",
212
+ disabled && "switch--disabled",
213
+ error && "switch--error",
214
+ className
215
+ ].filter(Boolean).join(" ");
216
+ return /* @__PURE__ */ jsxs3("div", { className: "switch__wrapper", children: [
217
+ /* @__PURE__ */ jsxs3("label", { className: "switch__label", children: [
218
+ /* @__PURE__ */ jsx6(
219
+ "input",
220
+ {
221
+ type: "checkbox",
222
+ ref,
223
+ checked,
224
+ disabled,
225
+ className: "switch__input",
226
+ ...props
227
+ }
228
+ ),
229
+ /* @__PURE__ */ jsx6("span", { className: switchClasses, children: /* @__PURE__ */ jsx6("span", { className: "switch__track", children: /* @__PURE__ */ jsxs3("span", { className: "switch__thumb", children: [
230
+ onIcon && /* @__PURE__ */ jsx6(Icon, { name: onIcon, size: 16, className: "switch__icon switch__icon--on" }),
231
+ offIcon && /* @__PURE__ */ jsx6(Icon, { name: offIcon, size: 16, className: "switch__icon switch__icon--off" })
232
+ ] }) }) }),
233
+ label && /* @__PURE__ */ jsx6("span", { className: "switch__text", children: label })
234
+ ] }),
235
+ (error || helperText) && /* @__PURE__ */ jsxs3("div", { className: "switch__message", children: [
236
+ error && /* @__PURE__ */ jsx6("span", { className: "switch__error-text", children: error }),
237
+ helperText && !error && /* @__PURE__ */ jsx6("span", { className: "switch__helper-text", children: helperText })
238
+ ] })
239
+ ] });
240
+ }
241
+ );
242
+ Switch.displayName = "Switch";
243
+
244
+ // src/components/layout/Layout.tsx
245
+ import * as React6 from "react";
246
+
247
+ // src/components/drag-handle/DragHandle.tsx
248
+ import React5, { useState as useState2, useRef, useCallback as useCallback2 } from "react";
249
+ import { jsx as jsx7 } from "react/jsx-runtime";
250
+ var DragHandle = ({
251
+ onResize,
252
+ onResizeEnd,
253
+ orientation = "vertical",
254
+ className = ""
255
+ }) => {
256
+ const [isDragging, setIsDragging] = useState2(false);
257
+ const dragHandleRef = useRef(null);
258
+ const startPosRef = useRef(0);
259
+ const handleMouseDown = useCallback2((e) => {
260
+ setIsDragging(true);
261
+ startPosRef.current = orientation === "vertical" ? e.clientX : e.clientY;
262
+ e.preventDefault();
263
+ }, [orientation]);
264
+ const handleMouseMove = useCallback2((e) => {
265
+ if (!isDragging) return;
266
+ const currentPos = orientation === "vertical" ? e.clientX : e.clientY;
267
+ const delta = currentPos - startPosRef.current;
268
+ onResize(delta);
269
+ startPosRef.current = currentPos;
270
+ }, [isDragging, onResize, orientation]);
271
+ const handleMouseUp = useCallback2(() => {
272
+ setIsDragging(false);
273
+ onResizeEnd?.();
274
+ }, [onResizeEnd]);
275
+ React5.useEffect(() => {
276
+ if (isDragging) {
277
+ document.addEventListener("mousemove", handleMouseMove);
278
+ document.addEventListener("mouseup", handleMouseUp);
279
+ document.body.style.cursor = orientation === "vertical" ? "col-resize" : "row-resize";
280
+ document.body.style.userSelect = "none";
281
+ } else {
282
+ document.removeEventListener("mousemove", handleMouseMove);
283
+ document.removeEventListener("mouseup", handleMouseUp);
284
+ document.body.style.cursor = "";
285
+ document.body.style.userSelect = "";
286
+ }
287
+ return () => {
288
+ document.removeEventListener("mousemove", handleMouseMove);
289
+ document.removeEventListener("mouseup", handleMouseUp);
290
+ document.body.style.cursor = "";
291
+ document.body.style.userSelect = "";
292
+ };
293
+ }, [isDragging, handleMouseMove, handleMouseUp, orientation]);
294
+ const classes = [
295
+ "drag-handle",
296
+ `drag-handle--${orientation}`,
297
+ isDragging && "drag-handle--dragging",
298
+ className
299
+ ].filter(Boolean).join(" ");
300
+ return /* @__PURE__ */ jsx7(
301
+ "div",
302
+ {
303
+ ref: dragHandleRef,
304
+ className: classes,
305
+ onMouseDown: handleMouseDown,
306
+ children: /* @__PURE__ */ jsx7("div", { className: "drag-handle__indicator" })
307
+ }
308
+ );
309
+ };
310
+
311
+ // src/utils/user-preferences.ts
312
+ var DEFAULT_CONFIG = {
313
+ backend: "localStorage",
314
+ prefix: "hellboy-ds",
315
+ dbName: "hellboy-ds-prefs",
316
+ storeName: "preferences"
317
+ };
318
+ var config = { ...DEFAULT_CONFIG };
319
+ var configurePreferences = (userConfig) => {
320
+ config = { ...config, ...userConfig };
321
+ };
322
+ var getStorageKey = (key) => {
323
+ return `${config.prefix}:${key}`;
324
+ };
325
+ var isLocalStorageAvailable = () => {
326
+ try {
327
+ const test = "__storage_test__";
328
+ localStorage.setItem(test, test);
329
+ localStorage.removeItem(test);
330
+ return true;
331
+ } catch {
332
+ return false;
333
+ }
334
+ };
335
+ var IndexedDBStore = class {
336
+ constructor() {
337
+ __publicField(this, "db", null);
338
+ }
339
+ async init() {
340
+ if (typeof window === "undefined" || !window.indexedDB) {
341
+ throw new Error("IndexedDB not available");
342
+ }
343
+ return new Promise((resolve, reject) => {
344
+ const request = indexedDB.open(config.dbName, 1);
345
+ request.onerror = () => reject(request.error);
346
+ request.onsuccess = () => {
347
+ this.db = request.result;
348
+ resolve();
349
+ };
350
+ request.onupgradeneeded = (event) => {
351
+ const db = event.target.result;
352
+ if (!db.objectStoreNames.contains(config.storeName)) {
353
+ db.createObjectStore(config.storeName, { keyPath: "key" });
354
+ }
355
+ };
356
+ });
357
+ }
358
+ async get(key) {
359
+ if (!this.db) await this.init();
360
+ return new Promise((resolve, reject) => {
361
+ const transaction = this.db.transaction([config.storeName], "readonly");
362
+ const store = transaction.objectStore(config.storeName);
363
+ const request = store.get(key);
364
+ request.onsuccess = () => resolve(request.result?.value);
365
+ request.onerror = () => reject(request.error);
366
+ });
367
+ }
368
+ async set(key, value) {
369
+ if (!this.db) await this.init();
370
+ return new Promise((resolve, reject) => {
371
+ const transaction = this.db.transaction([config.storeName], "readwrite");
372
+ const store = transaction.objectStore(config.storeName);
373
+ const request = store.put({ key, value });
374
+ request.onsuccess = () => resolve();
375
+ request.onerror = () => reject(request.error);
376
+ });
377
+ }
378
+ async remove(key) {
379
+ if (!this.db) await this.init();
380
+ return new Promise((resolve, reject) => {
381
+ const transaction = this.db.transaction([config.storeName], "readwrite");
382
+ const store = transaction.objectStore(config.storeName);
383
+ const request = store.delete(key);
384
+ request.onsuccess = () => resolve();
385
+ request.onerror = () => reject(request.error);
386
+ });
387
+ }
388
+ async clear() {
389
+ if (!this.db) await this.init();
390
+ return new Promise((resolve, reject) => {
391
+ const transaction = this.db.transaction([config.storeName], "readwrite");
392
+ const store = transaction.objectStore(config.storeName);
393
+ const request = store.clear();
394
+ request.onsuccess = () => resolve();
395
+ request.onerror = () => reject(request.error);
396
+ });
397
+ }
398
+ };
399
+ var indexedDBStore = new IndexedDBStore();
400
+ var getPreference = (key, defaultValue) => {
401
+ try {
402
+ if (config.backend === "localStorage" && isLocalStorageAvailable()) {
403
+ const stored = localStorage.getItem(getStorageKey(key));
404
+ if (stored !== null) {
405
+ return JSON.parse(stored);
406
+ }
407
+ }
408
+ return defaultValue;
409
+ } catch (error) {
410
+ console.warn(`Failed to get preference "${key}":`, error);
411
+ return defaultValue;
412
+ }
413
+ };
414
+ var getPreferenceAsync = async (key, defaultValue) => {
415
+ try {
416
+ if (config.backend === "indexedDB") {
417
+ const value = await indexedDBStore.get(getStorageKey(key));
418
+ return value !== void 0 ? value : defaultValue;
419
+ }
420
+ return getPreference(key, defaultValue);
421
+ } catch (error) {
422
+ console.warn(`Failed to get preference "${key}":`, error);
423
+ return defaultValue;
424
+ }
425
+ };
426
+ var setPreference = (key, value) => {
427
+ try {
428
+ if (config.backend === "localStorage" && isLocalStorageAvailable()) {
429
+ localStorage.setItem(getStorageKey(key), JSON.stringify(value));
430
+ }
431
+ } catch (error) {
432
+ console.warn(`Failed to set preference "${key}":`, error);
433
+ }
434
+ };
435
+ var setPreferenceAsync = async (key, value) => {
436
+ try {
437
+ if (config.backend === "indexedDB") {
438
+ await indexedDBStore.set(getStorageKey(key), value);
439
+ } else {
440
+ setPreference(key, value);
441
+ }
442
+ } catch (error) {
443
+ console.warn(`Failed to set preference "${key}":`, error);
444
+ }
445
+ };
446
+ var removePreference = (key) => {
447
+ try {
448
+ if (config.backend === "localStorage" && isLocalStorageAvailable()) {
449
+ localStorage.removeItem(getStorageKey(key));
450
+ }
451
+ } catch (error) {
452
+ console.warn(`Failed to remove preference "${key}":`, error);
453
+ }
454
+ };
455
+ var removePreferenceAsync = async (key) => {
456
+ try {
457
+ if (config.backend === "indexedDB") {
458
+ await indexedDBStore.remove(getStorageKey(key));
459
+ } else {
460
+ removePreference(key);
461
+ }
462
+ } catch (error) {
463
+ console.warn(`Failed to remove preference "${key}":`, error);
464
+ }
465
+ };
466
+ var clearPreferences = () => {
467
+ try {
468
+ if (config.backend === "localStorage" && isLocalStorageAvailable()) {
469
+ const prefix = `${config.prefix}:`;
470
+ const keysToRemove = [];
471
+ for (let i = 0; i < localStorage.length; i++) {
472
+ const key = localStorage.key(i);
473
+ if (key?.startsWith(prefix)) {
474
+ keysToRemove.push(key);
475
+ }
476
+ }
477
+ keysToRemove.forEach((key) => localStorage.removeItem(key));
478
+ }
479
+ } catch (error) {
480
+ console.warn("Failed to clear preferences:", error);
481
+ }
482
+ };
483
+ var clearPreferencesAsync = async () => {
484
+ try {
485
+ if (config.backend === "indexedDB") {
486
+ await indexedDBStore.clear();
487
+ } else {
488
+ clearPreferences();
489
+ }
490
+ } catch (error) {
491
+ console.warn("Failed to clear preferences:", error);
492
+ }
493
+ };
494
+ var getAllPreferences = () => {
495
+ const preferences = {};
496
+ try {
497
+ if (config.backend === "localStorage" && isLocalStorageAvailable()) {
498
+ const prefix = `${config.prefix}:`;
499
+ for (let i = 0; i < localStorage.length; i++) {
500
+ const key = localStorage.key(i);
501
+ if (key?.startsWith(prefix)) {
502
+ const prefKey = key.substring(prefix.length);
503
+ const value = localStorage.getItem(key);
504
+ if (value !== null) {
505
+ try {
506
+ preferences[prefKey] = JSON.parse(value);
507
+ } catch {
508
+ preferences[prefKey] = value;
509
+ }
510
+ }
511
+ }
512
+ }
513
+ }
514
+ } catch (error) {
515
+ console.warn("Failed to get all preferences:", error);
516
+ }
517
+ return preferences;
518
+ };
519
+ var exportPreferences = () => {
520
+ const prefs = getAllPreferences();
521
+ return JSON.stringify(prefs, null, 2);
522
+ };
523
+ var importPreferences = (json, merge = false) => {
524
+ try {
525
+ const prefs = JSON.parse(json);
526
+ if (!merge) {
527
+ clearPreferences();
528
+ }
529
+ Object.entries(prefs).forEach(([key, value]) => {
530
+ setPreference(key, value);
531
+ });
532
+ } catch (error) {
533
+ console.warn("Failed to import preferences:", error);
534
+ }
535
+ };
536
+ var createPreferenceNamespace = (namespace) => {
537
+ const getKey = (key) => `${namespace}.${key}`;
538
+ return {
539
+ get: (key, defaultValue) => getPreference(getKey(key), defaultValue),
540
+ set: (key, value) => setPreference(getKey(key), value),
541
+ remove: (key) => removePreference(getKey(key)),
542
+ clear: () => {
543
+ const prefs = getAllPreferences();
544
+ const prefix = `${namespace}.`;
545
+ Object.keys(prefs).filter((key) => key.startsWith(prefix)).forEach((key) => removePreference(key));
546
+ }
547
+ };
548
+ };
549
+
550
+ // src/components/layout/Layout.tsx
551
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
552
+ var Layout = ({
553
+ variant = "stacked",
554
+ header,
555
+ footer,
556
+ sidebarLeft,
557
+ sidebarRight,
558
+ bottomBar,
559
+ resizable = false,
560
+ children,
561
+ className = "",
562
+ ...props
563
+ }) => {
564
+ const classes = ["layout", `layout--${variant}`, className].filter(Boolean).join(" ");
565
+ const NAVBAR_COLLAPSED_WIDTH = 72;
566
+ const NAVBAR_EXPAND_THRESHOLD = 210;
567
+ const NAVBAR_MIN_PERSIST_WIDTH = 211;
568
+ const NAVBAR_MAX_WIDTH = 600;
569
+ const hasSidebarLeft = sidebarLeft != null;
570
+ const hasSidebarRight = sidebarRight != null;
571
+ const sidebarLeftIsNavbar = hasSidebarLeft && React6.isValidElement(sidebarLeft) && Boolean(sidebarLeft.props?.isNavbar);
572
+ const columnCount = [hasSidebarLeft, true, hasSidebarRight].filter(Boolean).length;
573
+ const shouldShowResizers = resizable && columnCount >= 2;
574
+ const [leftSidebarWidth, setLeftSidebarWidth] = React6.useState(() => {
575
+ const v = getPreference("layout.leftSidebarWidth", 280);
576
+ return typeof v === "number" ? v : 280;
577
+ });
578
+ const preferredLeftSidebarWidth = React6.useMemo(() => {
579
+ const v = getPreference("layout.leftSidebarPreferredWidth", leftSidebarWidth);
580
+ if (typeof v === "number" && v >= NAVBAR_MIN_PERSIST_WIDTH) {
581
+ return v;
582
+ }
583
+ return Math.max(NAVBAR_MIN_PERSIST_WIDTH, leftSidebarWidth);
584
+ }, [leftSidebarWidth]);
585
+ const [rightSidebarWidth, setRightSidebarWidth] = React6.useState(() => {
586
+ const v = getPreference("layout.rightSidebarWidth", 300);
587
+ return typeof v === "number" ? v : 300;
588
+ });
589
+ const clampLeftWidth = React6.useCallback((width) => {
590
+ console.log("clampLeftWidth called with:", width);
591
+ if (width <= NAVBAR_COLLAPSED_WIDTH) {
592
+ console.log("Returning 72 (collapsed)");
593
+ return NAVBAR_COLLAPSED_WIDTH;
594
+ }
595
+ const result = Math.max(NAVBAR_COLLAPSED_WIDTH, Math.min(NAVBAR_MAX_WIDTH, Math.round(width)));
596
+ console.log("Returning clamped result:", result);
597
+ return result;
598
+ }, []);
599
+ const updateLeftSidebarWidth = React6.useCallback((width) => {
600
+ console.log("updateLeftSidebarWidth called with:", width);
601
+ const newWidth = clampLeftWidth(width);
602
+ console.log("clampLeftWidth result:", newWidth);
603
+ setLeftSidebarWidth(newWidth);
604
+ if (newWidth >= NAVBAR_MIN_PERSIST_WIDTH) {
605
+ setPreference("layout.leftSidebarWidth", newWidth);
606
+ }
607
+ }, [clampLeftWidth]);
608
+ const handleLeftResize = React6.useCallback((delta) => {
609
+ setLeftSidebarWidth((prev = 300) => {
610
+ const newWidthRaw = prev + delta;
611
+ const newWidth = clampLeftWidth(newWidthRaw);
612
+ if (newWidth >= NAVBAR_MIN_PERSIST_WIDTH) {
613
+ setPreference("layout.leftSidebarWidth", newWidth);
614
+ }
615
+ if (sidebarLeftIsNavbar && Math.abs(delta) > 5 && newWidth < NAVBAR_EXPAND_THRESHOLD) {
616
+ setPreference("layout.leftSidebarWidth", NAVBAR_COLLAPSED_WIDTH);
617
+ return NAVBAR_COLLAPSED_WIDTH;
618
+ }
619
+ if (newWidth >= NAVBAR_MIN_PERSIST_WIDTH) {
620
+ setPreference("layout.leftSidebarPreferredWidth", newWidth);
621
+ }
622
+ return newWidth;
623
+ });
624
+ }, [clampLeftWidth, sidebarLeftIsNavbar]);
625
+ const handleLeftResizeEnd = React6.useCallback(() => {
626
+ setLeftSidebarWidth((currentWidth) => {
627
+ if (currentWidth < NAVBAR_EXPAND_THRESHOLD) {
628
+ const collapsed = NAVBAR_COLLAPSED_WIDTH;
629
+ setPreference("layout.leftSidebarWidth", collapsed);
630
+ return collapsed;
631
+ }
632
+ return currentWidth;
633
+ });
634
+ }, []);
635
+ const handleRightResize = React6.useCallback((delta) => {
636
+ setRightSidebarWidth((prev = 300) => {
637
+ const newWidth = Math.max(200, Math.min(600, prev - delta));
638
+ setPreference("layout.rightSidebarWidth", newWidth);
639
+ return newWidth;
640
+ });
641
+ }, []);
642
+ if (variant === "single") {
643
+ return /* @__PURE__ */ jsx8("div", { className: classes, ...props, children: /* @__PURE__ */ jsxs4("div", { className: "layout__container", children: [
644
+ /* @__PURE__ */ jsxs4("main", { className: "layout__main", children: [
645
+ header && /* @__PURE__ */ jsx8("header", { className: "layout__header", children: header }),
646
+ children,
647
+ footer && /* @__PURE__ */ jsx8("footer", { className: "layout__footer", children: footer })
648
+ ] }),
649
+ bottomBar && /* @__PURE__ */ jsx8("div", { className: "layout__bottom-bar", children: bottomBar })
650
+ ] }) });
651
+ }
652
+ if (variant === "stacked") {
653
+ return /* @__PURE__ */ jsx8("div", { className: classes, ...props, children: /* @__PURE__ */ jsxs4("div", { className: "layout__container", children: [
654
+ /* @__PURE__ */ jsxs4("main", { className: "layout__main", children: [
655
+ header && /* @__PURE__ */ jsx8("header", { className: "layout__header", children: header }),
656
+ children,
657
+ footer && /* @__PURE__ */ jsx8("footer", { className: "layout__footer", children: footer })
658
+ ] }),
659
+ bottomBar && /* @__PURE__ */ jsx8("div", { className: "layout__bottom-bar", children: bottomBar })
660
+ ] }) });
661
+ }
662
+ if (variant === "sidebar-main-sidebar") {
663
+ return /* @__PURE__ */ jsxs4("div", { className: classes, ...props, children: [
664
+ hasSidebarLeft && /* @__PURE__ */ jsxs4(Fragment2, { children: [
665
+ /* @__PURE__ */ jsx8(
666
+ "aside",
667
+ {
668
+ className: "layout__sidebar layout__sidebar--left",
669
+ style: { width: leftSidebarWidth },
670
+ children: React6.isValidElement(sidebarLeft) ? React6.cloneElement(sidebarLeft, {
671
+ sidebarWidth: leftSidebarWidth,
672
+ setSidebarWidth: updateLeftSidebarWidth,
673
+ preferredSidebarWidth: preferredLeftSidebarWidth,
674
+ setPreferredSidebarWidth: (w) => {
675
+ const newW = clampLeftWidth(w);
676
+ if (newW >= NAVBAR_MIN_PERSIST_WIDTH) {
677
+ setPreference("layout.leftSidebarPreferredWidth", newW);
678
+ }
679
+ if (leftSidebarWidth > NAVBAR_COLLAPSED_WIDTH) {
680
+ setLeftSidebarWidth(newW);
681
+ setPreference("layout.leftSidebarWidth", newW);
682
+ }
683
+ }
684
+ }) : sidebarLeft
685
+ }
686
+ ),
687
+ shouldShowResizers && /* @__PURE__ */ jsx8(
688
+ DragHandle,
689
+ {
690
+ orientation: "vertical",
691
+ onResize: handleLeftResize,
692
+ onResizeEnd: handleLeftResizeEnd
693
+ }
694
+ )
695
+ ] }),
696
+ /* @__PURE__ */ jsxs4("div", { className: "layout__container", children: [
697
+ /* @__PURE__ */ jsxs4("main", { className: "layout__main", children: [
698
+ header && /* @__PURE__ */ jsx8("header", { className: "layout__header", children: header }),
699
+ children,
700
+ footer && /* @__PURE__ */ jsx8("footer", { className: "layout__footer", children: footer })
701
+ ] }),
702
+ bottomBar && /* @__PURE__ */ jsx8("div", { className: "layout__bottom-bar", children: bottomBar })
703
+ ] }),
704
+ hasSidebarRight && /* @__PURE__ */ jsxs4(Fragment2, { children: [
705
+ shouldShowResizers && /* @__PURE__ */ jsx8(
706
+ DragHandle,
707
+ {
708
+ orientation: "vertical",
709
+ onResize: handleRightResize
710
+ }
711
+ ),
712
+ /* @__PURE__ */ jsx8(
713
+ "aside",
714
+ {
715
+ className: "layout__sidebar layout__sidebar--right",
716
+ style: { width: rightSidebarWidth },
717
+ children: React6.isValidElement(sidebarRight) ? React6.cloneElement(sidebarRight, {
718
+ sidebarWidth: rightSidebarWidth,
719
+ setSidebarWidth: (w) => {
720
+ const newW = Math.max(200, Math.min(600, w));
721
+ setRightSidebarWidth(newW);
722
+ setPreference("layout.rightSidebarWidth", newW);
723
+ }
724
+ }) : sidebarRight
725
+ }
726
+ )
727
+ ] })
728
+ ] });
729
+ }
730
+ return /* @__PURE__ */ jsx8("div", { className: classes, ...props, children });
731
+ };
732
+
733
+ // src/components/page/page.tsx
734
+ import { jsx as jsx9 } from "react/jsx-runtime";
735
+ var Page = ({ width = "medium", children, className }) => {
736
+ const pageClasses = [
737
+ "page",
738
+ `page--${width}`,
739
+ className
740
+ ].filter(Boolean).join(" ");
741
+ return /* @__PURE__ */ jsx9("main", { className: pageClasses, children });
742
+ };
743
+
744
+ // src/components/header/header.tsx
745
+ import { useMemo as useMemo2 } from "react";
746
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
747
+ var Header = ({ title, subtitle, children, className }) => {
748
+ const headerId = useMemo2(() => {
749
+ if (typeof title === "string" && title.trim()) {
750
+ return title.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim();
751
+ }
752
+ return void 0;
753
+ }, [title]);
754
+ return /* @__PURE__ */ jsx10("header", { className: `header ${className || ""}`, id: headerId, children: /* @__PURE__ */ jsx10("div", { className: "header__container", children: children ? children : /* @__PURE__ */ jsxs5(Fragment3, { children: [
755
+ title && /* @__PURE__ */ jsx10("h1", { className: "header__title", children: title }),
756
+ subtitle && /* @__PURE__ */ jsx10("p", { className: "header__subtitle", children: subtitle })
757
+ ] }) }) });
758
+ };
759
+
760
+ // src/components/section/section.tsx
761
+ import { useMemo as useMemo3 } from "react";
762
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
763
+ var Section = ({ title, children, size = "md", className }) => {
764
+ const sectionClasses = [
765
+ "section",
766
+ size !== "md" && `section--${size}`,
767
+ className
768
+ ].filter(Boolean).join(" ");
769
+ const sectionId = useMemo3(() => {
770
+ if (typeof title === "string" && title.trim()) {
771
+ return title.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim();
772
+ }
773
+ return void 0;
774
+ }, [title]);
775
+ const titleText = typeof title === "string" ? title : void 0;
776
+ return /* @__PURE__ */ jsxs6(
777
+ "section",
778
+ {
779
+ className: sectionClasses,
780
+ id: sectionId,
781
+ "data-section-title": titleText,
782
+ children: [
783
+ title && /* @__PURE__ */ jsx11("h2", { className: "section__title", children: title }),
784
+ /* @__PURE__ */ jsx11("div", { className: "section__content", children })
785
+ ]
786
+ }
787
+ );
788
+ };
789
+
790
+ // src/components/code-block/code-block.tsx
791
+ import { jsx as jsx12 } from "react/jsx-runtime";
792
+ var CodeBlock = ({ children, variant = "block", className }) => {
793
+ const classes = [
794
+ "code-block",
795
+ variant === "inline" && "code-block--inline",
796
+ className
797
+ ].filter(Boolean).join(" ");
798
+ if (variant === "inline") {
799
+ return /* @__PURE__ */ jsx12("code", { className: classes, children });
800
+ }
801
+ return /* @__PURE__ */ jsx12("pre", { className: classes, children: /* @__PURE__ */ jsx12("code", { children }) });
802
+ };
803
+
804
+ // src/components/navbar/Navbar.tsx
805
+ import { jsx as jsx13 } from "react/jsx-runtime";
806
+ var Navbar = ({
807
+ children,
808
+ className = ""
809
+ }) => {
810
+ const classes = ["navbar", className].filter(Boolean).join(" ");
811
+ return /* @__PURE__ */ jsx13("nav", { className: classes, role: "navigation", "aria-label": "Main navigation", children: /* @__PURE__ */ jsx13("div", { className: "navbar__content", children }) });
812
+ };
813
+
814
+ // src/components/tooltip/tooltip.tsx
815
+ import * as React9 from "react";
816
+ import * as ReactDOM from "react-dom";
817
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
818
+ var Tooltip = ({
819
+ content,
820
+ children,
821
+ placement = "top",
822
+ delay = 0,
823
+ disabled = false
824
+ }) => {
825
+ const [isVisible, setIsVisible] = React9.useState(false);
826
+ const [tooltipStyle, setTooltipStyle] = React9.useState({});
827
+ const [resolvedPlacement, setResolvedPlacement] = React9.useState(placement);
828
+ const triggerRef = React9.useRef(null);
829
+ const tooltipRef = React9.useRef(null);
830
+ const timeoutRef = React9.useRef();
831
+ React9.useEffect(() => {
832
+ if (!isVisible || !triggerRef.current || !tooltipRef.current) {
833
+ return;
834
+ }
835
+ const updatePosition = () => {
836
+ if (!triggerRef.current || !tooltipRef.current) {
837
+ console.log("Tooltip refs not ready:", { trigger: !!triggerRef.current, tooltip: !!tooltipRef.current });
838
+ return;
839
+ }
840
+ const triggerRect = triggerRef.current.getBoundingClientRect();
841
+ const tooltipRect = tooltipRef.current.getBoundingClientRect();
842
+ if (tooltipRect.width === 0 || tooltipRect.height === 0) {
843
+ setTimeout(updatePosition, 10);
844
+ return;
845
+ }
846
+ const gap = 8;
847
+ const viewportWidth = window.innerWidth;
848
+ const viewportHeight = window.innerHeight;
849
+ const spaceTop = triggerRect.top;
850
+ const spaceBottom = viewportHeight - triggerRect.bottom;
851
+ const spaceLeft = triggerRect.left;
852
+ const spaceRight = viewportWidth - triggerRect.right;
853
+ let finalPlacement = placement;
854
+ if (placement === "right" && spaceRight < tooltipRect.width + gap) {
855
+ finalPlacement = spaceLeft >= tooltipRect.width + gap ? "left" : "bottom";
856
+ } else if (placement === "left" && spaceLeft < tooltipRect.width + gap) {
857
+ finalPlacement = spaceRight >= tooltipRect.width + gap ? "right" : "bottom";
858
+ } else if (placement === "bottom" && spaceBottom < tooltipRect.height + gap) {
859
+ finalPlacement = spaceTop >= tooltipRect.height + gap ? "top" : "bottom";
860
+ } else if (placement === "top" && spaceTop < tooltipRect.height + gap) {
861
+ finalPlacement = spaceBottom >= tooltipRect.height + gap ? "bottom" : "top";
862
+ }
863
+ setResolvedPlacement(finalPlacement);
864
+ const newStyle = {
865
+ position: "fixed",
866
+ zIndex: 1e4,
867
+ opacity: 1,
868
+ visibility: "visible",
869
+ pointerEvents: "auto"
870
+ };
871
+ switch (finalPlacement) {
872
+ case "right":
873
+ newStyle.top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
874
+ newStyle.left = triggerRect.right + gap;
875
+ break;
876
+ case "left":
877
+ newStyle.top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
878
+ newStyle.left = triggerRect.left - tooltipRect.width - gap;
879
+ break;
880
+ case "top":
881
+ newStyle.top = triggerRect.top - tooltipRect.height - gap;
882
+ newStyle.left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
883
+ break;
884
+ case "bottom":
885
+ default:
886
+ newStyle.top = triggerRect.bottom + gap;
887
+ newStyle.left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
888
+ }
889
+ if (newStyle.left < 0) {
890
+ newStyle.left = 0;
891
+ } else if (newStyle.left + tooltipRect.width > viewportWidth) {
892
+ newStyle.left = viewportWidth - tooltipRect.width;
893
+ }
894
+ if (newStyle.top < 0) {
895
+ newStyle.top = 0;
896
+ } else if (newStyle.top + tooltipRect.height > viewportHeight) {
897
+ newStyle.top = viewportHeight - tooltipRect.height;
898
+ }
899
+ setTooltipStyle(newStyle);
900
+ console.log("Calculated position:", newStyle);
901
+ };
902
+ console.log("Tooltip isVisible:", isVisible, "tooltipStyle:", tooltipStyle);
903
+ requestAnimationFrame(updatePosition);
904
+ window.addEventListener("resize", updatePosition);
905
+ window.addEventListener("scroll", updatePosition, true);
906
+ return () => {
907
+ window.removeEventListener("resize", updatePosition);
908
+ window.removeEventListener("scroll", updatePosition, true);
909
+ };
910
+ }, [isVisible, placement]);
911
+ const handleMouseEnter = () => {
912
+ if (disabled) return;
913
+ console.log("Tooltip mouse enter");
914
+ if (timeoutRef.current) {
915
+ clearTimeout(timeoutRef.current);
916
+ }
917
+ timeoutRef.current = setTimeout(() => {
918
+ console.log("Tooltip setting visible");
919
+ setIsVisible(true);
920
+ }, delay);
921
+ };
922
+ const handleMouseLeave = () => {
923
+ console.log("Tooltip mouse leave");
924
+ if (timeoutRef.current) {
925
+ clearTimeout(timeoutRef.current);
926
+ }
927
+ timeoutRef.current = setTimeout(() => {
928
+ console.log("Tooltip setting invisible");
929
+ setIsVisible(false);
930
+ }, 150);
931
+ };
932
+ const handleClick = () => {
933
+ if (timeoutRef.current) {
934
+ clearTimeout(timeoutRef.current);
935
+ }
936
+ setIsVisible(false);
937
+ };
938
+ return /* @__PURE__ */ jsxs7(Fragment4, { children: [
939
+ /* @__PURE__ */ jsx14(
940
+ "div",
941
+ {
942
+ ref: triggerRef,
943
+ onMouseEnter: handleMouseEnter,
944
+ onMouseLeave: handleMouseLeave,
945
+ onClick: handleClick,
946
+ style: { display: "inline-block" },
947
+ children
948
+ }
949
+ ),
950
+ isVisible && !disabled && ReactDOM.createPortal(
951
+ /* @__PURE__ */ jsx14(
952
+ "div",
953
+ {
954
+ ref: tooltipRef,
955
+ className: `tooltip tooltip--${resolvedPlacement}`,
956
+ style: {
957
+ ...tooltipStyle,
958
+ // Start with opacity 0 and visibility hidden to prevent initial flash
959
+ opacity: tooltipStyle.top !== void 0 ? 1 : 0,
960
+ visibility: tooltipStyle.top !== void 0 ? "visible" : "hidden"
961
+ },
962
+ onMouseEnter: () => {
963
+ console.log("Tooltip mouse enter on tooltip");
964
+ if (timeoutRef.current) {
965
+ clearTimeout(timeoutRef.current);
966
+ }
967
+ },
968
+ onMouseLeave: handleMouseLeave,
969
+ children: /* @__PURE__ */ jsx14("div", { className: "tooltip__content", children: content })
970
+ }
971
+ ),
972
+ document.body
973
+ )
974
+ ] });
975
+ };
976
+
977
+ // src/components/navbar/MenuItem.tsx
978
+ import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
979
+ var MenuItem = ({
980
+ icon,
981
+ active = false,
982
+ children,
983
+ className = "",
984
+ as: Component = "button",
985
+ isCollapsed = false,
986
+ showTooltipWhenCollapsed = false,
987
+ ...props
988
+ }) => {
989
+ const { hasOpenPopover } = useNavbarTooltip();
990
+ const classes = [
991
+ "navbar__menu-item",
992
+ active && "navbar__menu-item--active",
993
+ className
994
+ ].filter(Boolean).join(" ");
995
+ const menuItem = isCollapsed ? /* @__PURE__ */ jsx15(
996
+ Button,
997
+ {
998
+ variant: active ? "primary" : "ghost",
999
+ iconOnly: true,
1000
+ startIcon: icon,
1001
+ ...props
1002
+ }
1003
+ ) : /* @__PURE__ */ jsxs8(
1004
+ Component,
1005
+ {
1006
+ className: classes,
1007
+ type: Component === "button" ? "button" : void 0,
1008
+ ...props,
1009
+ children: [
1010
+ icon && /* @__PURE__ */ jsx15("span", { className: "navbar__menu-item-icon", children: /* @__PURE__ */ jsx15(Icon, { name: icon, size: 16 }) }),
1011
+ !isCollapsed && /* @__PURE__ */ jsx15("span", { className: "navbar__menu-item-label", children })
1012
+ ]
1013
+ }
1014
+ );
1015
+ if (showTooltipWhenCollapsed && isCollapsed) {
1016
+ return /* @__PURE__ */ jsx15(Tooltip, { content: typeof children === "string" ? children : "", placement: "right", disabled: hasOpenPopover, children: menuItem });
1017
+ }
1018
+ return menuItem;
1019
+ };
1020
+
1021
+ // src/components/navbar/MenuGroup.tsx
1022
+ import * as React11 from "react";
1023
+
1024
+ // src/components/popover/popover.tsx
1025
+ import * as React10 from "react";
1026
+ import * as ReactDOM2 from "react-dom";
1027
+ import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
1028
+ var Popover = ({
1029
+ trigger,
1030
+ children,
1031
+ isOpen = false,
1032
+ onToggle,
1033
+ placement = "bottom"
1034
+ }) => {
1035
+ const [internalOpen, setInternalOpen] = React10.useState(false);
1036
+ const triggerRef = React10.useRef(null);
1037
+ const popoverRef = React10.useRef(null);
1038
+ const [popoverStyle, setPopoverStyle] = React10.useState({});
1039
+ const [resolvedPlacement, setResolvedPlacement] = React10.useState(placement);
1040
+ const open = isOpen !== void 0 ? isOpen : internalOpen;
1041
+ const toggle = onToggle || (() => setInternalOpen(!internalOpen));
1042
+ React10.useEffect(() => {
1043
+ const handleClickOutside = (event) => {
1044
+ if (triggerRef.current && !triggerRef.current.contains(event.target) && popoverRef.current && !popoverRef.current.contains(event.target)) {
1045
+ if (onToggle) {
1046
+ onToggle();
1047
+ } else {
1048
+ setInternalOpen(false);
1049
+ }
1050
+ }
1051
+ };
1052
+ if (open) {
1053
+ document.addEventListener("mousedown", handleClickOutside);
1054
+ }
1055
+ return () => {
1056
+ document.removeEventListener("mousedown", handleClickOutside);
1057
+ };
1058
+ }, [open, onToggle]);
1059
+ React10.useEffect(() => {
1060
+ if (!open || !triggerRef.current || !popoverRef.current) {
1061
+ return;
1062
+ }
1063
+ const updatePosition = () => {
1064
+ if (!triggerRef.current || !popoverRef.current) {
1065
+ return;
1066
+ }
1067
+ const triggerRect = triggerRef.current.getBoundingClientRect();
1068
+ const popoverRect = popoverRef.current.getBoundingClientRect();
1069
+ const gap = 8;
1070
+ const viewportWidth = window.innerWidth;
1071
+ const viewportHeight = window.innerHeight;
1072
+ const spaceTop = triggerRect.top;
1073
+ const spaceBottom = viewportHeight - triggerRect.bottom;
1074
+ const spaceLeft = triggerRect.left;
1075
+ const spaceRight = viewportWidth - triggerRect.right;
1076
+ let finalPlacement = placement;
1077
+ if (placement === "right" && spaceRight < popoverRect.width + gap) {
1078
+ finalPlacement = spaceLeft >= popoverRect.width + gap ? "left" : "bottom";
1079
+ } else if (placement === "left" && spaceLeft < popoverRect.width + gap) {
1080
+ finalPlacement = spaceRight >= popoverRect.width + gap ? "right" : "bottom";
1081
+ } else if (placement === "bottom" && spaceBottom < popoverRect.height + gap) {
1082
+ finalPlacement = spaceTop >= popoverRect.height + gap ? "top" : "bottom";
1083
+ } else if (placement === "top" && spaceTop < popoverRect.height + gap) {
1084
+ finalPlacement = spaceBottom >= popoverRect.height + gap ? "bottom" : "top";
1085
+ }
1086
+ setResolvedPlacement(finalPlacement);
1087
+ const newStyle = {
1088
+ position: "fixed",
1089
+ zIndex: 9999,
1090
+ opacity: 1,
1091
+ visibility: "visible",
1092
+ pointerEvents: "auto"
1093
+ };
1094
+ switch (finalPlacement) {
1095
+ case "right":
1096
+ newStyle.top = triggerRect.top;
1097
+ newStyle.left = triggerRect.right + gap;
1098
+ break;
1099
+ case "left":
1100
+ newStyle.top = triggerRect.top;
1101
+ newStyle.left = triggerRect.left - popoverRect.width - gap;
1102
+ break;
1103
+ case "top":
1104
+ newStyle.top = triggerRect.top - popoverRect.height - gap;
1105
+ newStyle.left = triggerRect.left;
1106
+ break;
1107
+ case "bottom":
1108
+ default:
1109
+ newStyle.top = triggerRect.bottom + gap;
1110
+ newStyle.left = triggerRect.left;
1111
+ }
1112
+ if (typeof newStyle.left === "number") {
1113
+ if (newStyle.left + popoverRect.width > viewportWidth - gap) {
1114
+ newStyle.left = viewportWidth - popoverRect.width - gap;
1115
+ }
1116
+ if (newStyle.left < gap) {
1117
+ newStyle.left = gap;
1118
+ }
1119
+ }
1120
+ if (typeof newStyle.top === "number") {
1121
+ if (newStyle.top + popoverRect.height > viewportHeight - gap) {
1122
+ newStyle.top = viewportHeight - popoverRect.height - gap;
1123
+ }
1124
+ if (newStyle.top < gap) {
1125
+ newStyle.top = gap;
1126
+ }
1127
+ }
1128
+ setPopoverStyle(newStyle);
1129
+ };
1130
+ requestAnimationFrame(updatePosition);
1131
+ window.addEventListener("resize", updatePosition);
1132
+ window.addEventListener("scroll", updatePosition, true);
1133
+ return () => {
1134
+ window.removeEventListener("resize", updatePosition);
1135
+ window.removeEventListener("scroll", updatePosition, true);
1136
+ };
1137
+ }, [open, placement]);
1138
+ const handleTriggerClick = () => {
1139
+ toggle();
1140
+ };
1141
+ return /* @__PURE__ */ jsxs9(Fragment5, { children: [
1142
+ /* @__PURE__ */ jsx16(
1143
+ "div",
1144
+ {
1145
+ ref: triggerRef,
1146
+ onClick: handleTriggerClick,
1147
+ style: { display: "inline-block", position: "relative" },
1148
+ children: React10.isValidElement(trigger) ? React10.cloneElement(trigger, {
1149
+ onClick: (e) => {
1150
+ e.stopPropagation();
1151
+ handleTriggerClick();
1152
+ trigger.props?.onClick?.(e);
1153
+ }
1154
+ }) : trigger
1155
+ }
1156
+ ),
1157
+ open && ReactDOM2.createPortal(
1158
+ /* @__PURE__ */ jsx16(
1159
+ "div",
1160
+ {
1161
+ ref: popoverRef,
1162
+ className: `popover popover--${resolvedPlacement}`,
1163
+ style: {
1164
+ ...popoverStyle,
1165
+ // Start with opacity 0 and visibility hidden to prevent initial flash
1166
+ opacity: popoverStyle.top !== void 0 ? 1 : 0,
1167
+ visibility: popoverStyle.top !== void 0 ? "visible" : "hidden"
1168
+ },
1169
+ children: /* @__PURE__ */ jsx16("div", { className: "popover__content", children })
1170
+ }
1171
+ ),
1172
+ document.body
1173
+ )
1174
+ ] });
1175
+ };
1176
+
1177
+ // src/components/navbar/MenuGroup.tsx
1178
+ import { jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
1179
+ var MenuGroup = ({
1180
+ title,
1181
+ icon,
1182
+ children,
1183
+ defaultExpanded = false,
1184
+ autoExpand = false,
1185
+ expandable = true,
1186
+ isCollapsed = false
1187
+ }) => {
1188
+ const [expanded, setExpanded] = React11.useState(defaultExpanded);
1189
+ const [userInteracted, setUserInteracted] = React11.useState(false);
1190
+ const { openPopover, closePopover, activePopoverId } = useNavbarTooltip();
1191
+ const groupId = React11.useMemo(() => `menu-group-${title.replace(/\s+/g, "-").toLowerCase()}`, [title]);
1192
+ const popoverOpen = activePopoverId === groupId;
1193
+ const triggerRef = React11.useRef(null);
1194
+ const popoverContentRef = React11.useRef(null);
1195
+ React11.useEffect(() => {
1196
+ if (popoverOpen && popoverContentRef.current) {
1197
+ setTimeout(() => {
1198
+ const firstFocusable = popoverContentRef.current?.querySelector(
1199
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1200
+ );
1201
+ firstFocusable?.focus();
1202
+ }, 10);
1203
+ }
1204
+ }, [popoverOpen]);
1205
+ const findNextFocusableElement = React11.useCallback((currentElement) => {
1206
+ const navbar = currentElement.closest(".navbar");
1207
+ if (!navbar) return null;
1208
+ const focusableElements = navbar.querySelectorAll(
1209
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1210
+ );
1211
+ const rootFocusableElements = Array.from(focusableElements).filter((el) => {
1212
+ return !el.closest(".popover");
1213
+ });
1214
+ const currentIndex = rootFocusableElements.indexOf(currentElement);
1215
+ if (currentIndex >= 0 && currentIndex < rootFocusableElements.length - 1) {
1216
+ return rootFocusableElements[currentIndex + 1];
1217
+ }
1218
+ return null;
1219
+ }, []);
1220
+ const handleKeyDown = React11.useCallback((event) => {
1221
+ if (event.key === "Tab" && !event.shiftKey) {
1222
+ if (popoverContentRef.current) {
1223
+ const focusableElements = popoverContentRef.current.querySelectorAll(
1224
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1225
+ );
1226
+ const currentElement = event.target;
1227
+ const currentIndex = Array.from(focusableElements).indexOf(currentElement);
1228
+ if (currentIndex >= 0 && currentIndex === focusableElements.length - 1) {
1229
+ event.preventDefault();
1230
+ const nextElement = findNextFocusableElement(currentElement);
1231
+ if (nextElement) {
1232
+ nextElement.focus();
1233
+ } else {
1234
+ closePopover(groupId);
1235
+ triggerRef.current?.focus();
1236
+ }
1237
+ }
1238
+ }
1239
+ } else if (event.key === "Tab" && event.shiftKey) {
1240
+ if (popoverContentRef.current) {
1241
+ const focusableElements = popoverContentRef.current.querySelectorAll(
1242
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1243
+ );
1244
+ const currentElement = event.target;
1245
+ const currentIndex = Array.from(focusableElements).indexOf(currentElement);
1246
+ if (currentIndex === 0) {
1247
+ event.preventDefault();
1248
+ triggerRef.current?.focus();
1249
+ }
1250
+ }
1251
+ } else if (event.key === "Escape") {
1252
+ closePopover(groupId);
1253
+ setTimeout(() => {
1254
+ triggerRef.current?.focus();
1255
+ }, 10);
1256
+ }
1257
+ }, [closePopover, groupId, findNextFocusableElement]);
1258
+ const hasActiveItem = React11.useMemo(() => {
1259
+ const checkForActiveItems = (children2) => {
1260
+ return React11.Children.toArray(children2).some((child) => {
1261
+ if (React11.isValidElement(child)) {
1262
+ if (child.props && child.props.active === true) {
1263
+ return true;
1264
+ }
1265
+ if (child.props && child.props.children) {
1266
+ return checkForActiveItems(child.props.children);
1267
+ }
1268
+ }
1269
+ return false;
1270
+ });
1271
+ };
1272
+ return checkForActiveItems(children);
1273
+ }, [children]);
1274
+ React11.useEffect(() => {
1275
+ if (autoExpand && hasActiveItem && !userInteracted) {
1276
+ setExpanded(true);
1277
+ }
1278
+ }, [autoExpand, hasActiveItem, userInteracted]);
1279
+ const toggleExpanded = () => {
1280
+ setUserInteracted(true);
1281
+ setExpanded(!expanded);
1282
+ };
1283
+ const popoverContent = /* @__PURE__ */ jsxs10("div", { className: "navbar__menu-group-popover", children: [
1284
+ /* @__PURE__ */ jsx17("div", { className: "navbar__menu-group-popover-title", children: title }),
1285
+ /* @__PURE__ */ jsx17(
1286
+ "div",
1287
+ {
1288
+ className: "navbar__menu-group-popover-content",
1289
+ ref: popoverContentRef,
1290
+ onKeyDown: handleKeyDown,
1291
+ onClick: () => {
1292
+ setTimeout(() => {
1293
+ closePopover(groupId);
1294
+ }, 0);
1295
+ },
1296
+ children: React11.Children.map(children, (child) => {
1297
+ if (React11.isValidElement(child)) {
1298
+ return React11.cloneElement(child, {
1299
+ onKeyDown: (e) => {
1300
+ child.props.onKeyDown?.(e);
1301
+ handleKeyDown(e);
1302
+ }
1303
+ });
1304
+ }
1305
+ return child;
1306
+ })
1307
+ }
1308
+ )
1309
+ ] });
1310
+ const expandedHeader = !expandable ? /* @__PURE__ */ jsxs10("div", { className: "navbar__menu-group-header navbar__menu-group-header--static", children: [
1311
+ icon && /* @__PURE__ */ jsx17("span", { className: "navbar__menu-group-icon", children: /* @__PURE__ */ jsx17(Icon, { name: icon, size: 16 }) }),
1312
+ /* @__PURE__ */ jsx17("span", { className: "navbar__menu-group-title", children: title })
1313
+ ] }) : /* @__PURE__ */ jsxs10(
1314
+ "button",
1315
+ {
1316
+ className: `navbar__menu-group-header ${!expanded && hasActiveItem ? "navbar__menu-group-header--active" : ""}`,
1317
+ onClick: toggleExpanded,
1318
+ "aria-expanded": expanded,
1319
+ "aria-controls": `menu-group-${title.replace(/\s+/g, "-").toLowerCase()}`,
1320
+ type: "button",
1321
+ children: [
1322
+ icon && /* @__PURE__ */ jsx17("span", { className: "navbar__menu-group-icon", children: /* @__PURE__ */ jsx17(Icon, { name: icon, size: 16 }) }),
1323
+ /* @__PURE__ */ jsx17("span", { className: "navbar__menu-group-title", children: title }),
1324
+ /* @__PURE__ */ jsx17("span", { className: `navbar__menu-group-chevron ${expanded ? "navbar__menu-group-chevron--expanded" : ""}`, children: /* @__PURE__ */ jsx17(Icon, { name: "chevron-down", size: 12 }) })
1325
+ ]
1326
+ }
1327
+ );
1328
+ const collapsedHeader = /* @__PURE__ */ jsx17("div", { children: /* @__PURE__ */ jsx17(
1329
+ Popover,
1330
+ {
1331
+ trigger: /* @__PURE__ */ jsx17(Tooltip, { content: title, placement: "right", disabled: popoverOpen, children: /* @__PURE__ */ jsx17(
1332
+ Button,
1333
+ {
1334
+ ref: triggerRef,
1335
+ variant: popoverOpen ? "secondary" : hasActiveItem ? "primary" : "ghost",
1336
+ iconOnly: true,
1337
+ startIcon: icon,
1338
+ "aria-label": title,
1339
+ "aria-haspopup": "menu",
1340
+ "aria-expanded": popoverOpen,
1341
+ onKeyDown: (event) => {
1342
+ if (event.key === "Tab" && !event.shiftKey && popoverOpen) {
1343
+ event.preventDefault();
1344
+ const firstFocusable = popoverContentRef.current?.querySelector(
1345
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1346
+ );
1347
+ firstFocusable?.focus();
1348
+ }
1349
+ },
1350
+ onClick: () => {
1351
+ if (popoverOpen) {
1352
+ closePopover(groupId);
1353
+ } else {
1354
+ openPopover(groupId);
1355
+ }
1356
+ }
1357
+ }
1358
+ ) }),
1359
+ isOpen: popoverOpen,
1360
+ onToggle: () => {
1361
+ if (popoverOpen) {
1362
+ closePopover(groupId);
1363
+ } else {
1364
+ openPopover(groupId);
1365
+ }
1366
+ },
1367
+ placement: "right",
1368
+ children: popoverContent
1369
+ }
1370
+ ) });
1371
+ return /* @__PURE__ */ jsxs10("div", { className: "navbar__menu-group", children: [
1372
+ isCollapsed ? collapsedHeader : expandedHeader,
1373
+ !isCollapsed && /* @__PURE__ */ jsx17(
1374
+ "div",
1375
+ {
1376
+ className: "navbar__menu-group-content",
1377
+ id: `menu-group-${title.replace(/\s+/g, "-").toLowerCase()}`,
1378
+ "aria-hidden": !expandable || !expanded,
1379
+ style: { display: expandable ? expanded ? "block" : "none" : "block" },
1380
+ children
1381
+ }
1382
+ )
1383
+ ] });
1384
+ };
1385
+
1386
+ // src/components/navbar/MenuCategory.tsx
1387
+ import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
1388
+ var MenuCategory = ({
1389
+ title,
1390
+ children
1391
+ }) => {
1392
+ return /* @__PURE__ */ jsxs11("div", { className: "navbar__menu-category", children: [
1393
+ /* @__PURE__ */ jsx18("div", { className: "navbar__menu-category-title", children: title }),
1394
+ /* @__PURE__ */ jsx18("div", { className: "navbar__menu-category-content", children })
1395
+ ] });
1396
+ };
1397
+
1398
+ // src/components/theme-control/theme-control.tsx
1399
+ import * as React12 from "react";
1400
+
1401
+ // src/utils/theme.ts
1402
+ var THEME_KEY = "theme";
1403
+ var ATTR_NAME = "data-theme";
1404
+ var applyTheme = (theme) => {
1405
+ document.documentElement.setAttribute(ATTR_NAME, theme);
1406
+ };
1407
+ var getTheme = () => {
1408
+ const dataTheme = document.documentElement.getAttribute(ATTR_NAME);
1409
+ if (dataTheme === "light" || dataTheme === "dark") return dataTheme;
1410
+ try {
1411
+ const stored = getPreference(THEME_KEY);
1412
+ if (stored === "light" || stored === "dark") return stored;
1413
+ } catch (e) {
1414
+ }
1415
+ if (typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches) {
1416
+ return "dark";
1417
+ }
1418
+ return "light";
1419
+ };
1420
+ var getSavedTheme = () => getTheme();
1421
+ var setTheme = (theme) => {
1422
+ if (!["light", "dark"].includes(theme)) {
1423
+ console.warn(`Invalid theme: ${theme}. Using 'light' as fallback.`);
1424
+ theme = "light";
1425
+ }
1426
+ try {
1427
+ setPreference(THEME_KEY, theme);
1428
+ } catch (e) {
1429
+ }
1430
+ applyTheme(theme);
1431
+ };
1432
+ var initializeTheme = () => {
1433
+ const theme = getTheme();
1434
+ applyTheme(theme);
1435
+ };
1436
+ var onSystemThemeChange = (callback) => {
1437
+ if (typeof window === "undefined") return () => {
1438
+ };
1439
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
1440
+ const listener = (e) => {
1441
+ const theme = e.matches ? "dark" : "light";
1442
+ const hasStored = (() => {
1443
+ try {
1444
+ const stored = getPreference(THEME_KEY);
1445
+ return stored === "light" || stored === "dark";
1446
+ } catch {
1447
+ return false;
1448
+ }
1449
+ })();
1450
+ const dataTheme = document.documentElement.getAttribute(ATTR_NAME);
1451
+ if (!hasStored && !dataTheme) callback(theme);
1452
+ };
1453
+ if (mediaQuery.addEventListener) {
1454
+ mediaQuery.addEventListener("change", listener);
1455
+ return () => mediaQuery.removeEventListener("change", listener);
1456
+ }
1457
+ mediaQuery.addListener(listener);
1458
+ return () => mediaQuery.removeListener(listener);
1459
+ };
1460
+ var toggleTheme = () => {
1461
+ const current = getTheme();
1462
+ const next = current === "light" ? "dark" : "light";
1463
+ setTheme(next);
1464
+ return next;
1465
+ };
1466
+
1467
+ // src/components/theme-control/theme-control.tsx
1468
+ import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
1469
+ var themeOptions = [
1470
+ {
1471
+ value: "light",
1472
+ label: "Light",
1473
+ icon: /* @__PURE__ */ jsxs12("svg", { className: "theme-control__icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1474
+ /* @__PURE__ */ jsx19("circle", { cx: "12", cy: "12", r: "5" }),
1475
+ /* @__PURE__ */ jsx19("line", { x1: "12", y1: "1", x2: "12", y2: "3" }),
1476
+ /* @__PURE__ */ jsx19("line", { x1: "12", y1: "21", x2: "12", y2: "23" }),
1477
+ /* @__PURE__ */ jsx19("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }),
1478
+ /* @__PURE__ */ jsx19("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }),
1479
+ /* @__PURE__ */ jsx19("line", { x1: "1", y1: "12", x2: "3", y2: "12" }),
1480
+ /* @__PURE__ */ jsx19("line", { x1: "21", y1: "12", x2: "23", y2: "12" }),
1481
+ /* @__PURE__ */ jsx19("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }),
1482
+ /* @__PURE__ */ jsx19("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })
1483
+ ] })
1484
+ },
1485
+ {
1486
+ value: "dark",
1487
+ label: "Dark",
1488
+ icon: /* @__PURE__ */ jsx19("svg", { className: "theme-control__icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx19("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) })
1489
+ }
1490
+ ];
1491
+ var ThemeControl = ({ onThemeChange }) => {
1492
+ const [currentTheme, setCurrentTheme] = React12.useState(() => {
1493
+ return getSavedTheme();
1494
+ });
1495
+ React12.useEffect(() => {
1496
+ setTheme(currentTheme);
1497
+ onThemeChange?.(currentTheme);
1498
+ }, [currentTheme, onThemeChange]);
1499
+ const handleThemeSelect = (theme) => {
1500
+ setCurrentTheme(theme);
1501
+ };
1502
+ return /* @__PURE__ */ jsx19("div", { className: "theme-control", children: themeOptions.map((option) => /* @__PURE__ */ jsxs12(
1503
+ "div",
1504
+ {
1505
+ className: `theme-control__option ${currentTheme === option.value ? "theme-control__option--active" : ""}`,
1506
+ onClick: () => handleThemeSelect(option.value),
1507
+ children: [
1508
+ option.icon,
1509
+ /* @__PURE__ */ jsx19("span", { children: option.label })
1510
+ ]
1511
+ },
1512
+ option.value
1513
+ )) });
1514
+ };
1515
+
1516
+ // src/components/card/card.tsx
1517
+ import { jsx as jsx20 } from "react/jsx-runtime";
1518
+ var Card = ({
1519
+ variant = "default",
1520
+ children,
1521
+ className = "",
1522
+ onClick,
1523
+ ...props
1524
+ }) => {
1525
+ const cardClasses = [
1526
+ "card",
1527
+ `card--${variant}`,
1528
+ onClick && "card--interactive",
1529
+ className
1530
+ ].filter(Boolean).join(" ");
1531
+ const Component = onClick ? "button" : "div";
1532
+ return /* @__PURE__ */ jsx20(
1533
+ Component,
1534
+ {
1535
+ className: cardClasses,
1536
+ onClick,
1537
+ ...onClick && { type: "button" },
1538
+ ...props,
1539
+ children
1540
+ }
1541
+ );
1542
+ };
1543
+
1544
+ // src/components/color-control/color-control.tsx
1545
+ import { useState as useState9, useEffect as useEffect5, useCallback as useCallback6 } from "react";
1546
+
1547
+ // src/components/slider/Slider.tsx
1548
+ import React13, { useState as useState8, useCallback as useCallback5, useRef as useRef5 } from "react";
1549
+ import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
1550
+ var Slider = ({
1551
+ min = 0,
1552
+ max = 100,
1553
+ value,
1554
+ step = 1,
1555
+ onChange,
1556
+ onDragStart,
1557
+ onChangeEnd,
1558
+ label,
1559
+ showValue = true,
1560
+ className = "",
1561
+ disabled = false,
1562
+ type = "default",
1563
+ baseHue = 0,
1564
+ baseSaturation = 70
1565
+ }) => {
1566
+ const [isDragging, setIsDragging] = useState8(false);
1567
+ const inputRef = useRef5(null);
1568
+ const containerRef = useRef5(null);
1569
+ const valueRef = useRef5(value);
1570
+ React13.useEffect(() => {
1571
+ valueRef.current = value;
1572
+ }, [value]);
1573
+ const handleChange = useCallback5((event) => {
1574
+ const newValue = parseFloat(event.target.value);
1575
+ onChange(newValue);
1576
+ }, [onChange]);
1577
+ const getValueFromPosition = useCallback5((clientX) => {
1578
+ if (!containerRef.current) return value;
1579
+ const rect = containerRef.current.getBoundingClientRect();
1580
+ const percentage = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
1581
+ const rawValue = min + percentage * (max - min);
1582
+ const steppedValue = Math.round(rawValue / step) * step;
1583
+ return Math.max(min, Math.min(max, steppedValue));
1584
+ }, [min, max, step, value]);
1585
+ const handleMouseDown = useCallback5((event) => {
1586
+ if (disabled) return;
1587
+ event.preventDefault();
1588
+ setIsDragging(true);
1589
+ onDragStart?.();
1590
+ const newValue = getValueFromPosition(event.clientX);
1591
+ onChange(newValue);
1592
+ }, [disabled, onDragStart, getValueFromPosition, onChange]);
1593
+ const handleMouseMove = useCallback5((event) => {
1594
+ if (!isDragging) return;
1595
+ event.preventDefault();
1596
+ const newValue = getValueFromPosition(event.clientX);
1597
+ onChange(newValue);
1598
+ }, [isDragging, getValueFromPosition, onChange]);
1599
+ const handleMouseUp = useCallback5(() => {
1600
+ if (!isDragging) return;
1601
+ setIsDragging(false);
1602
+ onChangeEnd?.(valueRef.current);
1603
+ }, [isDragging, onChangeEnd]);
1604
+ React13.useEffect(() => {
1605
+ if (!isDragging) return;
1606
+ document.addEventListener("mousemove", handleMouseMove);
1607
+ document.addEventListener("mouseup", handleMouseUp);
1608
+ return () => {
1609
+ document.removeEventListener("mousemove", handleMouseMove);
1610
+ document.removeEventListener("mouseup", handleMouseUp);
1611
+ };
1612
+ }, [isDragging, handleMouseMove, handleMouseUp]);
1613
+ const handleTouchStart = useCallback5((event) => {
1614
+ if (disabled) return;
1615
+ event.preventDefault();
1616
+ setIsDragging(true);
1617
+ onDragStart?.();
1618
+ const touch = event.touches[0];
1619
+ const newValue = getValueFromPosition(touch.clientX);
1620
+ onChange(newValue);
1621
+ }, [disabled, onDragStart, getValueFromPosition, onChange]);
1622
+ const handleTouchMove = useCallback5((event) => {
1623
+ if (!isDragging) return;
1624
+ event.preventDefault();
1625
+ const touch = event.touches[0];
1626
+ const newValue = getValueFromPosition(touch.clientX);
1627
+ onChange(newValue);
1628
+ }, [isDragging, getValueFromPosition, onChange]);
1629
+ const handleTouchEnd = useCallback5(() => {
1630
+ if (!isDragging) return;
1631
+ setIsDragging(false);
1632
+ onChangeEnd?.(valueRef.current);
1633
+ }, [isDragging, onChangeEnd]);
1634
+ React13.useEffect(() => {
1635
+ if (!isDragging) return;
1636
+ document.addEventListener("touchmove", handleTouchMove);
1637
+ document.addEventListener("touchend", handleTouchEnd);
1638
+ return () => {
1639
+ document.removeEventListener("touchmove", handleTouchMove);
1640
+ document.removeEventListener("touchend", handleTouchEnd);
1641
+ };
1642
+ }, [isDragging, handleTouchMove, handleTouchEnd]);
1643
+ const sliderClasses = [
1644
+ "slider",
1645
+ `slider--${type}`,
1646
+ isDragging && "slider--dragging",
1647
+ disabled && "slider--disabled",
1648
+ className
1649
+ ].filter(Boolean).join(" ");
1650
+ const getBackground = () => {
1651
+ switch (type) {
1652
+ case "hue":
1653
+ return "linear-gradient(to right, hsl(0, 70%, 50%), hsl(60, 70%, 50%), hsl(120, 70%, 50%), hsl(180, 70%, 50%), hsl(240, 70%, 50%), hsl(300, 70%, 50%), hsl(360, 70%, 50%))";
1654
+ case "saturation":
1655
+ return `linear-gradient(to right, hsl(${baseHue}, 0%, 50%), hsl(${baseHue}, 100%, 50%))`;
1656
+ case "lightness":
1657
+ return `linear-gradient(to right, hsl(${baseHue}, ${baseSaturation}%, 0%), hsl(${baseHue}, ${baseSaturation}%, 50%), hsl(${baseHue}, ${baseSaturation}%, 100%))`;
1658
+ default:
1659
+ return "var(--color-action-primary)";
1660
+ }
1661
+ };
1662
+ const inputStyle = { background: getBackground() };
1663
+ const stepMarks = step > 1 ? Array.from({ length: Math.floor((max - min) / step) + 1 }, (_, i) => min + i * step) : [];
1664
+ const thumbPosition = (value - min) / (max - min) * 100;
1665
+ return /* @__PURE__ */ jsxs13("div", { className: sliderClasses, children: [
1666
+ (label || showValue) && /* @__PURE__ */ jsxs13("div", { className: "slider__header", children: [
1667
+ label && /* @__PURE__ */ jsx21("label", { className: "slider__label", children: label }),
1668
+ showValue && /* @__PURE__ */ jsx21("span", { className: "slider__value", children: value })
1669
+ ] }),
1670
+ /* @__PURE__ */ jsxs13("div", { className: "slider__container", ref: containerRef, onMouseDown: handleMouseDown, onTouchStart: handleTouchStart, children: [
1671
+ /* @__PURE__ */ jsx21(
1672
+ "input",
1673
+ {
1674
+ ref: inputRef,
1675
+ type: "range",
1676
+ min,
1677
+ max,
1678
+ step,
1679
+ value,
1680
+ onChange: handleChange,
1681
+ className: "slider__input",
1682
+ style: inputStyle,
1683
+ disabled,
1684
+ readOnly: true
1685
+ }
1686
+ ),
1687
+ /* @__PURE__ */ jsx21(
1688
+ "div",
1689
+ {
1690
+ className: "slider__thumb",
1691
+ style: {
1692
+ left: `${thumbPosition}%`,
1693
+ transform: "translateX(-50%)"
1694
+ },
1695
+ children: /* @__PURE__ */ jsx21("div", { className: "slider__thumb-icon", children: /* @__PURE__ */ jsx21(Icon, { name: "arrow-down", size: 16 }) })
1696
+ }
1697
+ ),
1698
+ stepMarks.length > 0 && /* @__PURE__ */ jsx21("div", { className: "slider__marks", children: stepMarks.map((mark) => /* @__PURE__ */ jsx21(
1699
+ "div",
1700
+ {
1701
+ className: "slider__mark",
1702
+ style: {
1703
+ left: `${(mark - min) / (max - min) * 100}%`
1704
+ }
1705
+ },
1706
+ mark
1707
+ )) })
1708
+ ] })
1709
+ ] });
1710
+ };
1711
+
1712
+ // src/components/color-control/color-control.tsx
1713
+ import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
1714
+ var getCSSVariable = (variable) => {
1715
+ if (typeof window === "undefined") return 0;
1716
+ const value = getComputedStyle(document.documentElement).getPropertyValue(variable).trim();
1717
+ return value ? parseInt(value, 10) : 0;
1718
+ };
1719
+ var loadColorsFromCSS = () => {
1720
+ return {
1721
+ hues: {
1722
+ primary: getCSSVariable("--primary-hue"),
1723
+ secondary: getCSSVariable("--secondary-hue"),
1724
+ accent: getCSSVariable("--accent-hue"),
1725
+ success: getCSSVariable("--success-hue"),
1726
+ warning: getCSSVariable("--warning-hue"),
1727
+ error: getCSSVariable("--error-hue"),
1728
+ info: getCSSVariable("--info-hue")
1729
+ },
1730
+ saturations: {
1731
+ primary: getCSSVariable("--primary-saturation"),
1732
+ secondary: getCSSVariable("--secondary-saturation"),
1733
+ accent: getCSSVariable("--accent-saturation"),
1734
+ success: getCSSVariable("--success-saturation"),
1735
+ warning: getCSSVariable("--warning-saturation"),
1736
+ error: getCSSVariable("--error-saturation"),
1737
+ info: getCSSVariable("--info-saturation")
1738
+ },
1739
+ lightnesses: {
1740
+ primary: getCSSVariable("--primary-lightness"),
1741
+ secondary: getCSSVariable("--secondary-lightness"),
1742
+ accent: getCSSVariable("--accent-lightness"),
1743
+ success: getCSSVariable("--success-lightness"),
1744
+ warning: getCSSVariable("--warning-lightness"),
1745
+ error: getCSSVariable("--error-lightness"),
1746
+ info: getCSSVariable("--info-lightness")
1747
+ }
1748
+ };
1749
+ };
1750
+ var ColorControl = () => {
1751
+ const [colors, setColors] = useState9(() => {
1752
+ const saved = localStorage.getItem("color-config");
1753
+ return saved ? JSON.parse(saved) : loadColorsFromCSS();
1754
+ });
1755
+ const [pendingColors, setPendingColors] = useState9(colors);
1756
+ useEffect5(() => {
1757
+ const root = document.documentElement;
1758
+ root.style.setProperty("--hue-primary", colors.hues.primary.toString());
1759
+ root.style.setProperty("--hue-secondary", colors.hues.secondary.toString());
1760
+ root.style.setProperty("--hue-accent", colors.hues.accent.toString());
1761
+ root.style.setProperty("--hue-success", colors.hues.success.toString());
1762
+ root.style.setProperty("--hue-warning", colors.hues.warning.toString());
1763
+ root.style.setProperty("--hue-error", colors.hues.error.toString());
1764
+ root.style.setProperty("--hue-info", colors.hues.info.toString());
1765
+ root.style.setProperty("--saturation-primary", `${colors.saturations.primary}%`);
1766
+ root.style.setProperty("--saturation-secondary", `${colors.saturations.secondary}%`);
1767
+ root.style.setProperty("--saturation-accent", `${colors.saturations.accent}%`);
1768
+ root.style.setProperty("--saturation-success", `${colors.saturations.success}%`);
1769
+ root.style.setProperty("--saturation-warning", `${colors.saturations.warning}%`);
1770
+ root.style.setProperty("--saturation-error", `${colors.saturations.error}%`);
1771
+ root.style.setProperty("--saturation-info", `${colors.saturations.info}%`);
1772
+ root.style.setProperty("--lightness-primary", `${colors.lightnesses.primary}%`);
1773
+ root.style.setProperty("--lightness-secondary", `${colors.lightnesses.secondary}%`);
1774
+ root.style.setProperty("--lightness-accent", `${colors.lightnesses.accent}%`);
1775
+ root.style.setProperty("--lightness-success", `${colors.lightnesses.success}%`);
1776
+ root.style.setProperty("--lightness-warning", `${colors.lightnesses.warning}%`);
1777
+ root.style.setProperty("--lightness-error", `${colors.lightnesses.error}%`);
1778
+ root.style.setProperty("--lightness-info", `${colors.lightnesses.info}%`);
1779
+ }, []);
1780
+ const commitColorChange = useCallback6((color, property, value) => {
1781
+ setColors((prev) => {
1782
+ const newColors = {
1783
+ ...prev,
1784
+ [property === "hue" ? "hues" : property === "saturation" ? "saturations" : "lightnesses"]: {
1785
+ ...prev[property === "hue" ? "hues" : property === "saturation" ? "saturations" : "lightnesses"],
1786
+ [color]: value
1787
+ }
1788
+ };
1789
+ const root = document.documentElement;
1790
+ const cssVar = property === "hue" ? `--hue-${color}` : `--${property}-${color}`;
1791
+ const cssValue = property === "hue" ? value.toString() : `${value}%`;
1792
+ root.style.setProperty(cssVar, cssValue);
1793
+ localStorage.setItem("color-config", JSON.stringify(newColors));
1794
+ return newColors;
1795
+ });
1796
+ }, []);
1797
+ const resetToDefaults = useCallback6(() => {
1798
+ const cssColors = loadColorsFromCSS();
1799
+ setColors(cssColors);
1800
+ setPendingColors(cssColors);
1801
+ }, []);
1802
+ const renderColorControls = (colorName) => {
1803
+ const hue = pendingColors.hues[colorName];
1804
+ const saturation = pendingColors.saturations[colorName];
1805
+ const lightness = pendingColors.lightnesses[colorName];
1806
+ return /* @__PURE__ */ jsxs14("div", { className: "color-control__color-group", children: [
1807
+ /* @__PURE__ */ jsx22("h4", { className: "color-control__color-title", children: colorName.charAt(0).toUpperCase() + colorName.slice(1) }),
1808
+ /* @__PURE__ */ jsxs14("div", { className: "color-control__controls-row", children: [
1809
+ /* @__PURE__ */ jsxs14("div", { className: "color-control__control", children: [
1810
+ /* @__PURE__ */ jsx22("label", { className: "color-control__label", children: "Hue" }),
1811
+ /* @__PURE__ */ jsx22(
1812
+ Slider,
1813
+ {
1814
+ label: "",
1815
+ value: hue,
1816
+ min: 0,
1817
+ max: 360,
1818
+ step: 1,
1819
+ onChange: (v) => setPendingColors((prev) => ({
1820
+ ...prev,
1821
+ hues: { ...prev.hues, [colorName]: v }
1822
+ })),
1823
+ onChangeEnd: (v) => {
1824
+ setPendingColors((prev) => ({
1825
+ ...prev,
1826
+ hues: { ...prev.hues, [colorName]: v }
1827
+ }));
1828
+ commitColorChange(colorName, "hue", v);
1829
+ },
1830
+ type: "hue",
1831
+ showValue: false
1832
+ }
1833
+ )
1834
+ ] }),
1835
+ /* @__PURE__ */ jsxs14("div", { className: "color-control__control", children: [
1836
+ /* @__PURE__ */ jsx22("label", { className: "color-control__label", children: "Saturation" }),
1837
+ /* @__PURE__ */ jsx22(
1838
+ Slider,
1839
+ {
1840
+ label: "",
1841
+ value: saturation,
1842
+ min: 0,
1843
+ max: 100,
1844
+ step: 1,
1845
+ onChange: (v) => setPendingColors((prev) => ({
1846
+ ...prev,
1847
+ saturations: { ...prev.saturations, [colorName]: v }
1848
+ })),
1849
+ onChangeEnd: (v) => {
1850
+ setPendingColors((prev) => ({
1851
+ ...prev,
1852
+ saturations: { ...prev.saturations, [colorName]: v }
1853
+ }));
1854
+ commitColorChange(colorName, "saturation", v);
1855
+ },
1856
+ type: "saturation",
1857
+ baseHue: hue,
1858
+ showValue: false
1859
+ }
1860
+ )
1861
+ ] }),
1862
+ /* @__PURE__ */ jsxs14("div", { className: "color-control__control", children: [
1863
+ /* @__PURE__ */ jsx22("label", { className: "color-control__label", children: "Lightness" }),
1864
+ /* @__PURE__ */ jsx22(
1865
+ Slider,
1866
+ {
1867
+ label: "",
1868
+ value: lightness,
1869
+ min: 0,
1870
+ max: 100,
1871
+ step: 1,
1872
+ onChange: (v) => setPendingColors((prev) => ({
1873
+ ...prev,
1874
+ lightnesses: { ...prev.lightnesses, [colorName]: v }
1875
+ })),
1876
+ onChangeEnd: (v) => {
1877
+ setPendingColors((prev) => ({
1878
+ ...prev,
1879
+ lightnesses: { ...prev.lightnesses, [colorName]: v }
1880
+ }));
1881
+ commitColorChange(colorName, "lightness", v);
1882
+ },
1883
+ type: "lightness",
1884
+ baseHue: hue,
1885
+ baseSaturation: saturation,
1886
+ showValue: false
1887
+ }
1888
+ )
1889
+ ] }),
1890
+ /* @__PURE__ */ jsx22(
1891
+ "div",
1892
+ {
1893
+ className: "color-control__preview",
1894
+ style: {
1895
+ backgroundColor: `hsl(${hue}, ${saturation}%, ${lightness}%)`,
1896
+ border: "2px solid var(--color-neutral-300)"
1897
+ }
1898
+ }
1899
+ )
1900
+ ] })
1901
+ ] }, colorName);
1902
+ };
1903
+ return /* @__PURE__ */ jsxs14("div", { className: "color-control", children: [
1904
+ /* @__PURE__ */ jsxs14("div", { className: "color-control__header", children: [
1905
+ /* @__PURE__ */ jsx22("h3", { className: "color-control__title", children: "Paleta de Cores" }),
1906
+ /* @__PURE__ */ jsx22("p", { className: "color-control__description", children: "Ajuste o matiz, satura\xE7\xE3o e luminosidade das cores. As mudan\xE7as s\xE3o aplicadas instantaneamente." })
1907
+ ] }),
1908
+ /* @__PURE__ */ jsxs14("div", { className: "color-control__sliders", children: [
1909
+ renderColorControls("primary"),
1910
+ renderColorControls("secondary"),
1911
+ renderColorControls("accent"),
1912
+ renderColorControls("success"),
1913
+ renderColorControls("warning"),
1914
+ renderColorControls("error"),
1915
+ renderColorControls("info")
1916
+ ] }),
1917
+ /* @__PURE__ */ jsx22("div", { className: "color-control__actions", children: /* @__PURE__ */ jsx22(
1918
+ "button",
1919
+ {
1920
+ onClick: resetToDefaults,
1921
+ className: "color-control__reset-btn",
1922
+ children: "Restaurar Padr\xF5es"
1923
+ }
1924
+ ) }),
1925
+ /* @__PURE__ */ jsxs14("div", { className: "color-control__preview-section", children: [
1926
+ /* @__PURE__ */ jsx22("h4", { className: "color-control__preview-title", children: "Pr\xE9via das Cores" }),
1927
+ /* @__PURE__ */ jsxs14("div", { className: "color-control__color-grid", children: [
1928
+ /* @__PURE__ */ jsx22(
1929
+ "div",
1930
+ {
1931
+ className: "color-control__color-sample",
1932
+ style: { backgroundColor: `hsl(${pendingColors.hues.primary}, ${pendingColors.saturations.primary}%, ${pendingColors.lightnesses.primary}%)` },
1933
+ children: "Primary"
1934
+ }
1935
+ ),
1936
+ /* @__PURE__ */ jsx22(
1937
+ "div",
1938
+ {
1939
+ className: "color-control__color-sample",
1940
+ style: { backgroundColor: `hsl(${pendingColors.hues.secondary}, ${pendingColors.saturations.secondary}%, ${pendingColors.lightnesses.secondary}%)` },
1941
+ children: "Secondary"
1942
+ }
1943
+ ),
1944
+ /* @__PURE__ */ jsx22(
1945
+ "div",
1946
+ {
1947
+ className: "color-control__color-sample",
1948
+ style: { backgroundColor: `hsl(${pendingColors.hues.accent}, ${pendingColors.saturations.accent}%, ${pendingColors.lightnesses.accent}%)` },
1949
+ children: "Accent"
1950
+ }
1951
+ ),
1952
+ /* @__PURE__ */ jsx22(
1953
+ "div",
1954
+ {
1955
+ className: "color-control__color-sample",
1956
+ style: { backgroundColor: `hsl(${pendingColors.hues.success}, ${pendingColors.saturations.success}%, ${pendingColors.lightnesses.success}%)` },
1957
+ children: "Success"
1958
+ }
1959
+ ),
1960
+ /* @__PURE__ */ jsx22(
1961
+ "div",
1962
+ {
1963
+ className: "color-control__color-sample",
1964
+ style: { backgroundColor: `hsl(${pendingColors.hues.warning}, ${pendingColors.saturations.warning}%, ${pendingColors.lightnesses.warning}%)` },
1965
+ children: "Warning"
1966
+ }
1967
+ ),
1968
+ /* @__PURE__ */ jsx22(
1969
+ "div",
1970
+ {
1971
+ className: "color-control__color-sample",
1972
+ style: { backgroundColor: `hsl(${pendingColors.hues.error}, ${pendingColors.saturations.error}%, ${pendingColors.lightnesses.error}%)` },
1973
+ children: "Error"
1974
+ }
1975
+ ),
1976
+ /* @__PURE__ */ jsx22(
1977
+ "div",
1978
+ {
1979
+ className: "color-control__color-sample",
1980
+ style: { backgroundColor: `hsl(${pendingColors.hues.info}, ${pendingColors.saturations.info}%, ${pendingColors.lightnesses.info}%)` },
1981
+ children: "Info"
1982
+ }
1983
+ )
1984
+ ] })
1985
+ ] })
1986
+ ] });
1987
+ };
1988
+
1989
+ // src/components/grid/Grid.tsx
1990
+ import { jsx as jsx23 } from "react/jsx-runtime";
1991
+ var Grid = ({
1992
+ columns = "auto-fit",
1993
+ minWidth = "250px",
1994
+ gap = "1rem",
1995
+ maxColumns,
1996
+ className = "",
1997
+ children,
1998
+ ...props
1999
+ }) => {
2000
+ const gridClass = [
2001
+ "grid",
2002
+ typeof columns === "number" ? `grid--cols-${Math.min(columns, maxColumns || columns)}` : `grid--${columns}`,
2003
+ className
2004
+ ].filter(Boolean).join(" ");
2005
+ const style = {
2006
+ "--grid-min-width": minWidth,
2007
+ "--grid-gap": gap
2008
+ };
2009
+ return /* @__PURE__ */ jsx23("div", { className: gridClass, style, ...props, children });
2010
+ };
2011
+
2012
+ // src/components/footer/footer.tsx
2013
+ import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
2014
+ var Footer = ({ className = "", children, ...props }) => {
2015
+ const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
2016
+ return /* @__PURE__ */ jsx24("footer", { className: `footer ${className}`.trim(), ...props, children: /* @__PURE__ */ jsx24("div", { className: "footer__container", children: children ? children : /* @__PURE__ */ jsx24(Fragment6, { children: /* @__PURE__ */ jsx24("div", { className: "footer__bottom", children: /* @__PURE__ */ jsxs15("p", { className: "footer__copyright", children: [
2017
+ "\xA9 ",
2018
+ currentYear,
2019
+ " ",
2020
+ /* @__PURE__ */ jsx24("strong", { children: "HellboyDS" }),
2021
+ " is a design system package published on npm by user ",
2022
+ /* @__PURE__ */ jsx24("strong", { children: "@hellboy" }),
2023
+ ". This project is not affiliated with any comic book, film, television, or other artistic works."
2024
+ ] }) }) }) }) });
2025
+ };
2026
+
2027
+ // src/components/input/InputText.tsx
2028
+ import React19 from "react";
2029
+
2030
+ // src/components/input/Input.tsx
2031
+ import * as React18 from "react";
2032
+
2033
+ // src/components/input/InputField.tsx
2034
+ import * as React15 from "react";
2035
+ import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
2036
+ var InputField = React15.forwardRef(
2037
+ ({
2038
+ type = "text",
2039
+ label,
2040
+ helperText,
2041
+ error,
2042
+ icon,
2043
+ iconRight,
2044
+ fullWidth = false,
2045
+ size = "md",
2046
+ className = "",
2047
+ disabled,
2048
+ id,
2049
+ onRightIconClick,
2050
+ ...props
2051
+ }, ref) => {
2052
+ const inputId = id || `input-${React15.useId()}`;
2053
+ const containerClasses = [
2054
+ "input-container",
2055
+ fullWidth && "input-container--full-width",
2056
+ className
2057
+ ].filter(Boolean).join(" ");
2058
+ const inputClasses = [
2059
+ "input",
2060
+ `input--${size}`,
2061
+ error && "input--error",
2062
+ disabled && "input--disabled",
2063
+ icon && "input--has-icon-left",
2064
+ iconRight && "input--has-icon-right"
2065
+ ].filter(Boolean).join(" ");
2066
+ return /* @__PURE__ */ jsxs16("div", { className: containerClasses, children: [
2067
+ label && /* @__PURE__ */ jsx25("label", { htmlFor: inputId, className: "input__label", children: label }),
2068
+ /* @__PURE__ */ jsxs16("div", { className: "input__wrapper", children: [
2069
+ icon && /* @__PURE__ */ jsx25("span", { className: "input__icon input__icon--left", "aria-hidden": "true", children: /* @__PURE__ */ jsx25(Icon, { name: icon, size: 16 }) }),
2070
+ /* @__PURE__ */ jsx25(
2071
+ "input",
2072
+ {
2073
+ ref,
2074
+ type,
2075
+ id: inputId,
2076
+ className: inputClasses,
2077
+ disabled,
2078
+ ...props
2079
+ }
2080
+ ),
2081
+ iconRight && /* @__PURE__ */ jsx25(
2082
+ "button",
2083
+ {
2084
+ type: "button",
2085
+ className: "input__icon input__icon--right",
2086
+ onClick: onRightIconClick,
2087
+ tabIndex: -1,
2088
+ "aria-label": "Icon action",
2089
+ children: /* @__PURE__ */ jsx25(Icon, { name: iconRight, size: 16 })
2090
+ }
2091
+ )
2092
+ ] }),
2093
+ error && /* @__PURE__ */ jsx25("p", { className: "input__message input__message--error", children: error }),
2094
+ helperText && !error && /* @__PURE__ */ jsx25("p", { className: "input__message", children: helperText })
2095
+ ] });
2096
+ }
2097
+ );
2098
+
2099
+ // src/components/input/DatePicker.tsx
2100
+ import * as React16 from "react";
2101
+ import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
2102
+ var MONTHS = [
2103
+ "January",
2104
+ "February",
2105
+ "March",
2106
+ "April",
2107
+ "May",
2108
+ "June",
2109
+ "July",
2110
+ "August",
2111
+ "September",
2112
+ "October",
2113
+ "November",
2114
+ "December"
2115
+ ];
2116
+ var DAYS_OF_WEEK = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
2117
+ var DatePicker = ({ value, onChange, disabled }) => {
2118
+ const parseDate = (dateStr) => {
2119
+ if (!dateStr) {
2120
+ const today = /* @__PURE__ */ new Date();
2121
+ return { year: today.getFullYear(), month: today.getMonth(), day: today.getDate() };
2122
+ }
2123
+ const [year, month, day] = dateStr.split("-").map(Number);
2124
+ return { year, month: month - 1, day };
2125
+ };
2126
+ const { year: initialYear, month: initialMonth, day: selectedDay } = parseDate(value);
2127
+ const [currentYear, setCurrentYear] = React16.useState(initialYear);
2128
+ const [currentMonth, setCurrentMonth] = React16.useState(initialMonth);
2129
+ const getDaysInMonth = (year, month) => {
2130
+ return new Date(year, month + 1, 0).getDate();
2131
+ };
2132
+ const getFirstDayOfMonth = (year, month) => {
2133
+ return new Date(year, month, 1).getDay();
2134
+ };
2135
+ const handleDateSelect = (day) => {
2136
+ if (disabled) return;
2137
+ const formattedDate = `${currentYear}-${String(currentMonth + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
2138
+ onChange(formattedDate);
2139
+ };
2140
+ const handlePrevMonth = () => {
2141
+ if (currentMonth === 0) {
2142
+ setCurrentMonth(11);
2143
+ setCurrentYear(currentYear - 1);
2144
+ } else {
2145
+ setCurrentMonth(currentMonth - 1);
2146
+ }
2147
+ };
2148
+ const handleNextMonth = () => {
2149
+ if (currentMonth === 11) {
2150
+ setCurrentMonth(0);
2151
+ setCurrentYear(currentYear + 1);
2152
+ } else {
2153
+ setCurrentMonth(currentMonth + 1);
2154
+ }
2155
+ };
2156
+ const daysInMonth = getDaysInMonth(currentYear, currentMonth);
2157
+ const firstDay = getFirstDayOfMonth(currentYear, currentMonth);
2158
+ const days = [
2159
+ ...Array(firstDay).fill(null),
2160
+ ...Array.from({ length: daysInMonth }, (_, i) => i + 1)
2161
+ ];
2162
+ return /* @__PURE__ */ jsxs17("div", { className: "date-picker", children: [
2163
+ /* @__PURE__ */ jsxs17("div", { className: "date-picker__header", children: [
2164
+ /* @__PURE__ */ jsx26(
2165
+ "button",
2166
+ {
2167
+ type: "button",
2168
+ className: "date-picker__nav",
2169
+ onClick: handlePrevMonth,
2170
+ disabled,
2171
+ "aria-label": "Previous month",
2172
+ children: "\u2039"
2173
+ }
2174
+ ),
2175
+ /* @__PURE__ */ jsxs17("div", { className: "date-picker__title", children: [
2176
+ /* @__PURE__ */ jsx26(
2177
+ "select",
2178
+ {
2179
+ className: "date-picker__select",
2180
+ value: currentMonth,
2181
+ onChange: (e) => setCurrentMonth(Number(e.target.value)),
2182
+ disabled,
2183
+ children: MONTHS.map((month, idx) => /* @__PURE__ */ jsx26("option", { value: idx, children: month }, month))
2184
+ }
2185
+ ),
2186
+ /* @__PURE__ */ jsx26(
2187
+ "select",
2188
+ {
2189
+ className: "date-picker__select",
2190
+ value: currentYear,
2191
+ onChange: (e) => setCurrentYear(Number(e.target.value)),
2192
+ disabled,
2193
+ children: Array.from({ length: 100 }, (_, i) => currentYear - 50 + i).map((year) => /* @__PURE__ */ jsx26("option", { value: year, children: year }, year))
2194
+ }
2195
+ )
2196
+ ] }),
2197
+ /* @__PURE__ */ jsx26(
2198
+ "button",
2199
+ {
2200
+ type: "button",
2201
+ className: "date-picker__nav",
2202
+ onClick: handleNextMonth,
2203
+ disabled,
2204
+ "aria-label": "Next month",
2205
+ children: "\u203A"
2206
+ }
2207
+ )
2208
+ ] }),
2209
+ /* @__PURE__ */ jsx26("div", { className: "date-picker__weekdays", children: DAYS_OF_WEEK.map((day) => /* @__PURE__ */ jsx26("div", { className: "date-picker__weekday", children: day }, day)) }),
2210
+ /* @__PURE__ */ jsx26("div", { className: "date-picker__days", children: days.map((day, idx) => /* @__PURE__ */ jsx26(
2211
+ "button",
2212
+ {
2213
+ type: "button",
2214
+ className: `date-picker__day ${day === selectedDay ? "date-picker__day--selected" : ""} ${!day ? "date-picker__day--empty" : ""}`,
2215
+ onClick: () => day && handleDateSelect(day),
2216
+ disabled: !day || disabled,
2217
+ children: day || ""
2218
+ },
2219
+ idx
2220
+ )) })
2221
+ ] });
2222
+ };
2223
+
2224
+ // src/components/input/TimePicker.tsx
2225
+ import * as React17 from "react";
2226
+ import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
2227
+ var parseTime = (timeStr) => {
2228
+ if (!timeStr) return { hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };
2229
+ const parts = timeStr.split(":");
2230
+ const hours = parseInt(parts[0] || "0", 10);
2231
+ const minutes = parseInt(parts[1] || "0", 10);
2232
+ const secondsParts = (parts[2] || "0").split(".");
2233
+ const seconds = parseInt(secondsParts[0] || "0", 10);
2234
+ const milliseconds = parseInt(secondsParts[1] || "0", 10);
2235
+ return { hours, minutes, seconds, milliseconds };
2236
+ };
2237
+ var TimeColumn = ({
2238
+ label,
2239
+ value,
2240
+ max,
2241
+ field,
2242
+ step,
2243
+ disabled,
2244
+ onChange
2245
+ }) => {
2246
+ const items = Array.from({ length: Math.floor(max / step) + 1 }, (_, i) => i * step);
2247
+ const columnRef = React17.useRef(null);
2248
+ React17.useEffect(() => {
2249
+ if (columnRef.current) {
2250
+ const selected = columnRef.current.querySelector(".time-picker__item--selected");
2251
+ if (selected) {
2252
+ selected.scrollIntoView({ block: "center", behavior: "smooth" });
2253
+ }
2254
+ }
2255
+ }, [value]);
2256
+ return /* @__PURE__ */ jsxs18("div", { className: "time-picker__column", children: [
2257
+ /* @__PURE__ */ jsx27("div", { className: "time-picker__label", children: label }),
2258
+ /* @__PURE__ */ jsx27("div", { className: "time-picker__scroll", ref: columnRef, children: items.map((item) => /* @__PURE__ */ jsx27(
2259
+ "button",
2260
+ {
2261
+ type: "button",
2262
+ className: `time-picker__item ${item === value ? "time-picker__item--selected" : ""}`,
2263
+ onClick: () => onChange(field, item),
2264
+ disabled,
2265
+ children: String(item).padStart(field === "milliseconds" ? 3 : 2, "0")
2266
+ },
2267
+ item
2268
+ )) })
2269
+ ] });
2270
+ };
2271
+ var TimePicker = ({
2272
+ value,
2273
+ onChange,
2274
+ disabled,
2275
+ showMilliseconds = false,
2276
+ minuteStep = 1
2277
+ }) => {
2278
+ const [internalTime, setInternalTime] = React17.useState(value);
2279
+ React17.useEffect(() => {
2280
+ setInternalTime(value);
2281
+ }, [value]);
2282
+ const { hours, minutes, seconds, milliseconds } = parseTime(internalTime);
2283
+ const handleChange = (field, newValue) => {
2284
+ if (disabled) return;
2285
+ const currentParsed = parseTime(internalTime);
2286
+ const updated = { ...currentParsed, [field]: newValue };
2287
+ let formattedTime = `${String(updated.hours).padStart(2, "0")}:${String(updated.minutes).padStart(2, "0")}:${String(updated.seconds).padStart(2, "0")}`;
2288
+ if (showMilliseconds && updated.milliseconds > 0) {
2289
+ formattedTime += `.${String(updated.milliseconds).padStart(3, "0")}`;
2290
+ }
2291
+ setInternalTime(formattedTime);
2292
+ onChange(formattedTime);
2293
+ };
2294
+ return /* @__PURE__ */ jsxs18("div", { className: "time-picker", children: [
2295
+ /* @__PURE__ */ jsx27(
2296
+ TimeColumn,
2297
+ {
2298
+ label: "Hours",
2299
+ value: hours,
2300
+ max: 23,
2301
+ field: "hours",
2302
+ step: 1,
2303
+ disabled,
2304
+ onChange: handleChange
2305
+ }
2306
+ ),
2307
+ /* @__PURE__ */ jsx27(
2308
+ TimeColumn,
2309
+ {
2310
+ label: "Minutes",
2311
+ value: minutes,
2312
+ max: 59,
2313
+ field: "minutes",
2314
+ step: minuteStep,
2315
+ disabled,
2316
+ onChange: handleChange
2317
+ }
2318
+ ),
2319
+ /* @__PURE__ */ jsx27(
2320
+ TimeColumn,
2321
+ {
2322
+ label: "Seconds",
2323
+ value: seconds,
2324
+ max: 59,
2325
+ field: "seconds",
2326
+ step: 1,
2327
+ disabled,
2328
+ onChange: handleChange
2329
+ }
2330
+ ),
2331
+ showMilliseconds && /* @__PURE__ */ jsx27(
2332
+ TimeColumn,
2333
+ {
2334
+ label: "ms",
2335
+ value: milliseconds,
2336
+ max: 999,
2337
+ field: "milliseconds",
2338
+ step: 1,
2339
+ disabled,
2340
+ onChange: handleChange
2341
+ }
2342
+ )
2343
+ ] });
2344
+ };
2345
+
2346
+ // src/components/input/Input.tsx
2347
+ import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
2348
+ var TYPE_ICON_MAP = {
2349
+ email: "mail",
2350
+ password: "lock-closed",
2351
+ search: "search",
2352
+ date: "calendar",
2353
+ time: "time",
2354
+ "datetime-local": "calendar",
2355
+ tel: "call",
2356
+ url: "link"
2357
+ };
2358
+ var formatDisplayValue = (val, inputType) => {
2359
+ if (!val) return "";
2360
+ if (inputType === "date") {
2361
+ const [year, month, day] = val.split("-");
2362
+ return `${day}/${month}/${year}`;
2363
+ }
2364
+ if (inputType === "time") {
2365
+ return val;
2366
+ }
2367
+ if (inputType === "datetime-local") {
2368
+ const [datePart, timePart] = val.split("T");
2369
+ if (datePart && timePart) {
2370
+ const [year, month, day] = datePart.split("-");
2371
+ return `${day}/${month}/${year} ${timePart}`;
2372
+ }
2373
+ return val;
2374
+ }
2375
+ return val;
2376
+ };
2377
+ var Input = React18.forwardRef(
2378
+ ({
2379
+ type = "text",
2380
+ label,
2381
+ helperText,
2382
+ error,
2383
+ icon,
2384
+ fullWidth = false,
2385
+ size = "md",
2386
+ className = "",
2387
+ disabled,
2388
+ id,
2389
+ showMilliseconds = false,
2390
+ minuteStep = 1,
2391
+ showClear = true,
2392
+ ...props
2393
+ }, ref) => {
2394
+ const [showPassword, setShowPassword] = React18.useState(false);
2395
+ const [showDateTimePicker, setShowDateTimePicker] = React18.useState(false);
2396
+ const inputRef = React18.useRef(null);
2397
+ const leftIcon = icon || TYPE_ICON_MAP[type];
2398
+ const isPasswordType = type === "password";
2399
+ const actualType = isPasswordType && showPassword ? "text" : type !== "date" && type !== "time" && type !== "datetime-local" ? type : "text";
2400
+ const isDateTimeType = type === "date" || type === "time" || type === "datetime-local";
2401
+ const isSearchType = type === "search";
2402
+ const hasValue = props.value && String(props.value).length > 0;
2403
+ const rightIconName = isPasswordType ? showPassword ? "eye-off" : "eye" : isDateTimeType ? "chevron-down" : isSearchType && hasValue && showClear ? "x" : void 0;
2404
+ const handleRightIconClick = () => {
2405
+ if (isPasswordType) {
2406
+ setShowPassword(!showPassword);
2407
+ } else if (isDateTimeType) {
2408
+ setShowDateTimePicker(!showDateTimePicker);
2409
+ } else if (isSearchType && hasValue && showClear) {
2410
+ if (props.onChange) {
2411
+ props.onChange({ target: { value: "" } });
2412
+ }
2413
+ }
2414
+ };
2415
+ const handleDateTimeChange = (newValue) => {
2416
+ if (props.onChange) {
2417
+ props.onChange({ target: { value: newValue } });
2418
+ }
2419
+ };
2420
+ if (!isDateTimeType) {
2421
+ return /* @__PURE__ */ jsx28(
2422
+ InputField,
2423
+ {
2424
+ ref: ref || inputRef,
2425
+ type: actualType,
2426
+ label,
2427
+ helperText,
2428
+ error,
2429
+ icon: leftIcon,
2430
+ iconRight: rightIconName,
2431
+ onRightIconClick: handleRightIconClick,
2432
+ fullWidth,
2433
+ size,
2434
+ className,
2435
+ disabled,
2436
+ id,
2437
+ ...props
2438
+ }
2439
+ );
2440
+ }
2441
+ return /* @__PURE__ */ jsxs19("div", { className: `input-container ${fullWidth ? "input-container--full-width" : ""} ${className}`.trim(), children: [
2442
+ label && /* @__PURE__ */ jsx28("label", { htmlFor: id, className: "input__label", children: label }),
2443
+ /* @__PURE__ */ jsx28(
2444
+ Popover,
2445
+ {
2446
+ trigger: /* @__PURE__ */ jsx28(
2447
+ InputField,
2448
+ {
2449
+ ref: ref || inputRef,
2450
+ type: "text",
2451
+ icon: leftIcon,
2452
+ iconRight: rightIconName,
2453
+ onRightIconClick: () => setShowDateTimePicker(!showDateTimePicker),
2454
+ fullWidth,
2455
+ size,
2456
+ disabled,
2457
+ id,
2458
+ value: formatDisplayValue(String(props.value || ""), type),
2459
+ placeholder: props.placeholder,
2460
+ readOnly: true
2461
+ }
2462
+ ),
2463
+ isOpen: showDateTimePicker,
2464
+ onToggle: () => setShowDateTimePicker(!showDateTimePicker),
2465
+ placement: "bottom",
2466
+ children: /* @__PURE__ */ jsxs19("div", { style: { padding: "1rem" }, children: [
2467
+ (type === "date" || type === "datetime-local") && /* @__PURE__ */ jsx28(
2468
+ DatePicker,
2469
+ {
2470
+ value: String(props.value || "").split("T")[0],
2471
+ onChange: (newDate) => {
2472
+ if (type === "datetime-local") {
2473
+ const time = String(props.value || "").split("T")[1] || "00:00:00";
2474
+ handleDateTimeChange(`${newDate}T${time}`);
2475
+ } else {
2476
+ handleDateTimeChange(newDate);
2477
+ setShowDateTimePicker(false);
2478
+ }
2479
+ },
2480
+ disabled
2481
+ }
2482
+ ),
2483
+ (type === "time" || type === "datetime-local") && /* @__PURE__ */ jsx28(
2484
+ TimePicker,
2485
+ {
2486
+ value: String(props.value || "").split("T")[1] || "00:00:00",
2487
+ onChange: (newTime) => {
2488
+ if (type === "datetime-local") {
2489
+ const date = String(props.value || "").split("T")[0] || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2490
+ handleDateTimeChange(`${date}T${newTime}`);
2491
+ } else {
2492
+ handleDateTimeChange(newTime);
2493
+ }
2494
+ },
2495
+ disabled,
2496
+ showMilliseconds,
2497
+ minuteStep
2498
+ }
2499
+ )
2500
+ ] })
2501
+ }
2502
+ ),
2503
+ error && /* @__PURE__ */ jsx28("p", { className: "input__message input__message--error", children: error }),
2504
+ helperText && !error && /* @__PURE__ */ jsx28("p", { className: "input__message", children: helperText })
2505
+ ] });
2506
+ }
2507
+ );
2508
+ Input.displayName = "Input";
2509
+
2510
+ // src/components/input/InputText.tsx
2511
+ import { jsx as jsx29 } from "react/jsx-runtime";
2512
+ var InputText = React19.forwardRef((props, ref) => {
2513
+ return /* @__PURE__ */ jsx29(Input, { ref, ...props, type: "text" });
2514
+ });
2515
+ InputText.displayName = "InputText";
2516
+
2517
+ // src/components/input/InputEmail.tsx
2518
+ import React20 from "react";
2519
+ import { jsx as jsx30 } from "react/jsx-runtime";
2520
+ var InputEmail = React20.forwardRef((props, ref) => {
2521
+ return /* @__PURE__ */ jsx30(Input, { ref, ...props, type: "email" });
2522
+ });
2523
+ InputEmail.displayName = "InputEmail";
2524
+
2525
+ // src/components/input/InputPassword.tsx
2526
+ import React21 from "react";
2527
+ import { jsx as jsx31 } from "react/jsx-runtime";
2528
+ var InputPassword = React21.forwardRef((props, ref) => {
2529
+ return /* @__PURE__ */ jsx31(Input, { ref, ...props, type: "password" });
2530
+ });
2531
+ InputPassword.displayName = "InputPassword";
2532
+
2533
+ // src/components/input/InputSearch.tsx
2534
+ import React22 from "react";
2535
+ import { jsx as jsx32 } from "react/jsx-runtime";
2536
+ var InputSearch = React22.forwardRef((props, ref) => {
2537
+ return /* @__PURE__ */ jsx32(Input, { ref, ...props, type: "search" });
2538
+ });
2539
+ InputSearch.displayName = "InputSearch";
2540
+
2541
+ // src/components/input/InputTel.tsx
2542
+ import React23 from "react";
2543
+ import { jsx as jsx33 } from "react/jsx-runtime";
2544
+ var InputTel = React23.forwardRef((props, ref) => {
2545
+ return /* @__PURE__ */ jsx33(Input, { ref, ...props, type: "tel" });
2546
+ });
2547
+ InputTel.displayName = "InputTel";
2548
+
2549
+ // src/components/input/InputUrl.tsx
2550
+ import React24 from "react";
2551
+ import { jsx as jsx34 } from "react/jsx-runtime";
2552
+ var InputUrl = React24.forwardRef((props, ref) => {
2553
+ return /* @__PURE__ */ jsx34(Input, { ref, ...props, type: "url" });
2554
+ });
2555
+ InputUrl.displayName = "InputUrl";
2556
+
2557
+ // src/components/input/InputNumber.tsx
2558
+ import React25 from "react";
2559
+ import { jsx as jsx35 } from "react/jsx-runtime";
2560
+ var InputNumber = React25.forwardRef((props, ref) => {
2561
+ return /* @__PURE__ */ jsx35(Input, { ref, ...props, type: "number" });
2562
+ });
2563
+ InputNumber.displayName = "InputNumber";
2564
+
2565
+ // src/components/input/InputDate.tsx
2566
+ import React26 from "react";
2567
+ import { jsx as jsx36 } from "react/jsx-runtime";
2568
+ var InputDate = React26.forwardRef((props, ref) => {
2569
+ return /* @__PURE__ */ jsx36(Input, { ref, ...props, type: "date" });
2570
+ });
2571
+ InputDate.displayName = "InputDate";
2572
+
2573
+ // src/components/input/InputTime.tsx
2574
+ import React27 from "react";
2575
+ import { jsx as jsx37 } from "react/jsx-runtime";
2576
+ var InputTime = React27.forwardRef((props, ref) => {
2577
+ return /* @__PURE__ */ jsx37(Input, { ref, ...props, type: "time" });
2578
+ });
2579
+ InputTime.displayName = "InputTime";
2580
+
2581
+ // src/components/input/InputDateTime.tsx
2582
+ import React28 from "react";
2583
+ import { jsx as jsx38 } from "react/jsx-runtime";
2584
+ var InputDateTime = React28.forwardRef((props, ref) => {
2585
+ return /* @__PURE__ */ jsx38(Input, { ref, ...props, type: "datetime-local" });
2586
+ });
2587
+ InputDateTime.displayName = "InputDateTime";
2588
+
2589
+ // src/components/list/List.tsx
2590
+ import { jsx as jsx39, jsxs as jsxs20 } from "react/jsx-runtime";
2591
+ var ListItem = ({
2592
+ children,
2593
+ icon,
2594
+ selected = false,
2595
+ disabled = false,
2596
+ onClick,
2597
+ category,
2598
+ className = "",
2599
+ ...props
2600
+ }) => {
2601
+ const classes = [
2602
+ "list-item",
2603
+ selected && "list-item--selected",
2604
+ disabled && "list-item--disabled",
2605
+ onClick && !disabled && "list-item--interactive",
2606
+ className
2607
+ ].filter(Boolean).join(" ");
2608
+ const handleClick = () => {
2609
+ if (!disabled && onClick) {
2610
+ onClick();
2611
+ }
2612
+ };
2613
+ const handleKeyDown = (e) => {
2614
+ if (!disabled && onClick && (e.key === "Enter" || e.key === " ")) {
2615
+ e.preventDefault();
2616
+ onClick();
2617
+ }
2618
+ };
2619
+ return /* @__PURE__ */ jsxs20(
2620
+ "div",
2621
+ {
2622
+ className: classes,
2623
+ onClick: handleClick,
2624
+ onKeyDown: handleKeyDown,
2625
+ role: onClick ? "button" : void 0,
2626
+ tabIndex: onClick && !disabled ? 0 : void 0,
2627
+ "aria-selected": selected,
2628
+ "aria-disabled": disabled,
2629
+ ...props,
2630
+ children: [
2631
+ icon && /* @__PURE__ */ jsx39("div", { className: "list-item__icon", children: /* @__PURE__ */ jsx39(Icon, { name: icon, size: 20 }) }),
2632
+ /* @__PURE__ */ jsxs20("div", { className: "list-item__content", children: [
2633
+ category && /* @__PURE__ */ jsx39("div", { className: "list-item__category", children: category }),
2634
+ /* @__PURE__ */ jsx39("div", { children })
2635
+ ] }),
2636
+ selected && /* @__PURE__ */ jsx39("div", { className: "list-item__indicator", children: /* @__PURE__ */ jsx39(Icon, { name: "checkmark", size: 16 }) })
2637
+ ]
2638
+ }
2639
+ );
2640
+ };
2641
+ var List = ({ children, className = "", ...props }) => {
2642
+ const classes = ["list", className].filter(Boolean).join(" ");
2643
+ return /* @__PURE__ */ jsx39("div", { className: classes, role: "list", ...props, children });
2644
+ };
2645
+
2646
+ // src/components/radio/Radio.tsx
2647
+ import React29 from "react";
2648
+ import { Radio as AriakitRadio, RadioGroup as AriakitRadioGroup, useRadioStore } from "@ariakit/react";
2649
+ import { jsx as jsx40, jsxs as jsxs21 } from "react/jsx-runtime";
2650
+ var Radio = React29.forwardRef(
2651
+ ({
2652
+ size = "md",
2653
+ label,
2654
+ error = false,
2655
+ disabled = false,
2656
+ className,
2657
+ ...props
2658
+ }, ref) => {
2659
+ const radioClasses = [
2660
+ "radio",
2661
+ `radio--${size}`,
2662
+ error && "radio--error",
2663
+ disabled && "radio--disabled",
2664
+ className
2665
+ ].filter(Boolean).join(" ");
2666
+ return /* @__PURE__ */ jsxs21("label", { className: radioClasses, children: [
2667
+ /* @__PURE__ */ jsx40(
2668
+ AriakitRadio,
2669
+ {
2670
+ ref,
2671
+ disabled,
2672
+ className: "radio__input",
2673
+ ...props
2674
+ }
2675
+ ),
2676
+ /* @__PURE__ */ jsx40("span", { className: "radio__box", children: /* @__PURE__ */ jsx40("span", { className: "radio__dot" }) }),
2677
+ label && /* @__PURE__ */ jsx40("span", { className: "radio__label", children: label })
2678
+ ] });
2679
+ }
2680
+ );
2681
+ Radio.displayName = "Radio";
2682
+ var RadioGroup = React29.forwardRef(
2683
+ ({
2684
+ size = "md",
2685
+ label,
2686
+ error,
2687
+ helperText,
2688
+ children,
2689
+ orientation = "vertical",
2690
+ disabled = false,
2691
+ className,
2692
+ value,
2693
+ onChange,
2694
+ ...props
2695
+ }, ref) => {
2696
+ const groupClasses = [
2697
+ "radio-group",
2698
+ `radio-group--${orientation}`,
2699
+ error && "radio-group--error",
2700
+ disabled && "radio-group--disabled",
2701
+ className
2702
+ ].filter(Boolean).join(" ");
2703
+ const radioGroupStore = useRadioStore({
2704
+ value,
2705
+ setValue: onChange
2706
+ });
2707
+ const childrenWithProps = React29.Children.map(children, (child) => {
2708
+ if (React29.isValidElement(child) && child.type === Radio) {
2709
+ return React29.cloneElement(child, {
2710
+ size: child.props.size || size,
2711
+ error: error ? true : child.props.error,
2712
+ disabled: disabled || child.props.disabled
2713
+ });
2714
+ }
2715
+ return child;
2716
+ });
2717
+ return /* @__PURE__ */ jsxs21("div", { className: groupClasses, children: [
2718
+ label && /* @__PURE__ */ jsx40("div", { className: "radio-group__label", children: label }),
2719
+ /* @__PURE__ */ jsx40(
2720
+ AriakitRadioGroup,
2721
+ {
2722
+ ref,
2723
+ store: radioGroupStore,
2724
+ className: "radio-group__container",
2725
+ ...props,
2726
+ children: childrenWithProps
2727
+ }
2728
+ ),
2729
+ (error || helperText) && /* @__PURE__ */ jsxs21("div", { className: "radio-group__feedback", children: [
2730
+ error && /* @__PURE__ */ jsx40("span", { className: "radio-group__error-text", children: error }),
2731
+ !error && helperText && /* @__PURE__ */ jsx40("span", { className: "radio-group__helper-text", children: helperText })
2732
+ ] })
2733
+ ] });
2734
+ }
2735
+ );
2736
+ RadioGroup.displayName = "RadioGroup";
2737
+
2738
+ // src/components/select/Select.tsx
2739
+ import * as React30 from "react";
2740
+ import { jsx as jsx41, jsxs as jsxs22 } from "react/jsx-runtime";
2741
+ var Select = ({
2742
+ options,
2743
+ value,
2744
+ onChange,
2745
+ label,
2746
+ placeholder = "Select an option",
2747
+ helperText,
2748
+ error,
2749
+ disabled = false,
2750
+ fullWidth = false,
2751
+ size = "md",
2752
+ className = "",
2753
+ id
2754
+ }) => {
2755
+ const [isOpen, setIsOpen] = React30.useState(false);
2756
+ const selectId = id || `select-${React30.useId()}`;
2757
+ const selectedOption = options.find((opt) => opt.value === value);
2758
+ const handleSelect = (optionValue) => {
2759
+ onChange?.(optionValue);
2760
+ setIsOpen(false);
2761
+ };
2762
+ const handleKeyDown = (e) => {
2763
+ if (disabled) return;
2764
+ if (e.key === "Enter" || e.key === " ") {
2765
+ e.preventDefault();
2766
+ setIsOpen(!isOpen);
2767
+ } else if (e.key === "Escape") {
2768
+ setIsOpen(false);
2769
+ } else if (e.key === "ArrowDown" || e.key === "ArrowUp") {
2770
+ e.preventDefault();
2771
+ if (!isOpen) {
2772
+ setIsOpen(true);
2773
+ }
2774
+ }
2775
+ };
2776
+ const containerClasses = [
2777
+ "select-container",
2778
+ fullWidth && "select-container--full-width",
2779
+ className
2780
+ ].filter(Boolean).join(" ");
2781
+ const triggerClasses = [
2782
+ "select__trigger",
2783
+ `select__trigger--${size}`,
2784
+ error && "select__trigger--error",
2785
+ disabled && "select__trigger--disabled",
2786
+ isOpen && "select__trigger--open"
2787
+ ].filter(Boolean).join(" ");
2788
+ return /* @__PURE__ */ jsxs22("div", { className: containerClasses, children: [
2789
+ label && /* @__PURE__ */ jsx41("label", { htmlFor: selectId, className: "select__label", children: label }),
2790
+ /* @__PURE__ */ jsx41(
2791
+ Popover,
2792
+ {
2793
+ trigger: /* @__PURE__ */ jsxs22(
2794
+ "button",
2795
+ {
2796
+ id: selectId,
2797
+ type: "button",
2798
+ className: triggerClasses,
2799
+ onClick: () => !disabled && setIsOpen(!isOpen),
2800
+ onKeyDown: handleKeyDown,
2801
+ disabled,
2802
+ "aria-haspopup": "listbox",
2803
+ "aria-expanded": isOpen,
2804
+ "aria-labelledby": label ? `${selectId}-label` : void 0,
2805
+ "aria-describedby": error ? `${selectId}-error` : helperText ? `${selectId}-helper` : void 0,
2806
+ "aria-invalid": error ? "true" : "false",
2807
+ children: [
2808
+ /* @__PURE__ */ jsxs22("span", { className: "select__trigger-content", children: [
2809
+ selectedOption?.icon && /* @__PURE__ */ jsx41(
2810
+ Icon,
2811
+ {
2812
+ name: selectedOption.icon,
2813
+ size: size === "sm" ? 16 : size === "lg" ? 24 : 20
2814
+ }
2815
+ ),
2816
+ /* @__PURE__ */ jsx41("span", { className: "select__trigger-text", children: selectedOption ? selectedOption.label : placeholder })
2817
+ ] }),
2818
+ /* @__PURE__ */ jsx41(
2819
+ Icon,
2820
+ {
2821
+ name: "chevron-down",
2822
+ size: size === "sm" ? 16 : size === "lg" ? 24 : 20,
2823
+ className: "select__trigger-icon"
2824
+ }
2825
+ )
2826
+ ]
2827
+ }
2828
+ ),
2829
+ isOpen,
2830
+ onToggle: () => !disabled && setIsOpen(!isOpen),
2831
+ placement: "bottom",
2832
+ children: /* @__PURE__ */ jsx41("div", { className: "select__dropdown", role: "listbox", children: /* @__PURE__ */ jsx41(List, { children: options.map((option) => /* @__PURE__ */ jsx41(
2833
+ ListItem,
2834
+ {
2835
+ icon: option.icon,
2836
+ selected: option.value === value,
2837
+ disabled: option.disabled,
2838
+ onClick: () => !option.disabled && handleSelect(option.value),
2839
+ role: "option",
2840
+ "aria-selected": option.value === value,
2841
+ children: option.label
2842
+ },
2843
+ option.value
2844
+ )) }) })
2845
+ }
2846
+ ),
2847
+ error && /* @__PURE__ */ jsx41("p", { id: `${selectId}-error`, className: "select__message select__message--error", children: error }),
2848
+ helperText && !error && /* @__PURE__ */ jsx41("p", { id: `${selectId}-helper`, className: "select__message", children: helperText })
2849
+ ] });
2850
+ };
2851
+
2852
+ // src/components/banner/Banner.tsx
2853
+ import { jsx as jsx42, jsxs as jsxs23 } from "react/jsx-runtime";
2854
+ var Banner = ({
2855
+ type = "info",
2856
+ children,
2857
+ icon,
2858
+ onDismiss
2859
+ }) => {
2860
+ const defaultIcons = {
2861
+ info: "information-circle",
2862
+ warning: "warning",
2863
+ error: "close-circle",
2864
+ success: "checkmark-circle"
2865
+ };
2866
+ const displayIcon = icon || defaultIcons[type];
2867
+ return /* @__PURE__ */ jsxs23("div", { className: `banner banner--${type}`, children: [
2868
+ /* @__PURE__ */ jsxs23("div", { className: "banner__content", children: [
2869
+ /* @__PURE__ */ jsx42(Icon, { name: displayIcon, size: 32 }),
2870
+ /* @__PURE__ */ jsx42("div", { className: "banner__message", children })
2871
+ ] }),
2872
+ onDismiss && /* @__PURE__ */ jsx42(
2873
+ Button,
2874
+ {
2875
+ variant: "ghost",
2876
+ size: "xs",
2877
+ onClick: onDismiss,
2878
+ "aria-label": "Dismiss banner",
2879
+ children: /* @__PURE__ */ jsx42(Icon, { name: "close", size: 20 })
2880
+ }
2881
+ )
2882
+ ] });
2883
+ };
2884
+
2885
+ // src/components/floating-bar/floating-bar.tsx
2886
+ import { jsx as jsx43 } from "react/jsx-runtime";
2887
+ var FloatingBar = ({
2888
+ position = "bottom",
2889
+ children,
2890
+ className = "",
2891
+ ...props
2892
+ }) => {
2893
+ const classes = [
2894
+ "floating-bar",
2895
+ `floating-bar--${position}`,
2896
+ className
2897
+ ].filter(Boolean).join(" ");
2898
+ return /* @__PURE__ */ jsx43(
2899
+ "div",
2900
+ {
2901
+ className: classes,
2902
+ ...props,
2903
+ children: /* @__PURE__ */ jsx43("div", { className: "floating-bar__content", children })
2904
+ }
2905
+ );
2906
+ };
2907
+
2908
+ // src/components/drawer/drawer.tsx
2909
+ import { Dialog, DialogHeading } from "@ariakit/react";
2910
+ import { jsx as jsx44, jsxs as jsxs24 } from "react/jsx-runtime";
2911
+ var Drawer = ({
2912
+ children,
2913
+ title,
2914
+ placement = "right",
2915
+ size = "400px",
2916
+ store,
2917
+ ...props
2918
+ }) => {
2919
+ const sizeValue = typeof size === "number" ? `${size}px` : size;
2920
+ const getDrawerStyles = () => {
2921
+ const baseStyles = {
2922
+ zIndex: 1e3
2923
+ };
2924
+ switch (placement) {
2925
+ case "top":
2926
+ return {
2927
+ ...baseStyles,
2928
+ height: sizeValue
2929
+ };
2930
+ case "bottom":
2931
+ return {
2932
+ ...baseStyles,
2933
+ height: sizeValue
2934
+ };
2935
+ case "left":
2936
+ return {
2937
+ ...baseStyles,
2938
+ width: sizeValue
2939
+ };
2940
+ case "right":
2941
+ default:
2942
+ return {
2943
+ ...baseStyles,
2944
+ width: sizeValue
2945
+ };
2946
+ }
2947
+ };
2948
+ return /* @__PURE__ */ jsx44(
2949
+ Dialog,
2950
+ {
2951
+ store,
2952
+ ...props,
2953
+ className: `drawer drawer--${placement}`,
2954
+ style: getDrawerStyles(),
2955
+ backdrop: /* @__PURE__ */ jsx44("div", { className: "drawer__backdrop" }),
2956
+ children: /* @__PURE__ */ jsxs24("div", { className: "drawer__content", children: [
2957
+ title && /* @__PURE__ */ jsxs24("div", { className: "drawer__header", children: [
2958
+ /* @__PURE__ */ jsx44(DialogHeading, { className: "drawer__title", children: title }),
2959
+ /* @__PURE__ */ jsx44(
2960
+ "button",
2961
+ {
2962
+ className: "drawer__close",
2963
+ onClick: store.hide,
2964
+ "aria-label": "Close drawer",
2965
+ children: "\u2715"
2966
+ }
2967
+ )
2968
+ ] }),
2969
+ /* @__PURE__ */ jsx44("div", { className: "drawer__body", children })
2970
+ ] })
2971
+ }
2972
+ );
2973
+ };
2974
+
2975
+ // src/components/table/Table.tsx
2976
+ import { jsx as jsx45 } from "react/jsx-runtime";
2977
+ var Table = ({
2978
+ bordered = false,
2979
+ striped = true,
2980
+ hover = true,
2981
+ size = "md",
2982
+ className = "",
2983
+ children,
2984
+ ...props
2985
+ }) => {
2986
+ const classes = [
2987
+ "table",
2988
+ bordered && "table--bordered",
2989
+ striped && "table--striped",
2990
+ hover && "table--hover",
2991
+ size && `table--${size}`,
2992
+ className
2993
+ ].filter(Boolean).join(" ");
2994
+ return /* @__PURE__ */ jsx45("table", { className: classes, ...props, children });
2995
+ };
2996
+ var TableHead = ({
2997
+ className = "",
2998
+ children,
2999
+ ...props
3000
+ }) => {
3001
+ const classes = ["table__head", className].filter(Boolean).join(" ");
3002
+ return /* @__PURE__ */ jsx45("thead", { className: classes, ...props, children });
3003
+ };
3004
+ var TableBody = ({
3005
+ className = "",
3006
+ children,
3007
+ ...props
3008
+ }) => {
3009
+ const classes = ["table__body", className].filter(Boolean).join(" ");
3010
+ return /* @__PURE__ */ jsx45("tbody", { className: classes, ...props, children });
3011
+ };
3012
+ var TableRow = ({
3013
+ className = "",
3014
+ children,
3015
+ ...props
3016
+ }) => {
3017
+ const classes = ["table__row", className].filter(Boolean).join(" ");
3018
+ return /* @__PURE__ */ jsx45("tr", { className: classes, ...props, children });
3019
+ };
3020
+ var TableCell = ({
3021
+ header = false,
3022
+ className = "",
3023
+ children,
3024
+ ...props
3025
+ }) => {
3026
+ const classes = [
3027
+ header ? "table__cell--header" : "table__cell",
3028
+ className
3029
+ ].filter(Boolean).join(" ");
3030
+ if (header) {
3031
+ return /* @__PURE__ */ jsx45("th", { className: classes, ...props, children });
3032
+ }
3033
+ return /* @__PURE__ */ jsx45("td", { className: classes, ...props, children });
3034
+ };
3035
+ var TableContainer = ({
3036
+ className = "",
3037
+ children,
3038
+ ...props
3039
+ }) => {
3040
+ const classes = ["table-container", className].filter(Boolean).join(" ");
3041
+ return /* @__PURE__ */ jsx45("div", { className: classes, ...props, children });
3042
+ };
3043
+
3044
+ // src/components/page-index/PageIndex.tsx
3045
+ import * as React31 from "react";
3046
+ import { jsx as jsx46, jsxs as jsxs25 } from "react/jsx-runtime";
3047
+ var PageIndex = ({
3048
+ title = "On this page",
3049
+ collapsed = false,
3050
+ className = "",
3051
+ ...props
3052
+ }) => {
3053
+ const [items, setItems] = React31.useState([]);
3054
+ const [activeId, setActiveId] = React31.useState("");
3055
+ const [manualNavigation, setManualNavigation] = React31.useState(false);
3056
+ const getTextContent = React31.useCallback((element) => {
3057
+ if (element.tagName.match(/^H[1-6]$/)) {
3058
+ return element.textContent || "";
3059
+ }
3060
+ return element.getAttribute("data-page-index-title") || element.getAttribute("title") || element.textContent || "";
3061
+ }, []);
3062
+ const generateId = React31.useCallback((text) => {
3063
+ return text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim();
3064
+ }, []);
3065
+ const scanPage = React31.useCallback(() => {
3066
+ const newItems = [];
3067
+ const seenIds = /* @__PURE__ */ new Set();
3068
+ const pages = document.querySelectorAll("main");
3069
+ pages.forEach((page) => {
3070
+ const pageElement = page;
3071
+ if (pageElement.closest(".page-index")) {
3072
+ return;
3073
+ }
3074
+ const sections = pageElement.querySelectorAll("section");
3075
+ sections.forEach((section) => {
3076
+ const sectionElement = section;
3077
+ if (sectionElement.closest(".page-index")) {
3078
+ return;
3079
+ }
3080
+ const childElements = Array.from(sectionElement.children);
3081
+ const headings = childElements.filter(
3082
+ (child) => child.tagName.match(/^H[1-6]$/)
3083
+ );
3084
+ headings.forEach((element) => {
3085
+ const text = getTextContent(element);
3086
+ if (text.trim()) {
3087
+ if (element.closest('.component-preview, [data-demo], .demo, .example, .drawer, [role="dialog"]')) {
3088
+ return;
3089
+ }
3090
+ const id = element.id || generateId(text);
3091
+ if (seenIds.has(id)) {
3092
+ return;
3093
+ }
3094
+ seenIds.add(id);
3095
+ if (!element.id) {
3096
+ element.id = id;
3097
+ }
3098
+ const tagName = element.tagName.toLowerCase();
3099
+ const level = parseInt(tagName.substring(1));
3100
+ newItems.push({
3101
+ id,
3102
+ title: text.trim(),
3103
+ level,
3104
+ element
3105
+ });
3106
+ }
3107
+ });
3108
+ });
3109
+ });
3110
+ newItems.sort((a, b) => {
3111
+ const aRect = a.element.getBoundingClientRect();
3112
+ const bRect = b.element.getBoundingClientRect();
3113
+ return aRect.top - bRect.top;
3114
+ });
3115
+ setItems(newItems);
3116
+ }, [getTextContent, generateId]);
3117
+ React31.useEffect(() => {
3118
+ const observer = new IntersectionObserver(
3119
+ (entries) => {
3120
+ if (manualNavigation) return;
3121
+ entries.forEach((entry) => {
3122
+ if (entry.isIntersecting) {
3123
+ setActiveId(entry.target.id);
3124
+ }
3125
+ });
3126
+ },
3127
+ {
3128
+ rootMargin: "-80px 0px -80% 0px",
3129
+ threshold: 0
3130
+ }
3131
+ );
3132
+ items.forEach((item) => {
3133
+ observer.observe(item.element);
3134
+ });
3135
+ return () => {
3136
+ items.forEach((item) => {
3137
+ observer.unobserve(item.element);
3138
+ });
3139
+ };
3140
+ }, [items, manualNavigation]);
3141
+ React31.useEffect(() => {
3142
+ const timer = setTimeout(() => {
3143
+ scanPage();
3144
+ }, 100);
3145
+ const handleLocationChange = () => {
3146
+ setTimeout(() => {
3147
+ scanPage();
3148
+ }, 150);
3149
+ };
3150
+ window.addEventListener("popstate", handleLocationChange);
3151
+ window.addEventListener("locationchange", handleLocationChange);
3152
+ const observer = new MutationObserver(() => {
3153
+ clearTimeout(timer);
3154
+ setTimeout(() => {
3155
+ scanPage();
3156
+ }, 200);
3157
+ });
3158
+ const mainContent = document.querySelector("main") || document.body;
3159
+ observer.observe(mainContent, {
3160
+ childList: true,
3161
+ subtree: true,
3162
+ attributes: true,
3163
+ attributeFilter: ["data-section-title", "id"]
3164
+ });
3165
+ return () => {
3166
+ clearTimeout(timer);
3167
+ window.removeEventListener("popstate", handleLocationChange);
3168
+ window.removeEventListener("locationchange", handleLocationChange);
3169
+ observer.disconnect();
3170
+ };
3171
+ }, [scanPage]);
3172
+ const handleItemClick = React31.useCallback((id) => {
3173
+ const element = document.getElementById(id);
3174
+ if (element) {
3175
+ setManualNavigation(true);
3176
+ setActiveId(id);
3177
+ element.scrollIntoView({
3178
+ behavior: "smooth",
3179
+ block: "start"
3180
+ });
3181
+ setTimeout(() => {
3182
+ setManualNavigation(false);
3183
+ }, 1e3);
3184
+ }
3185
+ }, []);
3186
+ const classes = [
3187
+ "page-index",
3188
+ collapsed && "page-index--collapsed",
3189
+ className
3190
+ ].filter(Boolean).join(" ");
3191
+ if (items.length === 0) {
3192
+ return null;
3193
+ }
3194
+ const { sidebarWidth, setSidebarWidth, ...domProps } = props;
3195
+ return /* @__PURE__ */ jsxs25("div", { className: classes, ...domProps, children: [
3196
+ !collapsed && /* @__PURE__ */ jsx46("h3", { className: "page-index__title", children: title }),
3197
+ /* @__PURE__ */ jsx46("nav", { className: "page-index__nav", "aria-label": "Page contents", children: /* @__PURE__ */ jsx46("ul", { className: "page-index__list", children: items.map((item) => /* @__PURE__ */ jsx46(
3198
+ "li",
3199
+ {
3200
+ className: `page-index__item page-index__item--level-${item.level}`,
3201
+ children: /* @__PURE__ */ jsx46(
3202
+ "button",
3203
+ {
3204
+ className: `page-index__link ${activeId === item.id ? "page-index__link--active" : ""}`,
3205
+ onClick: () => handleItemClick(item.id),
3206
+ "aria-current": activeId === item.id ? "location" : void 0,
3207
+ children: collapsed ? /* @__PURE__ */ jsx46("span", { className: "page-index__link-text--collapsed", children: item.title.charAt(0) }) : item.title
3208
+ }
3209
+ )
3210
+ },
3211
+ item.id
3212
+ )) }) })
3213
+ ] });
3214
+ };
3215
+ export {
3216
+ Badge,
3217
+ Banner,
3218
+ Button,
3219
+ Card,
3220
+ Checkbox,
3221
+ CodeBlock,
3222
+ ColorControl,
3223
+ DragHandle,
3224
+ Drawer,
3225
+ FloatingBar,
3226
+ Footer,
3227
+ Grid,
3228
+ Header,
3229
+ Icon,
3230
+ InputDate,
3231
+ InputDateTime,
3232
+ InputEmail,
3233
+ InputNumber,
3234
+ InputPassword,
3235
+ InputSearch,
3236
+ InputTel,
3237
+ InputText,
3238
+ InputTime,
3239
+ InputUrl,
3240
+ Layout,
3241
+ List,
3242
+ ListItem,
3243
+ MenuCategory,
3244
+ MenuGroup,
3245
+ MenuItem,
3246
+ Navbar,
3247
+ NavbarTooltipProvider,
3248
+ Page,
3249
+ PageIndex,
3250
+ Popover,
3251
+ Radio,
3252
+ RadioGroup,
3253
+ Section,
3254
+ Select,
3255
+ Slider,
3256
+ Switch,
3257
+ Table,
3258
+ TableBody,
3259
+ TableCell,
3260
+ TableContainer,
3261
+ TableHead,
3262
+ TableRow,
3263
+ ThemeControl,
3264
+ Tooltip,
3265
+ applyTheme,
3266
+ clearPreferences,
3267
+ clearPreferencesAsync,
3268
+ configurePreferences,
3269
+ createPreferenceNamespace,
3270
+ exportPreferences,
3271
+ getAllPreferences,
3272
+ getPreference,
3273
+ getPreferenceAsync,
3274
+ getSavedTheme,
3275
+ getTheme,
3276
+ importPreferences,
3277
+ initializeTheme,
3278
+ onSystemThemeChange,
3279
+ removePreference,
3280
+ removePreferenceAsync,
3281
+ setPreference,
3282
+ setPreferenceAsync,
3283
+ setTheme,
3284
+ toggleTheme,
3285
+ useNavbarTooltip
3286
+ };
3287
+ //# sourceMappingURL=index.mjs.map