marclayui 0.0.0-stage → 0.3.1

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 (69) hide show
  1. package/README.md +50 -3
  2. package/dist/index.cjs +1510 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.mts +379 -0
  5. package/dist/index.d.ts +379 -0
  6. package/dist/index.js +1443 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/theme-init.cjs +31 -0
  9. package/dist/theme-init.cjs.map +1 -0
  10. package/dist/theme-init.d.mts +8 -0
  11. package/dist/theme-init.d.ts +8 -0
  12. package/dist/theme-init.js +6 -0
  13. package/dist/theme-init.js.map +1 -0
  14. package/package.json +71 -4
  15. package/src/components/accordion/accordion.css +66 -0
  16. package/src/components/accordion/accordion.tsx +86 -0
  17. package/src/components/alert/alert.css +86 -0
  18. package/src/components/alert/alert.tsx +45 -0
  19. package/src/components/avatar/avatar.css +75 -0
  20. package/src/components/avatar/avatar.tsx +59 -0
  21. package/src/components/badge/badge.css +106 -0
  22. package/src/components/badge/badge.tsx +26 -0
  23. package/src/components/button/button.css +118 -0
  24. package/src/components/button/button.tsx +86 -0
  25. package/src/components/card/card.css +41 -0
  26. package/src/components/card/card.tsx +26 -0
  27. package/src/components/checks/checks.css +157 -0
  28. package/src/components/checks/checks.tsx +167 -0
  29. package/src/components/divider/divider.css +41 -0
  30. package/src/components/divider/divider.tsx +24 -0
  31. package/src/components/dropdown/dropdown.css +182 -0
  32. package/src/components/dropdown/dropdown.tsx +268 -0
  33. package/src/components/input/input.css +73 -0
  34. package/src/components/input/input.tsx +85 -0
  35. package/src/components/kbd/kbd.css +66 -0
  36. package/src/components/kbd/kbd.tsx +14 -0
  37. package/src/components/modal/modal.css +93 -0
  38. package/src/components/modal/modal.tsx +114 -0
  39. package/src/components/navbar/navbar.css +127 -0
  40. package/src/components/navbar/navbar.tsx +64 -0
  41. package/src/components/progress/progress.css +62 -0
  42. package/src/components/progress/progress.tsx +50 -0
  43. package/src/components/range/range.css +68 -0
  44. package/src/components/range/range.tsx +60 -0
  45. package/src/components/skeleton/skeleton.css +43 -0
  46. package/src/components/skeleton/skeleton.tsx +35 -0
  47. package/src/components/spinner/spinner.css +21 -0
  48. package/src/components/spinner/spinner.tsx +10 -0
  49. package/src/components/stack/stack.css +60 -0
  50. package/src/components/stack/stack.tsx +34 -0
  51. package/src/components/stat/stat.css +54 -0
  52. package/src/components/stat/stat.tsx +19 -0
  53. package/src/components/tabs/tabs.css +58 -0
  54. package/src/components/tabs/tabs.tsx +84 -0
  55. package/src/components/toast/toast.css +94 -0
  56. package/src/components/toast/toast.tsx +100 -0
  57. package/src/components/tooltip/tooltip.css +100 -0
  58. package/src/components/tooltip/tooltip.tsx +19 -0
  59. package/src/index.ts +112 -0
  60. package/src/styles/base.css +78 -0
  61. package/src/styles/index.css +26 -0
  62. package/src/styles/theme.css +246 -0
  63. package/src/theme-init.ts +6 -0
  64. package/src/theming/ThemeMenu.tsx +158 -0
  65. package/src/theming/ThemeProvider.tsx +234 -0
  66. package/src/theming/ThemeToggle.tsx +27 -0
  67. package/src/theming/presets.ts +33 -0
  68. package/src/theming/theming.css +155 -0
  69. package/src/utils/color.ts +58 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,1510 @@
1
+ "use client";
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var index_exports = {};
33
+ __export(index_exports, {
34
+ Accordion: () => Accordion,
35
+ Alert: () => Alert,
36
+ Avatar: () => Avatar,
37
+ AvatarGroup: () => AvatarGroup,
38
+ Badge: () => Badge,
39
+ Button: () => Button,
40
+ ButtonGroup: () => ButtonGroup,
41
+ COLOR_SWATCHES: () => COLOR_SWATCHES,
42
+ Card: () => Card,
43
+ CardBody: () => CardBody,
44
+ CardFooter: () => CardFooter,
45
+ CardHeader: () => CardHeader,
46
+ CardTitle: () => CardTitle,
47
+ Checkbox: () => Checkbox,
48
+ CheckboxGroup: () => CheckboxGroup,
49
+ Divider: () => Divider,
50
+ Dropdown: () => Dropdown,
51
+ Input: () => Input,
52
+ Kbd: () => Kbd,
53
+ MarclayProvider: () => MarclayProvider,
54
+ Modal: () => Modal,
55
+ Navbar: () => Navbar,
56
+ PRESETS: () => PRESETS,
57
+ Progress: () => Progress,
58
+ Radio: () => Radio,
59
+ Range: () => Range,
60
+ Skeleton: () => Skeleton,
61
+ Spinner: () => Spinner,
62
+ Stack: () => Stack,
63
+ Stat: () => Stat,
64
+ Switch: () => Switch,
65
+ Tabs: () => Tabs,
66
+ Textarea: () => Textarea,
67
+ ThemeMenu: () => ThemeMenu,
68
+ ThemeProvider: () => ThemeProvider,
69
+ ThemeToggle: () => ThemeToggle,
70
+ ToastProvider: () => ToastProvider,
71
+ Tooltip: () => Tooltip,
72
+ useTheme: () => useTheme,
73
+ useToast: () => useToast
74
+ });
75
+ module.exports = __toCommonJS(index_exports);
76
+
77
+ // src/theming/ThemeProvider.tsx
78
+ var import_react = require("react");
79
+
80
+ // src/utils/color.ts
81
+ var WHITE = { r: 255, g: 255, b: 255 };
82
+ var BLACK = { r: 0, g: 0, b: 0 };
83
+ function clamp(n, min = 0, max = 255) {
84
+ return Math.min(max, Math.max(min, n));
85
+ }
86
+ function parseHex(hex) {
87
+ let h = hex.trim().replace("#", "");
88
+ if (h.length === 3) h = h.split("").map((c) => c + c).join("");
89
+ if (h.length !== 6 || /[^0-9a-f]/i.test(h)) return { ...BLACK };
90
+ const n = parseInt(h, 16);
91
+ return { r: n >> 16 & 255, g: n >> 8 & 255, b: n & 255 };
92
+ }
93
+ function toHex(c) {
94
+ const part = (v) => clamp(Math.round(v)).toString(16).padStart(2, "0");
95
+ return `#${part(c.r)}${part(c.g)}${part(c.b)}`;
96
+ }
97
+ function rgba(c, a) {
98
+ return `rgba(${clamp(Math.round(c.r))}, ${clamp(Math.round(c.g))}, ${clamp(Math.round(c.b))}, ${a})`;
99
+ }
100
+ function mix(a, b, t) {
101
+ return {
102
+ r: a.r + (b.r - a.r) * t,
103
+ g: a.g + (b.g - a.g) * t,
104
+ b: a.b + (b.b - a.b) * t
105
+ };
106
+ }
107
+ function lighten(hex, t) {
108
+ return toHex(mix(parseHex(hex), WHITE, t));
109
+ }
110
+ function darken(hex, t) {
111
+ return toHex(mix(parseHex(hex), BLACK, t));
112
+ }
113
+ function alpha(hex, a) {
114
+ return rgba(parseHex(hex), a);
115
+ }
116
+ function readableInk(base) {
117
+ const { r, g, b } = mix(parseHex(base), WHITE, 0.12);
118
+ const lum = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
119
+ return lum > 0.62 ? "#3a2d20" : "#fff8f2";
120
+ }
121
+
122
+ // src/theming/presets.ts
123
+ var PRESETS = [
124
+ {
125
+ id: "clay",
126
+ label: "Claymorphism",
127
+ description: "Warm terracotta clay, squircles, Quicksand \u2014 the signature MarclayUI look."
128
+ },
129
+ {
130
+ id: "neo",
131
+ label: "Neumorphism",
132
+ description: "Soft grey-blue extrusions, violet (light) / gold (dark) accent, circles, Poppins & Manrope."
133
+ }
134
+ ];
135
+ var PRESET_STORAGE_KEY = "mcl-preset";
136
+ var COLOR_SWATCHES = [
137
+ { name: "Terra", color: "#e0785a" },
138
+ { name: "Violet", color: "#7c5cff" },
139
+ { name: "Ocean", color: "#4a90d9" },
140
+ { name: "Forest", color: "#5a8a46" },
141
+ { name: "Magenta", color: "#c74f9d" }
142
+ ];
143
+
144
+ // src/theming/ThemeProvider.tsx
145
+ var import_jsx_runtime = require("react/jsx-runtime");
146
+ var ThemeContext = (0, import_react.createContext)(null);
147
+ var STORAGE_KEY = "mcl-theme";
148
+ var TONES = [
149
+ ["primary", "primary", "p"],
150
+ ["secondary", "secondary", "s"],
151
+ ["accent", "accent", "a"],
152
+ ["success", "success", "c"],
153
+ ["danger", "danger", "d"],
154
+ ["warning", "warning", "w"],
155
+ ["info", "info", "i"]
156
+ ];
157
+ function systemMode() {
158
+ if (typeof window === "undefined" || !window.matchMedia) return "light";
159
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
160
+ }
161
+ function toneVars(base, dark) {
162
+ return {
163
+ base,
164
+ light: lighten(base, dark ? 0.24 : 0.16),
165
+ deep: darken(base, 0.32),
166
+ ink: readableInk(base),
167
+ clay: `inset -5px -6px 10px ${alpha(darken(base, 0.68), dark ? 0.5 : 0.3)}, inset 5px 6px 10px ${alpha(
168
+ lighten(base, 0.45),
169
+ dark ? 0.38 : 0.5
170
+ )}`
171
+ };
172
+ }
173
+ function colorVars(c, mode) {
174
+ const vars = {};
175
+ const dark = mode === "dark";
176
+ for (const [key, name, short] of TONES) {
177
+ const base = c[key];
178
+ if (!base) continue;
179
+ const t = toneVars(base, dark);
180
+ vars[`--mcl-${name}`] = t.base;
181
+ vars[`--mcl-${name}-2`] = t.light;
182
+ vars[`--mcl-${name}-deep`] = t.deep;
183
+ vars[`--mcl-${name}-ink`] = t.ink;
184
+ vars[`--mcl-clay-${short}`] = t.clay;
185
+ if (key === "primary") vars["--mcl-ring"] = alpha(base, dark ? 0.45 : 0.4);
186
+ }
187
+ if (c.bg) {
188
+ vars["--mcl-bg"] = c.bg;
189
+ vars["--mcl-sd"] = alpha(darken(c.bg, dark ? 0.78 : 0.4), dark ? 0.72 : 0.6);
190
+ vars["--mcl-sl"] = alpha(lighten(c.bg, dark ? 0.3 : 0.9), dark ? 0.07 : 0.95);
191
+ vars["--mcl-sheen"] = alpha(lighten(c.bg, 0.9), dark ? 0.08 : 0.5);
192
+ }
193
+ if (c.ink) vars["--mcl-ink"] = c.ink;
194
+ if (c.muted) vars["--mcl-muted"] = c.muted;
195
+ return vars;
196
+ }
197
+ function MarclayProvider({
198
+ children,
199
+ defaultMode = "system",
200
+ preset: initialPreset = "clay",
201
+ colors: initialColors
202
+ }) {
203
+ const [preference, setPreferenceState] = (0, import_react.useState)(defaultMode);
204
+ const [mode, setMode] = (0, import_react.useState)("light");
205
+ const [preset, setPresetState] = (0, import_react.useState)(initialPreset);
206
+ const [colors, setColorsState] = (0, import_react.useState)(initialColors ?? {});
207
+ const appliedKeys = (0, import_react.useRef)(/* @__PURE__ */ new Set());
208
+ (0, import_react.useEffect)(() => {
209
+ let stored = null;
210
+ let storedPreset = null;
211
+ try {
212
+ stored = localStorage.getItem(STORAGE_KEY);
213
+ storedPreset = localStorage.getItem(PRESET_STORAGE_KEY);
214
+ } catch {
215
+ stored = null;
216
+ }
217
+ setPreferenceState(stored ?? defaultMode);
218
+ if (storedPreset === "clay" || storedPreset === "neo") setPresetState(storedPreset);
219
+ }, []);
220
+ (0, import_react.useEffect)(() => {
221
+ const apply = () => {
222
+ const m = preference === "system" ? systemMode() : preference;
223
+ setMode(m);
224
+ document.documentElement.setAttribute("data-theme", m);
225
+ };
226
+ apply();
227
+ if (preference !== "system" || !window.matchMedia) return;
228
+ const mq = window.matchMedia("(prefers-color-scheme: dark)");
229
+ const onChange = () => apply();
230
+ mq.addEventListener?.("change", onChange);
231
+ return () => mq.removeEventListener?.("change", onChange);
232
+ }, [preference]);
233
+ (0, import_react.useEffect)(() => {
234
+ if (preset === "clay") document.documentElement.removeAttribute("data-preset");
235
+ else document.documentElement.setAttribute("data-preset", preset);
236
+ }, [preset]);
237
+ (0, import_react.useEffect)(() => {
238
+ const root = document.documentElement;
239
+ appliedKeys.current.forEach((k) => root.style.removeProperty(k));
240
+ appliedKeys.current.clear();
241
+ if (Object.keys(colors).length === 0) return;
242
+ const vars = colorVars(colors, mode);
243
+ for (const [k, v] of Object.entries(vars)) {
244
+ root.style.setProperty(k, v);
245
+ appliedKeys.current.add(k);
246
+ }
247
+ }, [colors, mode]);
248
+ const setPreference = (0, import_react.useCallback)((p) => {
249
+ setPreferenceState(p);
250
+ try {
251
+ localStorage.setItem(STORAGE_KEY, p);
252
+ } catch {
253
+ }
254
+ }, []);
255
+ const toggle = (0, import_react.useCallback)(() => {
256
+ setPreference(mode === "dark" ? "light" : "dark");
257
+ }, [mode, setPreference]);
258
+ const setPreset = (0, import_react.useCallback)((p) => {
259
+ setPresetState(p);
260
+ try {
261
+ localStorage.setItem(PRESET_STORAGE_KEY, p);
262
+ } catch {
263
+ }
264
+ setColorsState({});
265
+ }, []);
266
+ const setColors = (0, import_react.useCallback)((c) => {
267
+ setColorsState((prev) => ({ ...prev, ...c }));
268
+ }, []);
269
+ const resetColors = (0, import_react.useCallback)(() => setColorsState({}), []);
270
+ const value = (0, import_react.useMemo)(
271
+ () => ({
272
+ mode,
273
+ preference,
274
+ setPreference,
275
+ toggle,
276
+ preset,
277
+ setPreset,
278
+ colors,
279
+ setColors,
280
+ resetColors
281
+ }),
282
+ [mode, preference, setPreference, toggle, preset, setPreset, colors, setColors, resetColors]
283
+ );
284
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value, children });
285
+ }
286
+ function useTheme() {
287
+ const ctx = (0, import_react.useContext)(ThemeContext);
288
+ if (!ctx) throw new Error("useTheme must be used inside <MarclayProvider>.");
289
+ return ctx;
290
+ }
291
+ var ThemeProvider = MarclayProvider;
292
+
293
+ // src/theming/ThemeToggle.tsx
294
+ var import_jsx_runtime2 = require("react/jsx-runtime");
295
+ function ThemeToggle({ className = "" }) {
296
+ const { mode, toggle } = useTheme();
297
+ const next = mode === "dark" ? "light" : "dark";
298
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
299
+ "button",
300
+ {
301
+ type: "button",
302
+ className: `mcl-theme-toggle ${className}`.trim(),
303
+ onClick: toggle,
304
+ "aria-label": `Switch to ${next} mode`,
305
+ title: `Switch to ${next} mode`,
306
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "mcl-theme-toggle-icon", "aria-hidden": "true", children: mode === "dark" ? "\u2600\uFE0F" : "\u{1F319}" })
307
+ }
308
+ );
309
+ }
310
+
311
+ // src/theming/ThemeMenu.tsx
312
+ var import_react2 = require("react");
313
+ var import_jsx_runtime3 = require("react/jsx-runtime");
314
+ var MODE_OPTIONS = [
315
+ { key: "light", label: "Light", icon: "\u2600\uFE0F" },
316
+ { key: "system", label: "System", icon: "\u{1F5A5}\uFE0F" },
317
+ { key: "dark", label: "Dark", icon: "\u{1F319}" }
318
+ ];
319
+ function ThemeMenu({ className = "" }) {
320
+ const {
321
+ mode,
322
+ preference,
323
+ setPreference,
324
+ preset,
325
+ setPreset,
326
+ colors,
327
+ setColors,
328
+ resetColors
329
+ } = useTheme();
330
+ const [open, setOpen] = (0, import_react2.useState)(false);
331
+ const [flipUp, setFlipUp] = (0, import_react2.useState)(false);
332
+ const shellRef = (0, import_react2.useRef)(null);
333
+ const panelRef = (0, import_react2.useRef)(null);
334
+ const triggerRef = (0, import_react2.useRef)(null);
335
+ (0, import_react2.useEffect)(() => {
336
+ if (!open) return;
337
+ const onDown = (e) => {
338
+ if (shellRef.current && !shellRef.current.contains(e.target)) {
339
+ setOpen(false);
340
+ triggerRef.current?.focus();
341
+ }
342
+ };
343
+ const onKey = (e) => {
344
+ if (e.key === "Escape") {
345
+ setOpen(false);
346
+ triggerRef.current?.focus();
347
+ }
348
+ };
349
+ document.addEventListener("mousedown", onDown);
350
+ document.addEventListener("keydown", onKey);
351
+ return () => {
352
+ document.removeEventListener("mousedown", onDown);
353
+ document.removeEventListener("keydown", onKey);
354
+ };
355
+ }, [open]);
356
+ (0, import_react2.useEffect)(() => {
357
+ if (open) {
358
+ panelRef.current?.focus();
359
+ const t = window.setTimeout(() => {
360
+ const trig = triggerRef.current;
361
+ const panel = panelRef.current;
362
+ if (!trig || !panel) return;
363
+ const r = trig.getBoundingClientRect();
364
+ setFlipUp(window.innerHeight - r.bottom < panel.offsetHeight + 12);
365
+ }, 0);
366
+ return () => window.clearTimeout(t);
367
+ }
368
+ setFlipUp(false);
369
+ }, [open]);
370
+ const activeSwatch = colors.primary?.toLowerCase();
371
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { ref: shellRef, className: `mcl-theme-menu-shell ${className}`.trim(), children: [
372
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
373
+ "button",
374
+ {
375
+ ref: triggerRef,
376
+ type: "button",
377
+ className: "mcl-theme-toggle",
378
+ "aria-haspopup": "dialog",
379
+ "aria-expanded": open,
380
+ "aria-label": "Customize theme",
381
+ title: "Customize theme",
382
+ onClick: () => setOpen((o) => !o),
383
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mcl-theme-toggle-icon", "aria-hidden": "true", children: preference === "system" ? "\u{1F5A5}\uFE0F" : mode === "dark" ? "\u{1F319}" : "\u2600\uFE0F" })
384
+ }
385
+ ),
386
+ open && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
387
+ "div",
388
+ {
389
+ ref: panelRef,
390
+ tabIndex: -1,
391
+ role: "dialog",
392
+ "aria-label": "Customize theme",
393
+ className: `mcl-theme-menu${flipUp ? " mcl-theme-menu-up" : ""}`,
394
+ children: [
395
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mcl-theme-menu-section", children: [
396
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "mcl-theme-menu-label", children: [
397
+ "Mode \xB7 ",
398
+ mode
399
+ ] }),
400
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mcl-theme-menu-chips", children: MODE_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
401
+ "button",
402
+ {
403
+ type: "button",
404
+ className: `mcl-theme-menu-chip${preference === m.key ? " mcl-theme-menu-chip-on" : ""}`,
405
+ "aria-pressed": preference === m.key,
406
+ onClick: () => setPreference(m.key),
407
+ children: [
408
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "aria-hidden": "true", children: m.icon }),
409
+ " ",
410
+ m.label
411
+ ]
412
+ },
413
+ m.key
414
+ )) })
415
+ ] }),
416
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mcl-theme-menu-section", children: [
417
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mcl-theme-menu-label", children: "Style preset" }),
418
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mcl-theme-menu-chips", children: PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
419
+ "button",
420
+ {
421
+ type: "button",
422
+ className: `mcl-theme-menu-chip${preset === p.id ? " mcl-theme-menu-chip-on" : ""}`,
423
+ "aria-pressed": preset === p.id,
424
+ onClick: () => setPreset(p.id),
425
+ children: p.label
426
+ },
427
+ p.id
428
+ )) })
429
+ ] }),
430
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mcl-theme-menu-section", children: [
431
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mcl-theme-menu-label", children: "Primary color" }),
432
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mcl-theme-menu-swatches", children: COLOR_SWATCHES.map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
433
+ "button",
434
+ {
435
+ type: "button",
436
+ className: `mcl-theme-menu-swatch${activeSwatch === s.color.toLowerCase() ? " mcl-theme-menu-swatch-on" : ""}`,
437
+ style: { background: s.color },
438
+ title: s.name,
439
+ "aria-label": `Primary ${s.name}`,
440
+ "aria-pressed": activeSwatch === s.color.toLowerCase(),
441
+ onClick: () => setColors({ primary: s.color })
442
+ },
443
+ s.color
444
+ )) }),
445
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mcl-theme-menu-reset", onClick: resetColors, children: "Reset colors" })
446
+ ] })
447
+ ]
448
+ }
449
+ )
450
+ ] });
451
+ }
452
+
453
+ // src/components/button/button.tsx
454
+ var import_react3 = __toESM(require("react"));
455
+ var import_jsx_runtime4 = require("react/jsx-runtime");
456
+ var Button = import_react3.default.forwardRef(
457
+ function Button2({
458
+ variant = "soft",
459
+ size = "md",
460
+ loading = false,
461
+ block = false,
462
+ className = "",
463
+ disabled,
464
+ children,
465
+ type = "button",
466
+ href,
467
+ ...rest
468
+ }, ref) {
469
+ const cls = [
470
+ "mcl-btn",
471
+ `mcl-btn-${variant}`,
472
+ `mcl-btn-${size}`,
473
+ block ? "mcl-btn-block" : "",
474
+ loading ? "mcl-btn-loading" : "",
475
+ className
476
+ ].filter(Boolean).join(" ");
477
+ if (href) {
478
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
479
+ "a",
480
+ {
481
+ ref,
482
+ href,
483
+ className: cls,
484
+ "aria-disabled": disabled || void 0,
485
+ ...rest,
486
+ children: [
487
+ loading && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mcl-btn-spinner", "aria-hidden": "true" }),
488
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mcl-btn-label", children })
489
+ ]
490
+ }
491
+ );
492
+ }
493
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
494
+ "button",
495
+ {
496
+ ref,
497
+ type,
498
+ className: cls,
499
+ disabled: disabled || loading,
500
+ ...rest,
501
+ children: [
502
+ loading && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mcl-btn-spinner", "aria-hidden": "true" }),
503
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mcl-btn-label", children })
504
+ ]
505
+ }
506
+ );
507
+ }
508
+ );
509
+ function ButtonGroup({ children, className = "", ...rest }) {
510
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `mcl-btn-group ${className}`.trim(), role: "group", ...rest, children });
511
+ }
512
+
513
+ // src/components/kbd/kbd.tsx
514
+ var import_jsx_runtime5 = require("react/jsx-runtime");
515
+ function Kbd({ children, className = "", ...rest }) {
516
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("kbd", { className: `mcl-kbd ${className}`.trim(), ...rest, children });
517
+ }
518
+
519
+ // src/components/card/card.tsx
520
+ var import_jsx_runtime6 = require("react/jsx-runtime");
521
+ function Card({ hover = false, className = "", ...rest }) {
522
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `mcl-card${hover ? " mcl-card-hover" : ""} ${className}`.trim(), ...rest });
523
+ }
524
+ function CardHeader({ className = "", ...rest }) {
525
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `mcl-card-header ${className}`.trim(), ...rest });
526
+ }
527
+ function CardTitle({ className = "", ...rest }) {
528
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { className: `mcl-card-title ${className}`.trim(), ...rest });
529
+ }
530
+ function CardBody({ className = "", ...rest }) {
531
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `mcl-card-body ${className}`.trim(), ...rest });
532
+ }
533
+ function CardFooter({ className = "", ...rest }) {
534
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `mcl-card-footer ${className}`.trim(), ...rest });
535
+ }
536
+
537
+ // src/components/input/input.tsx
538
+ var import_react4 = __toESM(require("react"));
539
+ var import_jsx_runtime7 = require("react/jsx-runtime");
540
+ function fieldClasses(base, size, invalid) {
541
+ return [base, `${base}-${size}`, invalid ? `${base}-invalid` : ""].filter(Boolean).join(" ");
542
+ }
543
+ function Chrome({
544
+ id,
545
+ label,
546
+ hint,
547
+ error,
548
+ block,
549
+ children
550
+ }) {
551
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `mcl-field${block ? " mcl-field-block" : ""}`, children: [
552
+ label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "mcl-label", htmlFor: id, children: label }),
553
+ children,
554
+ error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mcl-hint mcl-hint-error", role: "alert", children: error }) : hint ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mcl-hint", children: hint }) : null
555
+ ] });
556
+ }
557
+ function Input({ label, hint, error, size = "md", block = false, className = "", id, ...rest }) {
558
+ const autoId = import_react4.default.useId();
559
+ const inputId = id ?? autoId;
560
+ const input = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
561
+ "input",
562
+ {
563
+ id: inputId,
564
+ className: `${fieldClasses("mcl-input", size, !!error)}${block ? " mcl-input-block" : ""} ${className}`.trim(),
565
+ "aria-invalid": error ? true : void 0,
566
+ ...rest
567
+ }
568
+ );
569
+ if (!label && !hint && !error) return input;
570
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Chrome, { id: inputId, label, hint, error, block, children: input });
571
+ }
572
+ function Textarea({ label, hint, error, size = "md", block = true, className = "", id, rows = 4, ...rest }) {
573
+ const autoId = import_react4.default.useId();
574
+ const inputId = id ?? autoId;
575
+ const el = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
576
+ "textarea",
577
+ {
578
+ id: inputId,
579
+ rows,
580
+ className: `${fieldClasses("mcl-textarea", size, !!error)} ${className}`.trim(),
581
+ "aria-invalid": error ? true : void 0,
582
+ ...rest
583
+ }
584
+ );
585
+ if (!label && !hint && !error) return el;
586
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Chrome, { id: inputId, label, hint, error, block: true, children: el });
587
+ }
588
+
589
+ // src/components/checks/checks.tsx
590
+ var import_react5 = require("react");
591
+ var import_jsx_runtime8 = require("react/jsx-runtime");
592
+ function withLabel(input, label) {
593
+ if (label === void 0 || label === null) return input;
594
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "mcl-check", children: [
595
+ input,
596
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "mcl-check-label", children: label })
597
+ ] });
598
+ }
599
+ function Checkbox({ label, indeterminate = false, className = "", ...rest }) {
600
+ const inputRef = (0, import_react5.useRef)(null);
601
+ (0, import_react5.useEffect)(() => {
602
+ if (inputRef.current) inputRef.current.indeterminate = indeterminate;
603
+ }, [indeterminate]);
604
+ return withLabel(
605
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
606
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { ref: inputRef, type: "checkbox", className: `mcl-check-input ${className}`.trim(), ...rest }),
607
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "mcl-check-box", "aria-hidden": "true" })
608
+ ] }),
609
+ label
610
+ );
611
+ }
612
+ function CheckboxGroup({
613
+ options,
614
+ value,
615
+ defaultValue = [],
616
+ onChange,
617
+ selectAll = false,
618
+ selectAllLabel = "Select all",
619
+ label,
620
+ disabled = false,
621
+ className = ""
622
+ }) {
623
+ const [inner, setInner] = (0, import_react5.useState)(defaultValue);
624
+ const allRef = (0, import_react5.useRef)(null);
625
+ const selected = value ?? inner;
626
+ const enabled = options.filter((o) => !o.disabled).map((o) => o.value);
627
+ const allOn = enabled.length > 0 && enabled.every((v) => selected.includes(v));
628
+ const someOn = enabled.some((v) => selected.includes(v));
629
+ (0, import_react5.useEffect)(() => {
630
+ if (allRef.current) allRef.current.indeterminate = someOn && !allOn;
631
+ }, [someOn, allOn]);
632
+ const commit = (next) => {
633
+ setInner(next);
634
+ onChange?.(next);
635
+ };
636
+ const toggle = (v) => {
637
+ commit(selected.includes(v) ? selected.filter((x) => x !== v) : [...selected, v]);
638
+ };
639
+ const toggleAll = () => {
640
+ commit(allOn ? selected.filter((v) => !enabled.includes(v)) : Array.from(/* @__PURE__ */ new Set([...selected, ...enabled])));
641
+ };
642
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
643
+ "div",
644
+ {
645
+ className: `mcl-check-group ${className}`.trim(),
646
+ role: "group",
647
+ "aria-label": typeof label === "string" ? label : void 0,
648
+ children: [
649
+ label && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "mcl-label", children: label }),
650
+ selectAll && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: `mcl-check mcl-check-group-all${disabled ? " mcl-check-disabled" : ""}`, children: [
651
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
652
+ "input",
653
+ {
654
+ ref: allRef,
655
+ type: "checkbox",
656
+ className: "mcl-check-input",
657
+ checked: allOn,
658
+ disabled,
659
+ onChange: toggleAll
660
+ }
661
+ ),
662
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "mcl-check-box", "aria-hidden": "true" }),
663
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "mcl-check-label", children: selectAllLabel })
664
+ ] }),
665
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mcl-check-group-items", children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: `mcl-check${o.disabled || disabled ? " mcl-check-disabled" : ""}`, children: [
666
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
667
+ "input",
668
+ {
669
+ type: "checkbox",
670
+ className: "mcl-check-input",
671
+ checked: selected.includes(o.value),
672
+ disabled: o.disabled || disabled,
673
+ onChange: () => toggle(o.value)
674
+ }
675
+ ),
676
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "mcl-check-box", "aria-hidden": "true" }),
677
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "mcl-check-label", children: o.label })
678
+ ] }, o.value)) })
679
+ ]
680
+ }
681
+ );
682
+ }
683
+ function Radio({ label, className = "", ...rest }) {
684
+ return withLabel(
685
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
686
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "radio", className: `mcl-check-input ${className}`.trim(), ...rest }),
687
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "mcl-check-box mcl-radio-box", "aria-hidden": "true" })
688
+ ] }),
689
+ label
690
+ );
691
+ }
692
+ function Switch({ label, className = "", ...rest }) {
693
+ return withLabel(
694
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
695
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
696
+ "input",
697
+ {
698
+ type: "checkbox",
699
+ role: "switch",
700
+ className: `mcl-switch-input ${className}`.trim(),
701
+ ...rest
702
+ }
703
+ ),
704
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "mcl-switch-track", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "mcl-switch-knob" }) })
705
+ ] }),
706
+ label
707
+ );
708
+ }
709
+
710
+ // src/components/dropdown/dropdown.tsx
711
+ var import_react6 = require("react");
712
+ var import_jsx_runtime9 = require("react/jsx-runtime");
713
+ function Dropdown({
714
+ items,
715
+ value,
716
+ defaultValue,
717
+ onChange,
718
+ multiple = false,
719
+ placeholder = "Select\u2026",
720
+ label,
721
+ hint,
722
+ size = "md",
723
+ block = false,
724
+ disabled = false,
725
+ className = ""
726
+ }) {
727
+ const [open, setOpen] = (0, import_react6.useState)(false);
728
+ const [inner, setInner] = (0, import_react6.useState)(defaultValue);
729
+ const [active, setActive] = (0, import_react6.useState)(0);
730
+ const [flip, setFlip] = (0, import_react6.useState)({ up: false, left: false });
731
+ const shellRef = (0, import_react6.useRef)(null);
732
+ const menuRef = (0, import_react6.useRef)(null);
733
+ const triggerRef = (0, import_react6.useRef)(null);
734
+ const current = value ?? inner;
735
+ const selectedValues = multiple ? Array.isArray(current) ? current : [] : [];
736
+ const singleValue = !multiple && !Array.isArray(current) ? current : void 0;
737
+ const labelFor = (v) => items.find((i) => i.value === v)?.label;
738
+ let triggerText = placeholder;
739
+ if (multiple) {
740
+ if (selectedValues.length > 0) {
741
+ const labels = items.filter((i) => selectedValues.includes(i.value)).map((i) => i.label);
742
+ triggerText = labels.length <= 2 ? labels.join(", ") : `${labels.length} selected`;
743
+ }
744
+ } else if (singleValue !== void 0) {
745
+ triggerText = labelFor(singleValue) ?? singleValue;
746
+ }
747
+ const hasSelection = multiple ? selectedValues.length > 0 : singleValue !== void 0 && singleValue !== "";
748
+ (0, import_react6.useEffect)(() => {
749
+ if (!open) return;
750
+ const onDown = (e) => {
751
+ if (shellRef.current && !shellRef.current.contains(e.target)) {
752
+ setOpen(false);
753
+ triggerRef.current?.focus();
754
+ }
755
+ };
756
+ document.addEventListener("mousedown", onDown);
757
+ return () => document.removeEventListener("mousedown", onDown);
758
+ }, [open]);
759
+ (0, import_react6.useEffect)(() => {
760
+ if (!open) return;
761
+ const firstSelected = multiple ? items.findIndex((i) => selectedValues.includes(i.value)) : items.findIndex((i) => i.value === singleValue);
762
+ const firstEnabled = items.findIndex((i) => !i.disabled);
763
+ const idx = firstSelected >= 0 ? firstSelected : Math.max(firstEnabled, 0);
764
+ setActive(idx);
765
+ menuRef.current?.focus();
766
+ const t = window.setTimeout(() => {
767
+ const el = menuRef.current?.children[idx];
768
+ if (el && typeof el.scrollIntoView === "function") el.scrollIntoView({ block: "nearest" });
769
+ }, 0);
770
+ return () => window.clearTimeout(t);
771
+ }, [open]);
772
+ (0, import_react6.useEffect)(() => {
773
+ if (!open) return;
774
+ const t = window.setTimeout(() => {
775
+ const trig = triggerRef.current;
776
+ const menu = menuRef.current;
777
+ if (!trig || !menu) return;
778
+ const r = trig.getBoundingClientRect();
779
+ const m = menu.getBoundingClientRect();
780
+ const below = window.innerHeight - r.bottom;
781
+ const above = r.top;
782
+ setFlip({
783
+ up: below < m.height + 12 && above > below,
784
+ left: r.left + Math.max(m.width, r.width) > window.innerWidth - 12
785
+ });
786
+ }, 0);
787
+ return () => window.clearTimeout(t);
788
+ }, [open]);
789
+ const close = (refocus = true) => {
790
+ setOpen(false);
791
+ if (refocus) triggerRef.current?.focus();
792
+ };
793
+ const commit = (v) => {
794
+ if (multiple) {
795
+ const next = selectedValues.includes(v) ? selectedValues.filter((x) => x !== v) : [...selectedValues, v];
796
+ setInner(next);
797
+ onChange?.(next);
798
+ } else {
799
+ setInner(v);
800
+ onChange?.(v);
801
+ close();
802
+ }
803
+ };
804
+ const move = (dir) => {
805
+ const enabled = items.map((it, i) => it.disabled ? -1 : i).filter((i) => i >= 0);
806
+ if (enabled.length === 0) return;
807
+ const pos = enabled.indexOf(active);
808
+ const next = enabled[(pos + dir + enabled.length) % enabled.length];
809
+ setActive(next);
810
+ const el = menuRef.current?.children[next];
811
+ if (el && typeof el.scrollIntoView === "function") el.scrollIntoView({ block: "nearest" });
812
+ };
813
+ const onMenuKeyDown = (e) => {
814
+ if (e.key === "Escape") {
815
+ e.preventDefault();
816
+ close();
817
+ } else if (e.key === "ArrowDown") {
818
+ e.preventDefault();
819
+ move(1);
820
+ } else if (e.key === "ArrowUp") {
821
+ e.preventDefault();
822
+ move(-1);
823
+ } else if (e.key === "Home") {
824
+ e.preventDefault();
825
+ const first = items.findIndex((i) => !i.disabled);
826
+ if (first >= 0) setActive(first);
827
+ } else if (e.key === "End") {
828
+ e.preventDefault();
829
+ const last = items.map((i, idx) => i.disabled ? -1 : idx).filter((i) => i >= 0).pop();
830
+ if (last !== void 0) setActive(last);
831
+ } else if (e.key === "Enter" || e.key === " ") {
832
+ e.preventDefault();
833
+ const it = items[active];
834
+ if (it && !it.disabled) commit(it.value);
835
+ } else if (e.key === "Tab") {
836
+ setOpen(false);
837
+ }
838
+ };
839
+ const onTriggerKeyDown = (e) => {
840
+ if (!open && e.key === "ArrowDown") {
841
+ e.preventDefault();
842
+ setOpen(true);
843
+ }
844
+ };
845
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: `mcl-field${block ? " mcl-field-block" : ""} ${className}`.trim(), children: [
846
+ label && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "mcl-label", children: label }),
847
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
848
+ "div",
849
+ {
850
+ ref: shellRef,
851
+ className: `mcl-dropdown-shell${block ? " mcl-dropdown-block" : ""}`,
852
+ children: [
853
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
854
+ "button",
855
+ {
856
+ ref: triggerRef,
857
+ type: "button",
858
+ className: `mcl-dropdown-trigger mcl-dropdown-${size}`,
859
+ "aria-haspopup": "listbox",
860
+ "aria-expanded": open,
861
+ disabled,
862
+ onClick: () => setOpen((o) => !o),
863
+ onKeyDown: onTriggerKeyDown,
864
+ children: [
865
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: `mcl-dropdown-value${hasSelection ? "" : " mcl-dropdown-placeholder"}`, children: triggerText }),
866
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "mcl-dropdown-chevron", "aria-hidden": "true" })
867
+ ]
868
+ }
869
+ ),
870
+ open && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
871
+ "div",
872
+ {
873
+ ref: menuRef,
874
+ tabIndex: -1,
875
+ role: "listbox",
876
+ "aria-multiselectable": multiple || void 0,
877
+ className: [
878
+ "mcl-dropdown-menu",
879
+ "mcl-scroll",
880
+ `mcl-dropdown-${size}`,
881
+ flip.up ? "mcl-dropdown-menu-up" : "",
882
+ flip.left ? "mcl-dropdown-menu-left" : ""
883
+ ].filter(Boolean).join(" "),
884
+ onKeyDown: onMenuKeyDown,
885
+ children: items.map((it, i) => {
886
+ const selected = multiple ? selectedValues.includes(it.value) : singleValue === it.value;
887
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
888
+ "div",
889
+ {
890
+ role: "option",
891
+ "aria-selected": selected,
892
+ "aria-disabled": it.disabled || void 0,
893
+ className: [
894
+ "mcl-dropdown-item",
895
+ i === active ? "mcl-dropdown-item-active" : "",
896
+ selected ? "mcl-dropdown-item-selected" : "",
897
+ it.disabled ? "mcl-dropdown-item-disabled" : ""
898
+ ].filter(Boolean).join(" "),
899
+ onMouseEnter: () => setActive(i),
900
+ onClick: () => {
901
+ if (!it.disabled) commit(it.value);
902
+ },
903
+ children: [
904
+ multiple && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "mcl-dropdown-check", "aria-hidden": "true" }),
905
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "mcl-dropdown-item-label", children: it.label }),
906
+ !multiple && selected && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "mcl-dropdown-tick", "aria-hidden": "true", children: "\u2713" })
907
+ ]
908
+ },
909
+ it.value
910
+ );
911
+ })
912
+ }
913
+ )
914
+ ]
915
+ }
916
+ ),
917
+ hint && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "mcl-hint", children: hint })
918
+ ] });
919
+ }
920
+
921
+ // src/components/range/range.tsx
922
+ var import_react7 = __toESM(require("react"));
923
+ var import_jsx_runtime10 = require("react/jsx-runtime");
924
+ function Range({
925
+ label,
926
+ hint,
927
+ showValue = false,
928
+ value,
929
+ defaultValue,
930
+ onChange,
931
+ className = "",
932
+ id,
933
+ ...rest
934
+ }) {
935
+ const autoId = import_react7.default.useId();
936
+ const inputId = id ?? autoId;
937
+ const isControlled = value !== void 0;
938
+ const [inner, setInner] = (0, import_react7.useState)(
939
+ () => value !== void 0 ? String(value) : defaultValue !== void 0 ? String(defaultValue) : "0"
940
+ );
941
+ const current = isControlled ? String(value) : inner;
942
+ const input = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
943
+ "input",
944
+ {
945
+ id: inputId,
946
+ type: "range",
947
+ className: `mcl-range ${className}`.trim(),
948
+ value: isControlled ? value : inner,
949
+ onChange: (e) => {
950
+ if (!isControlled) setInner(e.target.value);
951
+ onChange?.(e);
952
+ },
953
+ ...rest
954
+ }
955
+ );
956
+ const field = /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mcl-field", children: [
957
+ label && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "mcl-range-head", htmlFor: inputId, children: [
958
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "mcl-label", children: label }),
959
+ showValue && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "mcl-range-value", children: current })
960
+ ] }),
961
+ input,
962
+ hint && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mcl-hint", children: hint })
963
+ ] });
964
+ if (!label && !hint) return input;
965
+ return field;
966
+ }
967
+
968
+ // src/components/badge/badge.tsx
969
+ var import_jsx_runtime11 = require("react/jsx-runtime");
970
+ function Badge({ variant = "neutral", solid = false, className = "", ...rest }) {
971
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
972
+ "span",
973
+ {
974
+ className: `mcl-badge mcl-badge-${variant}${solid ? " mcl-badge-solid" : ""} ${className}`.trim(),
975
+ ...rest
976
+ }
977
+ );
978
+ }
979
+
980
+ // src/components/alert/alert.tsx
981
+ var import_jsx_runtime12 = require("react/jsx-runtime");
982
+ var DEFAULT_ICONS = {
983
+ success: "\u2713",
984
+ danger: "\u2715",
985
+ warning: "!",
986
+ info: "i"
987
+ };
988
+ function Alert({
989
+ variant = "info",
990
+ title,
991
+ icon,
992
+ onClose,
993
+ className = "",
994
+ children,
995
+ ...rest
996
+ }) {
997
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `mcl-alert mcl-alert-${variant} ${className}`.trim(), role: "alert", ...rest, children: [
998
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "mcl-alert-icon", "aria-hidden": "true", children: icon ?? DEFAULT_ICONS[variant] }),
999
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mcl-alert-content", children: [
1000
+ title && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mcl-alert-title", children: title }),
1001
+ children
1002
+ ] }),
1003
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: "mcl-alert-close", onClick: onClose, "aria-label": "Dismiss", children: "\u2715" })
1004
+ ] });
1005
+ }
1006
+
1007
+ // src/components/avatar/avatar.tsx
1008
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1009
+ function initialsOf(name) {
1010
+ const parts = name.trim().split(/\s+/).slice(0, 2);
1011
+ return parts.map((p) => p[0]?.toUpperCase() ?? "").join("");
1012
+ }
1013
+ function Avatar({
1014
+ src,
1015
+ alt,
1016
+ name,
1017
+ size = "md",
1018
+ status,
1019
+ gradient = false,
1020
+ className = "",
1021
+ children,
1022
+ ...rest
1023
+ }) {
1024
+ const label = alt ?? (name ? `${name}'s avatar` : "avatar");
1025
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1026
+ "span",
1027
+ {
1028
+ className: `mcl-avatar mcl-avatar-${size}${gradient ? " mcl-avatar-gradient" : ""} ${className}`.trim(),
1029
+ role: "img",
1030
+ "aria-label": label,
1031
+ ...rest,
1032
+ children: [
1033
+ src ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("img", { src, alt: "", className: "mcl-avatar-img", loading: "lazy", decoding: "async" }) : children ?? initialsOf(name ?? "??") ?? "",
1034
+ status && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: `mcl-avatar-status mcl-avatar-status-${status}`, "aria-hidden": "true" })
1035
+ ]
1036
+ }
1037
+ );
1038
+ }
1039
+ function AvatarGroup({ className = "", children, ...rest }) {
1040
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: `mcl-avatar-group ${className}`.trim(), ...rest, children });
1041
+ }
1042
+
1043
+ // src/components/progress/progress.tsx
1044
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1045
+ function Progress({
1046
+ value = 0,
1047
+ max = 100,
1048
+ tone = "primary",
1049
+ size = "md",
1050
+ label,
1051
+ showValue = false,
1052
+ indeterminate = false,
1053
+ className = ""
1054
+ }) {
1055
+ const pct = Math.max(0, Math.min(100, value / max * 100));
1056
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1057
+ "div",
1058
+ {
1059
+ className: `mcl-progress mcl-progress-${size} ${className}`.trim(),
1060
+ role: "progressbar",
1061
+ "aria-valuemin": 0,
1062
+ "aria-valuemax": max,
1063
+ "aria-valuenow": indeterminate ? void 0 : Math.round(pct),
1064
+ children: [
1065
+ (label || showValue) && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mcl-progress-head", children: [
1066
+ label && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: label }),
1067
+ showValue && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "mcl-progress-value", children: indeterminate ? "\u2026" : `${Math.round(pct)}%` })
1068
+ ] }),
1069
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "mcl-progress-track", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1070
+ "span",
1071
+ {
1072
+ className: `mcl-progress-fill mcl-progress-fill-${tone}${indeterminate ? " mcl-progress-fill-indeterminate" : ""}`,
1073
+ style: indeterminate ? void 0 : { width: `${pct}%` }
1074
+ }
1075
+ ) })
1076
+ ]
1077
+ }
1078
+ );
1079
+ }
1080
+
1081
+ // src/components/spinner/spinner.tsx
1082
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1083
+ function Spinner({ size = "md", className = "" }) {
1084
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: `mcl-spinner mcl-spinner-${size} ${className}`.trim(), role: "status", "aria-label": "Loading" });
1085
+ }
1086
+
1087
+ // src/components/skeleton/skeleton.tsx
1088
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1089
+ function Skeleton({ variant = "text", width, height, count = 1, className = "" }) {
1090
+ const lines = variant === "text" ? Math.max(1, count) : 1;
1091
+ const style = (last) => ({
1092
+ width: width ?? (variant === "circle" ? 48 : "100%"),
1093
+ height: height ?? (variant === "text" ? 14 : variant === "circle" ? 48 : 96),
1094
+ ...variant === "text" && count > 1 && last ? { width: "62%" } : null
1095
+ });
1096
+ if (lines === 1) {
1097
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1098
+ "span",
1099
+ {
1100
+ className: `mcl-skeleton mcl-skeleton-${variant} ${className}`.trim(),
1101
+ style: style(true),
1102
+ "aria-hidden": "true"
1103
+ }
1104
+ );
1105
+ }
1106
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: `mcl-skeleton-lines ${className}`.trim(), "aria-hidden": "true", children: Array.from({ length: lines }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "mcl-skeleton mcl-skeleton-text", style: style(i === lines - 1) }, i)) });
1107
+ }
1108
+
1109
+ // src/components/modal/modal.tsx
1110
+ var import_react8 = require("react");
1111
+ var import_react_dom = require("react-dom");
1112
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1113
+ var FOCUSABLE = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
1114
+ function Modal({
1115
+ open,
1116
+ onClose,
1117
+ title,
1118
+ footer,
1119
+ size = "md",
1120
+ closeOnBackdrop = true,
1121
+ closeOnEsc = true,
1122
+ children,
1123
+ className = ""
1124
+ }) {
1125
+ const [mounted, setMounted] = (0, import_react8.useState)(false);
1126
+ const panelRef = (0, import_react8.useRef)(null);
1127
+ const lastFocusedRef = (0, import_react8.useRef)(null);
1128
+ const titleId = (0, import_react8.useId)();
1129
+ (0, import_react8.useEffect)(() => setMounted(true), []);
1130
+ (0, import_react8.useEffect)(() => {
1131
+ if (!open) return;
1132
+ lastFocusedRef.current = document.activeElement;
1133
+ const onKey = (e) => {
1134
+ if (e.key === "Escape" && closeOnEsc) onClose();
1135
+ };
1136
+ document.addEventListener("keydown", onKey);
1137
+ const prevOverflow = document.body.style.overflow;
1138
+ document.body.style.overflow = "hidden";
1139
+ panelRef.current?.focus();
1140
+ return () => {
1141
+ document.removeEventListener("keydown", onKey);
1142
+ document.body.style.overflow = prevOverflow;
1143
+ lastFocusedRef.current?.focus?.();
1144
+ };
1145
+ }, [open, onClose, closeOnEsc]);
1146
+ const trapFocus = (e) => {
1147
+ if (e.key !== "Tab" || !panelRef.current) return;
1148
+ const focusable = Array.from(panelRef.current.querySelectorAll(FOCUSABLE)).filter(
1149
+ (el) => el.offsetParent !== null
1150
+ );
1151
+ if (focusable.length === 0) {
1152
+ e.preventDefault();
1153
+ return;
1154
+ }
1155
+ const first = focusable[0];
1156
+ const last = focusable[focusable.length - 1];
1157
+ const active = document.activeElement;
1158
+ if (e.shiftKey && (active === first || !panelRef.current.contains(active))) {
1159
+ e.preventDefault();
1160
+ last.focus();
1161
+ } else if (!e.shiftKey && active === last) {
1162
+ e.preventDefault();
1163
+ first.focus();
1164
+ }
1165
+ };
1166
+ if (!open || !mounted) return null;
1167
+ return (0, import_react_dom.createPortal)(
1168
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1169
+ "div",
1170
+ {
1171
+ className: "mcl-modal-overlay",
1172
+ onMouseDown: (e) => {
1173
+ if (e.target === e.currentTarget && closeOnBackdrop) onClose();
1174
+ },
1175
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1176
+ "div",
1177
+ {
1178
+ ref: panelRef,
1179
+ className: `mcl-modal mcl-modal-${size} ${className}`.trim(),
1180
+ role: "dialog",
1181
+ "aria-modal": "true",
1182
+ "aria-labelledby": title ? titleId : void 0,
1183
+ tabIndex: -1,
1184
+ onKeyDown: trapFocus,
1185
+ children: [
1186
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "mcl-modal-header", children: [
1187
+ title ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h3", { id: titleId, className: "mcl-modal-title", children: title }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", {}),
1188
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "mcl-modal-close", onClick: onClose, "aria-label": "Close dialog", children: "\u2715" })
1189
+ ] }),
1190
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "mcl-modal-body mcl-scroll", children }),
1191
+ footer && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "mcl-modal-footer", children: footer })
1192
+ ]
1193
+ }
1194
+ )
1195
+ }
1196
+ ),
1197
+ document.body
1198
+ );
1199
+ }
1200
+
1201
+ // src/components/tooltip/tooltip.tsx
1202
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1203
+ function Tooltip({ label, placement = "top", className = "", children }) {
1204
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: `mcl-tooltip mcl-tooltip-${placement} ${className}`.trim(), "data-mcl-tooltip": label, children });
1205
+ }
1206
+
1207
+ // src/components/tabs/tabs.tsx
1208
+ var import_react9 = require("react");
1209
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1210
+ function Tabs({ items, value, onChange, className = "" }) {
1211
+ const uid = (0, import_react9.useId)();
1212
+ const [inner, setInner] = (0, import_react9.useState)(0);
1213
+ const active = value ?? inner;
1214
+ const tabRefs = (0, import_react9.useRef)([]);
1215
+ const select = (i) => {
1216
+ if (items[i]?.disabled) return;
1217
+ setInner(i);
1218
+ onChange?.(i);
1219
+ };
1220
+ const onKeyDown = (e) => {
1221
+ const focusable = items.map((it, i) => it.disabled ? -1 : i).filter((i) => i >= 0);
1222
+ let next = -1;
1223
+ if (e.key === "ArrowRight") next = focusable[(focusable.indexOf(active) + 1) % focusable.length];
1224
+ if (e.key === "ArrowLeft") next = focusable[(focusable.indexOf(active) - 1 + focusable.length) % focusable.length];
1225
+ if (e.key === "Home") next = focusable[0];
1226
+ if (e.key === "End") next = focusable[focusable.length - 1];
1227
+ if (next >= 0 && next !== active) {
1228
+ e.preventDefault();
1229
+ select(next);
1230
+ tabRefs.current[next]?.focus();
1231
+ }
1232
+ };
1233
+ const current = items[active];
1234
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: `mcl-tabs ${className}`.trim(), children: [
1235
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "mcl-tablist", role: "tablist", "aria-label": "Tabs", onKeyDown, children: items.map((it, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1236
+ "button",
1237
+ {
1238
+ ref: (el) => {
1239
+ tabRefs.current[i] = el;
1240
+ },
1241
+ type: "button",
1242
+ role: "tab",
1243
+ id: `mcl-tab-${uid}-${it.key}`,
1244
+ "aria-selected": i === active,
1245
+ "aria-controls": `mcl-panel-${uid}-${it.key}`,
1246
+ tabIndex: i === active ? 0 : -1,
1247
+ className: `mcl-tab${i === active ? " mcl-tab-active" : ""}`,
1248
+ disabled: it.disabled,
1249
+ onClick: () => select(i),
1250
+ children: it.label
1251
+ },
1252
+ it.key
1253
+ )) }),
1254
+ current && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1255
+ "div",
1256
+ {
1257
+ role: "tabpanel",
1258
+ id: `mcl-panel-${uid}-${current.key}`,
1259
+ "aria-labelledby": `mcl-tab-${uid}-${current.key}`,
1260
+ className: "mcl-tabpanel",
1261
+ children: current.content
1262
+ },
1263
+ current.key
1264
+ )
1265
+ ] });
1266
+ }
1267
+
1268
+ // src/components/accordion/accordion.tsx
1269
+ var import_react10 = require("react");
1270
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1271
+ function Accordion({ items, defaultOpen = -1, exclusive = true, className = "" }) {
1272
+ const uid = (0, import_react10.useId)();
1273
+ const [openSet, setOpenSet] = (0, import_react10.useState)(
1274
+ () => new Set(defaultOpen >= 0 ? [defaultOpen] : [])
1275
+ );
1276
+ const panelRefs = (0, import_react10.useRef)([]);
1277
+ const [heights, setHeights] = (0, import_react10.useState)([]);
1278
+ const measure = () => {
1279
+ setHeights(items.map((_, i) => panelRefs.current[i]?.scrollHeight ?? 0));
1280
+ };
1281
+ (0, import_react10.useEffect)(() => {
1282
+ measure();
1283
+ window.addEventListener("resize", measure);
1284
+ return () => window.removeEventListener("resize", measure);
1285
+ }, [items, openSet]);
1286
+ const toggle = (i) => {
1287
+ if (!openSet.has(i)) {
1288
+ const h = panelRefs.current[i]?.scrollHeight ?? 0;
1289
+ setHeights((prev) => prev[i] === h ? prev : prev.map((x, j) => j === i ? h : x));
1290
+ }
1291
+ setOpenSet((prev) => {
1292
+ const next = new Set(exclusive ? [] : prev);
1293
+ if (prev.has(i)) next.delete(i);
1294
+ else next.add(i);
1295
+ return next;
1296
+ });
1297
+ };
1298
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: `mcl-accordion ${className}`.trim(), children: items.map((item, i) => {
1299
+ const open = openSet.has(i);
1300
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: `mcl-accordion-item${open ? " mcl-accordion-item-open" : ""}`, children: [
1301
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1302
+ "button",
1303
+ {
1304
+ type: "button",
1305
+ className: "mcl-accordion-header",
1306
+ "aria-expanded": open,
1307
+ "aria-controls": `mcl-acc-${uid}-${i}`,
1308
+ onClick: () => toggle(i),
1309
+ children: [
1310
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: item.title }),
1311
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "mcl-accordion-chevron", "aria-hidden": "true", children: "\u25BE" })
1312
+ ]
1313
+ }
1314
+ ),
1315
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1316
+ "div",
1317
+ {
1318
+ id: `mcl-acc-${uid}-${i}`,
1319
+ ref: (el) => {
1320
+ panelRefs.current[i] = el;
1321
+ },
1322
+ className: "mcl-accordion-panel",
1323
+ style: { maxHeight: open ? heights[i] || 999 : 0 },
1324
+ role: "region",
1325
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "mcl-accordion-panel-inner", children: item.content })
1326
+ }
1327
+ )
1328
+ ] }, i);
1329
+ }) });
1330
+ }
1331
+
1332
+ // src/components/toast/toast.tsx
1333
+ var import_react11 = require("react");
1334
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1335
+ var ToastContext = (0, import_react11.createContext)(null);
1336
+ function ToastProvider({ children, placement = "bottom-right" }) {
1337
+ const [toasts, setToasts] = (0, import_react11.useState)([]);
1338
+ const idRef = (0, import_react11.useRef)(0);
1339
+ const timersRef = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
1340
+ const dismiss = (0, import_react11.useCallback)((id) => {
1341
+ const timer = timersRef.current.get(id);
1342
+ if (timer !== void 0) {
1343
+ window.clearTimeout(timer);
1344
+ timersRef.current.delete(id);
1345
+ }
1346
+ setToasts((list) => list.filter((t) => t.id !== id));
1347
+ }, []);
1348
+ const toast = (0, import_react11.useCallback)(
1349
+ (o) => {
1350
+ const id = ++idRef.current;
1351
+ setToasts((list) => [...list, { ...o, id }].slice(-4));
1352
+ const d = o.duration ?? 4200;
1353
+ if (d > 0) {
1354
+ const timer = window.setTimeout(() => dismiss(id), d);
1355
+ timersRef.current.set(id, timer);
1356
+ }
1357
+ },
1358
+ [dismiss]
1359
+ );
1360
+ (0, import_react11.useEffect)(
1361
+ () => () => {
1362
+ timersRef.current.forEach((timer) => window.clearTimeout(timer));
1363
+ timersRef.current.clear();
1364
+ },
1365
+ []
1366
+ );
1367
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(ToastContext.Provider, { value: { toast, dismiss }, children: [
1368
+ children,
1369
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: `mcl-toasts mcl-toasts-${placement}`, "aria-live": "polite", children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToastCard, { item: t, onClose: () => dismiss(t.id) }, t.id)) })
1370
+ ] });
1371
+ }
1372
+ function ToastCard({ item, onClose }) {
1373
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `mcl-toast mcl-toast-${item.variant ?? "info"}`, role: "status", children: [
1374
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "mcl-toast-dot", "aria-hidden": "true" }),
1375
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mcl-toast-content", children: [
1376
+ item.title && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mcl-toast-title", children: item.title }),
1377
+ item.message && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mcl-toast-message", children: item.message })
1378
+ ] }),
1379
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: "mcl-toast-close", onClick: onClose, "aria-label": "Dismiss notification", children: "\u2715" })
1380
+ ] });
1381
+ }
1382
+ function useToast() {
1383
+ const ctx = (0, import_react11.useContext)(ToastContext);
1384
+ if (!ctx) throw new Error("useToast must be used inside <ToastProvider>.");
1385
+ return ctx;
1386
+ }
1387
+
1388
+ // src/components/navbar/navbar.tsx
1389
+ var import_react12 = require("react");
1390
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1391
+ function Navbar({ brand, links = [], activeHref, right, sticky = true, className = "" }) {
1392
+ const [open, setOpen] = (0, import_react12.useState)(false);
1393
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("nav", { className: `mcl-navbar${sticky ? " mcl-navbar-sticky" : ""} ${className}`.trim(), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "mcl-navbar-inner", children: [
1394
+ brand && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("a", { className: "mcl-navbar-brand", href: "/", children: brand }),
1395
+ links.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1396
+ "button",
1397
+ {
1398
+ type: "button",
1399
+ className: "mcl-navbar-toggle",
1400
+ "aria-expanded": open,
1401
+ "aria-label": "Toggle menu",
1402
+ onClick: () => setOpen((o) => !o),
1403
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "mcl-navbar-burger", "aria-hidden": "true" })
1404
+ }
1405
+ ),
1406
+ links.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("ul", { className: `mcl-navbar-links${open ? " mcl-navbar-open" : ""}`, children: links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1407
+ "a",
1408
+ {
1409
+ href: l.href,
1410
+ className: `mcl-navbar-link${activeHref === l.href ? " mcl-navbar-link-active" : ""}`,
1411
+ onClick: () => setOpen(false),
1412
+ "aria-current": activeHref === l.href ? "page" : void 0,
1413
+ children: l.label
1414
+ }
1415
+ ) }, l.href)) }),
1416
+ right && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "mcl-navbar-right", children: right })
1417
+ ] }) });
1418
+ }
1419
+
1420
+ // src/components/stat/stat.tsx
1421
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1422
+ function Stat({ value, label, tone = "primary", className = "" }) {
1423
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `mcl-stat mcl-stat-${tone} ${className}`.trim(), children: [
1424
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("b", { className: "mcl-stat-value", children: value }),
1425
+ label && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "mcl-stat-label", children: label })
1426
+ ] });
1427
+ }
1428
+
1429
+ // src/components/divider/divider.tsx
1430
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1431
+ function Divider({ orientation = "horizontal", label, className = "", ...rest }) {
1432
+ if (label !== void 0 && label !== null) {
1433
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: `mcl-divider-label ${className}`.trim(), role: "separator", ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "mcl-divider-label-text", children: label }) });
1434
+ }
1435
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1436
+ "div",
1437
+ {
1438
+ className: `mcl-divider mcl-divider-${orientation} ${className}`.trim(),
1439
+ role: "separator",
1440
+ ...rest
1441
+ }
1442
+ );
1443
+ }
1444
+
1445
+ // src/components/stack/stack.tsx
1446
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1447
+ function Stack({
1448
+ direction = "column",
1449
+ gap = "md",
1450
+ wrap = false,
1451
+ align,
1452
+ justify,
1453
+ className = "",
1454
+ ...rest
1455
+ }) {
1456
+ const cls = [
1457
+ "mcl-stack",
1458
+ direction === "row" ? "mcl-stack-row" : "",
1459
+ `mcl-stack-gap-${gap}`,
1460
+ wrap ? "mcl-stack-wrap" : "",
1461
+ align ? `mcl-stack-align-${align}` : "",
1462
+ justify ? `mcl-stack-justify-${justify}` : "",
1463
+ className
1464
+ ].filter(Boolean).join(" ");
1465
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: cls, ...rest });
1466
+ }
1467
+ // Annotate the CommonJS export names for ESM import in node:
1468
+ 0 && (module.exports = {
1469
+ Accordion,
1470
+ Alert,
1471
+ Avatar,
1472
+ AvatarGroup,
1473
+ Badge,
1474
+ Button,
1475
+ ButtonGroup,
1476
+ COLOR_SWATCHES,
1477
+ Card,
1478
+ CardBody,
1479
+ CardFooter,
1480
+ CardHeader,
1481
+ CardTitle,
1482
+ Checkbox,
1483
+ CheckboxGroup,
1484
+ Divider,
1485
+ Dropdown,
1486
+ Input,
1487
+ Kbd,
1488
+ MarclayProvider,
1489
+ Modal,
1490
+ Navbar,
1491
+ PRESETS,
1492
+ Progress,
1493
+ Radio,
1494
+ Range,
1495
+ Skeleton,
1496
+ Spinner,
1497
+ Stack,
1498
+ Stat,
1499
+ Switch,
1500
+ Tabs,
1501
+ Textarea,
1502
+ ThemeMenu,
1503
+ ThemeProvider,
1504
+ ThemeToggle,
1505
+ ToastProvider,
1506
+ Tooltip,
1507
+ useTheme,
1508
+ useToast
1509
+ });
1510
+ //# sourceMappingURL=index.cjs.map