najm-kit 0.0.18 → 0.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -27,9 +27,12 @@ import { Command as Command$1 } from 'cmdk';
27
27
  import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
28
28
  import * as TogglePrimitive from '@radix-ui/react-toggle';
29
29
  import { Toaster as Toaster$1 } from 'sonner';
30
+ export { toast } from 'sonner';
30
31
  import { FormProvider, Controller, useFormContext, useForm, useFieldArray } from 'react-hook-form';
31
32
  import { defaultStyles, FileIcon } from 'react-file-icon';
32
33
  import { format } from 'date-fns';
34
+ import { HexColorPicker } from 'react-colorful';
35
+ import { converter, parse, formatHsl, formatRgb, formatHex } from 'culori';
33
36
  import { PhoneInput as PhoneInput$1, defaultCountries } from 'react-international-phone';
34
37
  import * as SliderPrimitive from '@radix-ui/react-slider';
35
38
  import { zodResolver } from '@hookform/resolvers/zod';
@@ -47,6 +50,8 @@ var lightMode = {
47
50
  "popover-foreground": "oklch(0.1445 0 0)",
48
51
  secondary: "oklch(0.9703 0 0)",
49
52
  "secondary-foreground": "oklch(0.2044 0 0)",
53
+ tertiary: "oklch(0.9676 0.007 247.897)",
54
+ "tertiary-foreground": "oklch(0.3138 0.0453 249.447)",
50
55
  muted: "oklch(0.9703 0 0)",
51
56
  "muted-foreground": "oklch(0.5555 0 0)",
52
57
  accent: "oklch(0.9703 0 0)",
@@ -54,10 +59,16 @@ var lightMode = {
54
59
  destructive: "oklch(0.6368 0.2078 25.326)",
55
60
  "destructive-foreground": "oklch(0.9848 0 0)",
56
61
  border: "oklch(0.9219 0 0)",
57
- "border-subtle": "oklch(0.9619 0 0)",
58
- "border-strong": "oklch(0.4184 0 0)",
59
62
  input: "oklch(0.9219 0 0)",
60
- radius: "0.5rem"
63
+ radius: "0.5rem",
64
+ sidebar: "oklch(0.985 0 0)",
65
+ "sidebar-foreground": "oklch(0.1445 0 0)",
66
+ "sidebar-primary": "oklch(0.2228 0.0043 286.044)",
67
+ "sidebar-primary-foreground": "oklch(0.9848 0 0)",
68
+ "sidebar-accent": "oklch(0.9703 0 0)",
69
+ "sidebar-accent-foreground": "oklch(0.2044 0 0)",
70
+ "sidebar-border": "oklch(0.9219 0 0)",
71
+ "sidebar-ring": "oklch(0.2228 0.0043 286.044)"
61
72
  };
62
73
  var darkMode = {
63
74
  background: "oklch(0.1417 0.0044 285.819)",
@@ -68,6 +79,8 @@ var darkMode = {
68
79
  "popover-foreground": "oklch(0.9683 0.0014 286.375)",
69
80
  secondary: "oklch(0.2313 0.007 285.839)",
70
81
  "secondary-foreground": "oklch(0.9203 0.0034 286.332)",
82
+ tertiary: "oklch(0.3138 0.0453 249.447)",
83
+ "tertiary-foreground": "oklch(0.8529 0.0324 248.208)",
71
84
  muted: "oklch(0.2313 0.007 285.839)",
72
85
  "muted-foreground": "oklch(0.6255 0.0171 285.896)",
73
86
  accent: "oklch(0.2313 0.007 285.839)",
@@ -75,10 +88,16 @@ var darkMode = {
75
88
  destructive: "oklch(0.6356 0.2082 25.378)",
76
89
  "destructive-foreground": "oklch(1 0 0)",
77
90
  border: "oklch(0.262 0.0085 285.799)",
78
- "border-subtle": "oklch(0.2208 0.0065 285.856)",
79
- "border-strong": "oklch(0.8294 0 0)",
80
91
  input: "oklch(0.262 0.0085 285.799)",
81
- radius: "0.5rem"
92
+ radius: "0.5rem",
93
+ sidebar: "oklch(0.205 0 0)",
94
+ "sidebar-foreground": "oklch(0.9683 0.0014 286.375)",
95
+ "sidebar-primary": "oklch(0.4865 0.2423 291.866)",
96
+ "sidebar-primary-foreground": "oklch(0.9848 0 0)",
97
+ "sidebar-accent": "oklch(0.2313 0.007 285.839)",
98
+ "sidebar-accent-foreground": "oklch(0.9683 0.0014 286.375)",
99
+ "sidebar-border": "oklch(0.262 0.0085 285.799)",
100
+ "sidebar-ring": "oklch(0.4865 0.2423 291.866)"
82
101
  };
83
102
 
84
103
  // src/theme/presets/accents.ts
@@ -88,42 +107,54 @@ var accents = {
88
107
  "primary-foreground": "oklch(0.9848 0 0)",
89
108
  ring: "oklch(0.2228 0.0043 286.044)",
90
109
  accent: "oklch(0.2747 0.006 286.001)",
91
- "accent-foreground": "oklch(0.9848 0 0)"
110
+ "accent-foreground": "oklch(0.9848 0 0)",
111
+ "sidebar-primary": "oklch(0.2228 0.0043 286.044)",
112
+ "sidebar-ring": "oklch(0.2228 0.0043 286.044)"
92
113
  },
93
114
  emerald: {
94
115
  primary: "oklch(0.6902 0.1481 162.368)",
95
116
  "primary-foreground": "oklch(1 0 0)",
96
117
  ring: "oklch(0.6902 0.1481 162.368)",
97
118
  accent: "oklch(0.3519 0.0714 164.26)",
98
- "accent-foreground": "oklch(0.9131 0.0924 171.145)"
119
+ "accent-foreground": "oklch(0.9131 0.0924 171.145)",
120
+ "sidebar-primary": "oklch(0.6902 0.1481 162.368)",
121
+ "sidebar-ring": "oklch(0.6902 0.1481 162.368)"
99
122
  },
100
123
  green: {
101
124
  primary: "oklch(0.7205 0.192 149.493)",
102
125
  "primary-foreground": "oklch(1 0 0)",
103
126
  ring: "oklch(0.7205 0.192 149.493)",
104
127
  accent: "oklch(0.333 0.0811 150.922)",
105
- "accent-foreground": "oklch(0.8958 0.096 156.121)"
128
+ "accent-foreground": "oklch(0.8958 0.096 156.121)",
129
+ "sidebar-primary": "oklch(0.7205 0.192 149.493)",
130
+ "sidebar-ring": "oklch(0.7205 0.192 149.493)"
106
131
  },
107
132
  slate: {
108
133
  primary: "oklch(0.6227 0.0463 256.82)",
109
134
  "primary-foreground": "oklch(1 0 0)",
110
135
  ring: "oklch(0.6227 0.0463 256.82)",
111
136
  accent: "oklch(0.3115 0.0245 256.824)",
112
- "accent-foreground": "oklch(0.8784 0.0141 256.711)"
137
+ "accent-foreground": "oklch(0.8784 0.0141 256.711)",
138
+ "sidebar-primary": "oklch(0.6227 0.0463 256.82)",
139
+ "sidebar-ring": "oklch(0.6227 0.0463 256.82)"
113
140
  },
114
141
  blue: {
115
142
  primary: "oklch(0.6261 0.1859 259.596)",
116
143
  "primary-foreground": "oklch(1 0 0)",
117
144
  ring: "oklch(0.6261 0.1859 259.596)",
118
145
  accent: "oklch(0.2941 0.1092 259.917)",
119
- "accent-foreground": "oklch(0.8064 0.0902 259.76)"
146
+ "accent-foreground": "oklch(0.8064 0.0902 259.76)",
147
+ "sidebar-primary": "oklch(0.6261 0.1859 259.596)",
148
+ "sidebar-ring": "oklch(0.6261 0.1859 259.596)"
120
149
  },
121
150
  violet: {
122
151
  primary: "oklch(0.4865 0.2423 291.866)",
123
152
  "primary-foreground": "oklch(1 0 0)",
124
153
  ring: "oklch(0.6016 0.2214 292.234)",
125
154
  accent: "oklch(0.2467 0.109 294.41)",
126
- "accent-foreground": "oklch(0.7817 0.1036 301.636)"
155
+ "accent-foreground": "oklch(0.7817 0.1036 301.636)",
156
+ "sidebar-primary": "oklch(0.4865 0.2423 291.866)",
157
+ "sidebar-ring": "oklch(0.6016 0.2214 292.234)"
127
158
  }
128
159
  };
129
160
 
@@ -162,7 +193,15 @@ function resolvePreset(preset) {
162
193
  const { mode, accent } = PRESET_MAP[preset];
163
194
  return composePreset(mode, accent);
164
195
  }
165
- var ACCENT_KEYS = /* @__PURE__ */ new Set(["primary", "primary-foreground", "ring", "accent", "accent-foreground"]);
196
+ var ACCENT_KEYS = /* @__PURE__ */ new Set([
197
+ "primary",
198
+ "primary-foreground",
199
+ "ring",
200
+ "accent",
201
+ "accent-foreground",
202
+ "sidebar-primary",
203
+ "sidebar-ring"
204
+ ]);
166
205
  function tokensToStyle(tokens, accentOnly) {
167
206
  const style = {};
168
207
  for (const [key, value] of Object.entries(tokens)) {
@@ -172,50 +211,85 @@ function tokensToStyle(tokens, accentOnly) {
172
211
  }
173
212
  return style;
174
213
  }
214
+ var SHADCN_RADIUS_SCALE = {
215
+ "--radius-xs": "calc(var(--radius) - 4px)",
216
+ "--radius-sm": "calc(var(--radius) - 4px)",
217
+ "--radius-md": "calc(var(--radius) - 2px)",
218
+ "--radius-lg": "var(--radius)",
219
+ "--radius-xl": "calc(var(--radius) + 4px)",
220
+ "--radius-2xl": "calc(var(--radius) + 8px)",
221
+ "--radius-3xl": "calc(var(--radius) + 12px)",
222
+ "--radius-4xl": "calc(var(--radius) + 16px)"
223
+ };
224
+ function radiusToStyle(radius, scale) {
225
+ const style = { "--radius": radius };
226
+ for (const [key, value] of Object.entries(SHADCN_RADIUS_SCALE)) {
227
+ style[key] = scale === "uniform" ? "var(--radius)" : value;
228
+ }
229
+ return style;
230
+ }
175
231
  var NajmThemeDepthContext = React.createContext(0);
176
232
  var NajmThemeContainerCtx = React.createContext(null);
177
- var DEFAULT_APPEARANCE = {
178
- borderDegree: "default"
179
- };
233
+ var DEFAULT_APPEARANCE = {};
180
234
  var NajmAppearanceContext = React.createContext(DEFAULT_APPEARANCE);
181
235
  function useNajmAppearance() {
182
236
  return React.useContext(NajmAppearanceContext);
183
237
  }
184
238
  function NajmThemeProvider({
239
+ config,
185
240
  preset,
186
241
  mode,
187
242
  accent,
188
243
  tokens,
189
244
  accentOnly,
190
245
  appearance,
246
+ radius,
247
+ radiusScale,
248
+ spacing,
191
249
  className,
192
250
  asChild,
193
251
  children
194
252
  }) {
195
253
  const depth = React.useContext(NajmThemeDepthContext);
196
254
  const parentAppearance = React.useContext(NajmAppearanceContext);
197
- const shouldApplyThemeTokens = Boolean(preset || mode || tokens);
255
+ const effectivePreset = preset ?? config?.preset;
256
+ const effectiveMode = mode ?? config?.mode;
257
+ const effectiveAccent = accent ?? config?.accent;
258
+ const effectiveTokens = tokens ?? config?.tokens;
259
+ const effectiveAccentOnly = accentOnly ?? config?.accentOnly;
260
+ const effectiveRadius = radius ?? config?.radius;
261
+ const effectiveRadiusScale = radiusScale ?? config?.radiusScale ?? "shadcn";
262
+ const effectiveSpacing = spacing ?? config?.spacing;
263
+ const effectiveBorderWidth = appearance?.borderWidth ?? config?.appearance?.borderWidth;
264
+ const shouldApplyThemeTokens = Boolean(effectivePreset || effectiveMode || effectiveTokens);
198
265
  const resolved = React.useMemo(() => {
199
266
  if (!shouldApplyThemeTokens) return null;
200
- if (tokens) return tokens;
201
- if (preset) return resolvePreset(preset);
202
- return composePreset(mode, accent ?? "neutral");
203
- }, [preset, mode, accent, tokens, shouldApplyThemeTokens]);
267
+ if (effectiveTokens) return effectiveTokens;
268
+ if (effectivePreset) return resolvePreset(effectivePreset);
269
+ return composePreset(effectiveMode, effectiveAccent ?? "neutral");
270
+ }, [effectivePreset, effectiveMode, effectiveAccent, effectiveTokens, shouldApplyThemeTokens]);
204
271
  const style = React.useMemo(
205
- () => resolved ? tokensToStyle(resolved, accentOnly) : void 0,
206
- [resolved, accentOnly]
272
+ () => {
273
+ const tokenStyle = resolved ? tokensToStyle(resolved, effectiveAccentOnly) : void 0;
274
+ const radiusStyle = effectiveRadius !== void 0 ? radiusToStyle(effectiveRadius, effectiveRadiusScale) : void 0;
275
+ const borderWidthStyle = effectiveBorderWidth !== void 0 ? { "--border-width": effectiveBorderWidth } : void 0;
276
+ const spacingStyle = effectiveSpacing !== void 0 ? { "--spacing": effectiveSpacing } : void 0;
277
+ if (!tokenStyle && !radiusStyle && !borderWidthStyle && !spacingStyle) return void 0;
278
+ return { ...tokenStyle, ...radiusStyle, ...borderWidthStyle, ...spacingStyle };
279
+ },
280
+ [resolved, effectiveAccentOnly, effectiveRadius, effectiveRadiusScale, effectiveSpacing, effectiveBorderWidth]
207
281
  );
208
282
  const Comp = asChild ? Slot : "div";
209
283
  const [container, setContainer] = React.useState(null);
210
284
  const resolvedAppearance = React.useMemo(
211
- () => ({ ...parentAppearance, ...appearance ?? {} }),
212
- [parentAppearance, appearance]
285
+ () => ({ ...parentAppearance, ...config?.appearance ?? {}, ...appearance ?? {} }),
286
+ [parentAppearance, config?.appearance, appearance]
213
287
  );
214
288
  return /* @__PURE__ */ jsx(NajmThemeDepthContext.Provider, { value: depth + 1, children: /* @__PURE__ */ jsx(NajmAppearanceContext.Provider, { value: resolvedAppearance, children: /* @__PURE__ */ jsx(NajmThemeContainerCtx.Provider, { value: container, children: /* @__PURE__ */ jsx(
215
289
  Comp,
216
290
  {
217
291
  ref: setContainer,
218
- "data-najm-theme": preset ?? `${mode ?? "light"}-${accent ?? "neutral"}`,
292
+ "data-najm-theme": effectivePreset ?? `${effectiveMode ?? "light"}-${effectiveAccent ?? "neutral"}`,
219
293
  className,
220
294
  style,
221
295
  children
@@ -223,49 +297,473 @@ function NajmThemeProvider({
223
297
  ) }) }) });
224
298
  }
225
299
 
226
- // src/theme/borders.ts
227
- function resolveBorderDegree(borderDegree, bordered, globalBorderDegree, fallback = "default") {
228
- if (borderDegree) return borderDegree;
229
- if (bordered === true) return "strong";
230
- if (bordered === false) return fallback;
231
- return globalBorderDegree ?? fallback;
232
- }
233
- function borderColorClassForDegree(degree) {
234
- switch (degree) {
235
- case "none":
236
- return "border-transparent";
237
- case "subtle":
238
- return "border-border-subtle";
239
- case "strong":
240
- return "border-border-strong";
241
- default:
242
- return "border-border";
300
+ // src/theme/config.ts
301
+ var MODES = ["light", "dark"];
302
+ var ACCENTS = ["neutral", "emerald", "green", "slate", "blue", "violet"];
303
+ var PRESETS = ["light", "dark", "dark-emerald", "dark-green", "dark-slate", "dark-blue", "dark-violet"];
304
+ var RADIUS_SCALES = ["shadcn", "uniform"];
305
+ var TOKEN_KEYS = [
306
+ "background",
307
+ "foreground",
308
+ "card",
309
+ "card-foreground",
310
+ "popover",
311
+ "popover-foreground",
312
+ "primary",
313
+ "primary-foreground",
314
+ "secondary",
315
+ "secondary-foreground",
316
+ "tertiary",
317
+ "tertiary-foreground",
318
+ "muted",
319
+ "muted-foreground",
320
+ "accent",
321
+ "accent-foreground",
322
+ "destructive",
323
+ "destructive-foreground",
324
+ "border",
325
+ "input",
326
+ "ring",
327
+ "sidebar",
328
+ "sidebar-foreground",
329
+ "sidebar-primary",
330
+ "sidebar-primary-foreground",
331
+ "sidebar-accent",
332
+ "sidebar-accent-foreground",
333
+ "sidebar-border",
334
+ "sidebar-ring",
335
+ "chart-1",
336
+ "chart-2",
337
+ "chart-3",
338
+ "chart-4",
339
+ "chart-5",
340
+ "radius"
341
+ ];
342
+ var ROOT_KEYS = /* @__PURE__ */ new Set([
343
+ "preset",
344
+ "mode",
345
+ "accent",
346
+ "tokens",
347
+ "accentOnly",
348
+ "appearance",
349
+ "radius",
350
+ "radiusScale"
351
+ ]);
352
+ var TOKEN_KEY_SET = new Set(TOKEN_KEYS);
353
+ function isRecord(value) {
354
+ return typeof value === "object" && value !== null && !Array.isArray(value);
355
+ }
356
+ function assertKnownKeys(value, keys, path) {
357
+ const unknown = Object.keys(value).find((key) => !keys.has(key));
358
+ if (unknown) throw new TypeError(`Unknown ${path} property: ${unknown}`);
359
+ }
360
+ function optionalEnum(value, values, path) {
361
+ if (value === void 0) return void 0;
362
+ if (typeof value !== "string" || !values.includes(value)) {
363
+ throw new TypeError(`${path} must be one of: ${values.join(", ")}`);
364
+ }
365
+ return value;
366
+ }
367
+ function optionalString(value, path) {
368
+ if (value === void 0) return void 0;
369
+ if (typeof value !== "string" || value.trim() === "") {
370
+ throw new TypeError(`${path} must be a non-empty string`);
243
371
  }
372
+ return value;
373
+ }
374
+ function parseTokens(value) {
375
+ if (value === void 0) return void 0;
376
+ if (!isRecord(value)) throw new TypeError("theme.tokens must be an object");
377
+ assertKnownKeys(value, TOKEN_KEY_SET, "theme.tokens");
378
+ const tokens = {};
379
+ for (const key of TOKEN_KEYS) {
380
+ const token = optionalString(value[key], `theme.tokens.${key}`);
381
+ if (token !== void 0) tokens[key] = token;
382
+ }
383
+ return tokens;
384
+ }
385
+ function defineNajmThemeConfig(config) {
386
+ return config;
244
387
  }
245
- function inputBorderColorClassForDegree(degree) {
246
- switch (degree) {
247
- case "none":
248
- return "border-transparent";
249
- case "subtle":
250
- return "border-border-subtle";
251
- case "strong":
252
- return "border-border-strong";
253
- default:
254
- return "border-input";
388
+ function parseNajmThemeConfig(input) {
389
+ let value = input;
390
+ if (typeof input === "string") {
391
+ try {
392
+ value = JSON.parse(input);
393
+ } catch (error) {
394
+ throw new TypeError(`Invalid theme JSON: ${error.message}`);
395
+ }
255
396
  }
397
+ if (!isRecord(value)) throw new TypeError("Theme config must be an object");
398
+ assertKnownKeys(value, ROOT_KEYS, "theme");
399
+ let appearance;
400
+ if (value.appearance !== void 0) {
401
+ if (!isRecord(value.appearance)) throw new TypeError("theme.appearance must be an object");
402
+ assertKnownKeys(value.appearance, /* @__PURE__ */ new Set(["borderWidth"]), "theme.appearance");
403
+ appearance = {
404
+ borderWidth: optionalString(
405
+ value.appearance.borderWidth,
406
+ "theme.appearance.borderWidth"
407
+ )
408
+ };
409
+ }
410
+ const accentOnly = value.accentOnly;
411
+ if (accentOnly !== void 0 && typeof accentOnly !== "boolean") {
412
+ throw new TypeError("theme.accentOnly must be a boolean");
413
+ }
414
+ const parsedAccentOnly = typeof accentOnly === "boolean" ? accentOnly : void 0;
415
+ const config = {};
416
+ const preset = optionalEnum(value.preset, PRESETS, "theme.preset");
417
+ const mode = optionalEnum(value.mode, MODES, "theme.mode");
418
+ const accent = optionalEnum(value.accent, ACCENTS, "theme.accent");
419
+ const tokens = parseTokens(value.tokens);
420
+ const radius = optionalString(value.radius, "theme.radius");
421
+ const radiusScale = optionalEnum(value.radiusScale, RADIUS_SCALES, "theme.radiusScale");
422
+ if (preset !== void 0) config.preset = preset;
423
+ if (mode !== void 0) config.mode = mode;
424
+ if (accent !== void 0) config.accent = accent;
425
+ if (tokens !== void 0) config.tokens = tokens;
426
+ if (parsedAccentOnly !== void 0) config.accentOnly = parsedAccentOnly;
427
+ if (appearance !== void 0) config.appearance = appearance;
428
+ if (radius !== void 0) config.radius = radius;
429
+ if (radiusScale !== void 0) config.radiusScale = radiusScale;
430
+ return config;
431
+ }
432
+ function stringifyNajmThemeConfig(config, space = 2) {
433
+ return JSON.stringify(config, null, space);
434
+ }
435
+ var NajmDesignContext = React.createContext({
436
+ components: {}
437
+ });
438
+ function useNajmDesign() {
439
+ return React.useContext(NajmDesignContext);
440
+ }
441
+ function useNajmComponentStyle(name) {
442
+ const { components } = useNajmDesign();
443
+ return components[name];
444
+ }
445
+ var SCALE_FACTOR = {
446
+ compact: "0.95",
447
+ default: "1",
448
+ comfortable: "1.05"
449
+ };
450
+ function typographyToStyle(t) {
451
+ const style = {};
452
+ if (t.fontSans) style["--font-sans"] = t.fontSans;
453
+ if (t.fontHeading) style["--font-heading"] = t.fontHeading;
454
+ if (t.fontMono) style["--font-mono"] = t.fontMono;
455
+ if (t.baseSize) style["--font-size-base"] = t.baseSize;
456
+ if (t.lineHeight) style["--line-height-base"] = t.lineHeight;
457
+ if (t.letterSpacing) style["--letter-spacing-base"] = t.letterSpacing;
458
+ if (t.scale) style["--font-scale"] = SCALE_FACTOR[t.scale];
459
+ return style;
256
460
  }
257
- function useResolvedBorderDegree(options = {}) {
258
- const appearance = useNajmAppearance();
259
- return resolveBorderDegree(
260
- options.borderDegree,
261
- options.bordered,
262
- appearance.borderDegree,
263
- options.fallback
461
+ function layoutToStyle(layout) {
462
+ const style = {};
463
+ if (layout.pageGutter) style["--page-gutter"] = layout.pageGutter;
464
+ if (layout.sectionGap) style["--section-gap"] = layout.sectionGap;
465
+ return style;
466
+ }
467
+ function NajmDesignProvider({
468
+ config,
469
+ className,
470
+ children
471
+ }) {
472
+ const contextValue = React.useMemo(
473
+ () => ({ components: config.components ?? {}, typography: config.typography, layout: config.layout }),
474
+ [config.components, config.typography, config.layout]
475
+ );
476
+ const typographyStyle = React.useMemo(
477
+ () => config.typography ? typographyToStyle(config.typography) : void 0,
478
+ [config.typography]
479
+ );
480
+ const layoutStyle = React.useMemo(
481
+ () => config.layout ? layoutToStyle(config.layout) : void 0,
482
+ [config.layout]
264
483
  );
484
+ const providerStyle = React.useMemo(
485
+ () => ({ ...layoutStyle ?? {}, ...typographyStyle ?? {} }),
486
+ [layoutStyle, typographyStyle]
487
+ );
488
+ return /* @__PURE__ */ jsx(NajmDesignContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(NajmThemeProvider, { config: config.theme, className, children: layoutStyle || typographyStyle ? (
489
+ // `display: contents` lets design CSS variables cascade to
490
+ // children without introducing a layout box that would break height
491
+ // chains (e.g. h-full) in the consuming app.
492
+ /* @__PURE__ */ jsx("div", { style: { display: "contents", ...providerStyle }, "data-najm-design-vars": "", children })
493
+ ) : children }) });
494
+ }
495
+
496
+ // src/theme/design-types.ts
497
+ var NAJM_COMPONENT_NAMES = [
498
+ "button",
499
+ "badge",
500
+ "card",
501
+ "table",
502
+ "tabs",
503
+ "dialog",
504
+ "alert",
505
+ "sidebar",
506
+ "pageHeader",
507
+ "input",
508
+ "select",
509
+ "sheet",
510
+ "popover",
511
+ "tooltip",
512
+ "progress",
513
+ "avatar"
514
+ ];
515
+ var RADIUS_VALUE_MAP = {
516
+ none: "0",
517
+ xs: "var(--radius-xs)",
518
+ sm: "var(--radius-sm)",
519
+ md: "var(--radius-md)",
520
+ lg: "var(--radius-lg)",
521
+ xl: "var(--radius-xl)",
522
+ full: "9999px"
523
+ };
524
+ function resolveRadiusValue(radius) {
525
+ if (!radius || radius === "inherit") return void 0;
526
+ return RADIUS_VALUE_MAP[radius] ?? radius;
527
+ }
528
+
529
+ // src/theme/design-config.ts
530
+ var ROOT_KEYS2 = /* @__PURE__ */ new Set(["version", "theme", "typography", "components", "layout"]);
531
+ var TYPOGRAPHY_KEYS = /* @__PURE__ */ new Set([
532
+ "fontSans",
533
+ "fontHeading",
534
+ "fontMono",
535
+ "baseSize",
536
+ "scale",
537
+ "lineHeight",
538
+ "letterSpacing"
539
+ ]);
540
+ var LAYOUT_KEYS = /* @__PURE__ */ new Set(["pageGutter", "sectionGap"]);
541
+ var COMPONENT_KEYS = /* @__PURE__ */ new Set([
542
+ "card",
543
+ "showSectionLabels",
544
+ "showSectionSeparators",
545
+ "defaultVariant",
546
+ "defaultSize",
547
+ "density",
548
+ "radius",
549
+ "borderWidth",
550
+ "slots",
551
+ "variants"
552
+ ]);
553
+ var SLOT_KEYS = /* @__PURE__ */ new Set(["className", "radius", "borderWidth", "padding", "paddingTop"]);
554
+ var VARIANT_KEYS = /* @__PURE__ */ new Set(["use", "className", "tokens"]);
555
+ var COMPONENT_NAME_SET = new Set(NAJM_COMPONENT_NAMES);
556
+ var DENSITIES = /* @__PURE__ */ new Set(["compact", "default", "comfortable"]);
557
+ var SCALES = /* @__PURE__ */ new Set(["compact", "default", "comfortable"]);
558
+ function isRecord2(value) {
559
+ return typeof value === "object" && value !== null && !Array.isArray(value);
560
+ }
561
+ function assertKnownKeys2(value, keys, path) {
562
+ const unknown = Object.keys(value).find((key) => !keys.has(key));
563
+ if (unknown) throw new TypeError(`Unknown ${path} property: ${unknown}`);
564
+ }
565
+ function optionalString2(value, path) {
566
+ if (value === void 0) return void 0;
567
+ if (typeof value !== "string") {
568
+ throw new TypeError(`${path} must be a string`);
569
+ }
570
+ return value;
571
+ }
572
+ function optionalBoolean(value, path) {
573
+ if (value === void 0) return void 0;
574
+ if (typeof value !== "boolean") {
575
+ throw new TypeError(`${path} must be a boolean`);
576
+ }
577
+ return value;
578
+ }
579
+ function optionalEnum2(value, values, path) {
580
+ if (value === void 0) return void 0;
581
+ if (typeof value !== "string" || !values.has(value)) {
582
+ throw new TypeError(`${path} must be one of: ${[...values].join(", ")}`);
583
+ }
584
+ return value;
585
+ }
586
+ function parseTypography(value) {
587
+ if (value === void 0) return void 0;
588
+ if (!isRecord2(value)) throw new TypeError("typography must be an object");
589
+ assertKnownKeys2(value, TYPOGRAPHY_KEYS, "typography");
590
+ const cfg = {};
591
+ const fontSans = optionalString2(value.fontSans, "typography.fontSans");
592
+ const fontHeading = optionalString2(value.fontHeading, "typography.fontHeading");
593
+ const fontMono = optionalString2(value.fontMono, "typography.fontMono");
594
+ const baseSize = optionalString2(value.baseSize, "typography.baseSize");
595
+ const scale = optionalEnum2(value.scale, SCALES, "typography.scale");
596
+ const lineHeight = optionalString2(value.lineHeight, "typography.lineHeight");
597
+ const letterSpacing = optionalString2(value.letterSpacing, "typography.letterSpacing");
598
+ if (fontSans !== void 0) cfg.fontSans = fontSans;
599
+ if (fontHeading !== void 0) cfg.fontHeading = fontHeading;
600
+ if (fontMono !== void 0) cfg.fontMono = fontMono;
601
+ if (baseSize !== void 0) cfg.baseSize = baseSize;
602
+ if (scale !== void 0) cfg.scale = scale;
603
+ if (lineHeight !== void 0) cfg.lineHeight = lineHeight;
604
+ if (letterSpacing !== void 0) cfg.letterSpacing = letterSpacing;
605
+ return cfg;
606
+ }
607
+ function parseLayout(value) {
608
+ if (value === void 0) return void 0;
609
+ if (!isRecord2(value)) throw new TypeError("layout must be an object");
610
+ assertKnownKeys2(value, LAYOUT_KEYS, "layout");
611
+ const cfg = {};
612
+ const pageGutter = optionalString2(value.pageGutter, "layout.pageGutter");
613
+ const sectionGap = optionalString2(value.sectionGap, "layout.sectionGap");
614
+ if (pageGutter !== void 0) cfg.pageGutter = pageGutter;
615
+ if (sectionGap !== void 0) cfg.sectionGap = sectionGap;
616
+ return cfg;
617
+ }
618
+ function parseVariant(value, path) {
619
+ if (!isRecord2(value)) throw new TypeError(`${path} must be an object`);
620
+ assertKnownKeys2(value, VARIANT_KEYS, path);
621
+ const variant = {};
622
+ const use = optionalString2(value.use, `${path}.use`);
623
+ const className = optionalString2(value.className, `${path}.className`);
624
+ if (use !== void 0) variant.use = use;
625
+ if (className !== void 0) variant.className = className;
626
+ if (value.tokens !== void 0) {
627
+ if (!isRecord2(value.tokens)) throw new TypeError(`${path}.tokens must be an object`);
628
+ variant.tokens = value.tokens;
629
+ }
630
+ return variant;
631
+ }
632
+ function parseComponentStyle(value, path) {
633
+ if (!isRecord2(value)) throw new TypeError(`${path} must be an object`);
634
+ assertKnownKeys2(value, COMPONENT_KEYS, path);
635
+ const cfg = {};
636
+ const card = optionalBoolean(value.card, `${path}.card`);
637
+ const showSectionLabels = optionalBoolean(value.showSectionLabels, `${path}.showSectionLabels`);
638
+ const showSectionSeparators = optionalBoolean(value.showSectionSeparators, `${path}.showSectionSeparators`);
639
+ const defaultVariant = optionalString2(value.defaultVariant, `${path}.defaultVariant`);
640
+ const defaultSize = optionalString2(value.defaultSize, `${path}.defaultSize`);
641
+ const density = optionalEnum2(value.density, DENSITIES, `${path}.density`);
642
+ const radius = optionalString2(value.radius, `${path}.radius`);
643
+ const borderWidth = optionalString2(value.borderWidth, `${path}.borderWidth`);
644
+ if (card !== void 0) cfg.card = card;
645
+ if (showSectionLabels !== void 0) cfg.showSectionLabels = showSectionLabels;
646
+ if (showSectionSeparators !== void 0) cfg.showSectionSeparators = showSectionSeparators;
647
+ if (defaultVariant !== void 0) cfg.defaultVariant = defaultVariant;
648
+ if (defaultSize !== void 0) cfg.defaultSize = defaultSize;
649
+ if (density !== void 0) cfg.density = density;
650
+ if (radius !== void 0) cfg.radius = radius;
651
+ if (borderWidth !== void 0) cfg.borderWidth = borderWidth;
652
+ if (value.slots !== void 0) {
653
+ if (!isRecord2(value.slots)) throw new TypeError(`${path}.slots must be an object`);
654
+ const slots = {};
655
+ for (const [slotName, slotValue] of Object.entries(value.slots)) {
656
+ if (!isRecord2(slotValue)) throw new TypeError(`${path}.slots.${slotName} must be an object`);
657
+ assertKnownKeys2(slotValue, SLOT_KEYS, `${path}.slots.${slotName}`);
658
+ slots[slotName] = slotValue;
659
+ }
660
+ cfg.slots = slots;
661
+ }
662
+ if (value.variants !== void 0) {
663
+ if (!isRecord2(value.variants)) throw new TypeError(`${path}.variants must be an object`);
664
+ const variants = {};
665
+ for (const [variantName, variantValue] of Object.entries(value.variants)) {
666
+ variants[variantName] = parseVariant(variantValue, `${path}.variants.${variantName}`);
667
+ }
668
+ cfg.variants = variants;
669
+ }
670
+ return cfg;
671
+ }
672
+ function parseComponents(value) {
673
+ if (value === void 0) return void 0;
674
+ if (!isRecord2(value)) throw new TypeError("components must be an object");
675
+ const unknown = Object.keys(value).find((key) => !COMPONENT_NAME_SET.has(key));
676
+ if (unknown) throw new TypeError(`Unknown component name: ${unknown}`);
677
+ const components = {};
678
+ for (const [name, cfg] of Object.entries(value)) {
679
+ components[name] = parseComponentStyle(cfg, `components.${name}`);
680
+ }
681
+ return components;
682
+ }
683
+ function defineNajmDesignConfig(config) {
684
+ return config;
685
+ }
686
+ function parseNajmDesignConfig(input) {
687
+ let value = input;
688
+ if (typeof input === "string") {
689
+ try {
690
+ value = JSON.parse(input);
691
+ } catch (error) {
692
+ throw new TypeError(`Invalid design JSON: ${error.message}`);
693
+ }
694
+ }
695
+ if (!isRecord2(value)) throw new TypeError("Design config must be an object");
696
+ if (!("version" in value) && !("theme" in value)) {
697
+ return {
698
+ version: 1,
699
+ theme: parseNajmThemeConfig(value)
700
+ };
701
+ }
702
+ assertKnownKeys2(value, ROOT_KEYS2, "design");
703
+ if (value.version !== void 0 && value.version !== 1) {
704
+ throw new TypeError("design.version must be 1");
705
+ }
706
+ if (value.theme === void 0) throw new TypeError("design.theme is required");
707
+ const config = {
708
+ version: 1,
709
+ theme: parseNajmThemeConfig(value.theme)
710
+ };
711
+ const typography = parseTypography(value.typography);
712
+ if (typography !== void 0) config.typography = typography;
713
+ const components = parseComponents(value.components);
714
+ if (components !== void 0) config.components = components;
715
+ const layout = parseLayout(value.layout);
716
+ if (layout !== void 0) config.layout = layout;
717
+ return config;
718
+ }
719
+ function stringifyNajmDesignConfig(config, space = 2) {
720
+ return JSON.stringify(config, null, space);
721
+ }
722
+ function resolveVariantAlias(variants, variant) {
723
+ if (!variants) return { variant };
724
+ const seen = /* @__PURE__ */ new Set();
725
+ let current = variant;
726
+ let style = variants[current];
727
+ while (style?.use && !seen.has(current)) {
728
+ seen.add(current);
729
+ const next = style.use;
730
+ if (seen.has(next)) break;
731
+ current = next;
732
+ style = variants[current];
733
+ }
734
+ return { variant: current, style };
735
+ }
736
+
737
+ // src/theme/borders.ts
738
+ var SURFACE_BORDER_CLASSES = {
739
+ all: "najm-border border-border",
740
+ top: "najm-border-t border-border",
741
+ right: "najm-border-r border-border",
742
+ bottom: "najm-border-b border-border",
743
+ left: "najm-border-l border-border"
744
+ };
745
+ var SIDEBAR_BORDER_CLASSES = {
746
+ all: "najm-border border-sidebar-border",
747
+ top: "najm-border-t border-sidebar-border",
748
+ right: "najm-border-r border-sidebar-border",
749
+ bottom: "najm-border-b border-sidebar-border",
750
+ left: "najm-border-l border-sidebar-border"
751
+ };
752
+ var BORDER_RESET_CLASSES = {
753
+ all: "border-0",
754
+ top: "border-t-0",
755
+ right: "border-r-0",
756
+ bottom: "border-b-0",
757
+ left: "border-l-0"
758
+ };
759
+ function surfaceBorderClasses(bordered = true, side = "all") {
760
+ return bordered === false ? BORDER_RESET_CLASSES[side] : SURFACE_BORDER_CLASSES[side];
265
761
  }
266
- function surfaceBorderClasses(degree) {
267
- if (degree === "none") return "border border-transparent";
268
- return `border ${borderColorClassForDegree(degree)}`;
762
+ function sidebarBorderClasses(bordered = true, side = "all") {
763
+ return bordered === false ? BORDER_RESET_CLASSES[side] : SIDEBAR_BORDER_CLASSES[side];
764
+ }
765
+ function inputBorderClasses(bordered = true) {
766
+ return bordered === false ? "border-0" : "najm-border border-input";
269
767
  }
270
768
  var EDITABLE_INPUT_TYPES = /* @__PURE__ */ new Set([
271
769
  "text",
@@ -600,21 +1098,25 @@ var Button = React.forwardRef(
600
1098
  leftIcon,
601
1099
  rightIcon,
602
1100
  bordered,
603
- borderDegree,
604
1101
  disabled,
605
1102
  children,
606
1103
  onClick,
1104
+ style,
607
1105
  ...props
608
1106
  }, ref) => {
1107
+ const recipe = useNajmComponentStyle("button");
1108
+ const aliased = resolveVariantAlias(
1109
+ recipe?.variants,
1110
+ variant ?? recipe?.defaultVariant ?? "default"
1111
+ );
1112
+ const effVariant = variant ?? aliased.variant ?? recipe?.defaultVariant;
1113
+ const effSize = size ?? recipe?.defaultSize;
1114
+ const recipeRadius = rounded === void 0 ? resolveRadiusValue(recipe?.radius) : void 0;
1115
+ const recipeStyle = recipeRadius ? { borderRadius: recipeRadius } : void 0;
609
1116
  const [pending, setPending] = React.useState(false);
610
1117
  const isLoading = loading || pending;
611
1118
  const isDisabled = disabled || disabledWhileLoading && isLoading;
612
1119
  const Comp = asChild ? Slot : "button";
613
- const resolvedBorderDegree = useResolvedBorderDegree({
614
- borderDegree,
615
- bordered,
616
- fallback: "default"
617
- });
618
1120
  const handleClick = React.useCallback(
619
1121
  (event) => {
620
1122
  if (isDisabled) {
@@ -644,21 +1146,22 @@ var Button = React.forwardRef(
644
1146
  "data-slot": "button",
645
1147
  "data-loading": isLoading || void 0,
646
1148
  "data-disabled": isDisabled || void 0,
647
- "data-border-degree": variant === "outline" || bordered || borderDegree ? resolvedBorderDegree : void 0,
1149
+ "data-bordered": effVariant === "outline" ? "true" : bordered === false ? "false" : bordered ? "true" : void 0,
648
1150
  "aria-busy": isLoading || void 0,
649
1151
  "aria-disabled": asChild && isDisabled ? true : void 0,
650
1152
  disabled: !asChild ? isDisabled : void 0,
1153
+ style: recipeStyle ? { ...recipeStyle, ...style } : style,
651
1154
  className: cn(
652
- buttonVariants({ variant, size, rounded, fullWidth }),
653
- // Outline buttons always have a border; let the resolved degree drive its color.
654
- variant === "outline" && borderColorClassForDegree(resolvedBorderDegree),
1155
+ buttonVariants({ variant: effVariant, size: effSize, rounded, fullWidth }),
1156
+ aliased.style?.className,
1157
+ // Outline buttons always carry an input-style border.
1158
+ effVariant === "outline" && inputBorderClasses(true),
655
1159
  // Filled/ghost/plain/link/success/warning/info/soft/subtle buttons only get a
656
- // border when the consumer explicitly opts in via `bordered` or `borderDegree`.
657
- // We do NOT honor the global strong mode for these, because it would make every
658
- // filled button look outlined.
659
- variant !== "outline" && (bordered || borderDegree) && cn(
1160
+ // border when the consumer explicitly opts in via `bordered`. Global theming
1161
+ // should not outline every filled button.
1162
+ effVariant !== "outline" && bordered === true && cn(
660
1163
  "border",
661
- borderDegree ? borderColorClassForDegree(resolvedBorderDegree) : "border-muted-foreground"
1164
+ "border-muted-foreground"
662
1165
  ),
663
1166
  className
664
1167
  ),
@@ -791,9 +1294,18 @@ function Badge({
791
1294
  iconPosition = "left",
792
1295
  asChild = false,
793
1296
  children,
1297
+ style,
794
1298
  ...props
795
1299
  }) {
796
1300
  const Comp = asChild ? Slot : "span";
1301
+ const recipe = useNajmComponentStyle("badge");
1302
+ const aliased = resolveVariantAlias(
1303
+ recipe?.variants,
1304
+ variant ?? recipe?.defaultVariant ?? "default"
1305
+ );
1306
+ const effVariant = variant ?? aliased.variant ?? recipe?.defaultVariant;
1307
+ const recipeRadius = shape === void 0 ? resolveRadiusValue(recipe?.radius) : void 0;
1308
+ const recipeStyle = recipeRadius ? { borderRadius: recipeRadius, ...style } : style;
797
1309
  const resolvedColor = statusMap?.[status ?? ""] ?? color;
798
1310
  const resolvedLabel = label ?? (typeof children === "string" ? children : void 0) ?? status;
799
1311
  const content = typeof children !== "string" && children ? children : resolvedLabel ?? children;
@@ -814,6 +1326,7 @@ function Badge({
814
1326
  sizeClass,
815
1327
  className
816
1328
  ),
1329
+ style: recipeStyle,
817
1330
  ...props,
818
1331
  children: [
819
1332
  iconPosition === "left" && iconNode,
@@ -823,8 +1336,8 @@ function Badge({
823
1336
  }
824
1337
  );
825
1338
  }
826
- const classes = resolvedColor ? badgeColorVariants({ color: resolvedColor, look, size, shape }) : badgeVariants({ variant });
827
- return /* @__PURE__ */ jsxs(Comp, { "data-slot": "badge", className: cn(classes, className), ...props, children: [
1339
+ const classes = resolvedColor ? badgeColorVariants({ color: resolvedColor, look, size, shape }) : badgeVariants({ variant: effVariant });
1340
+ return /* @__PURE__ */ jsxs(Comp, { "data-slot": "badge", className: cn(classes, aliased.style?.className, className), style: recipeStyle, ...props, children: [
828
1341
  iconPosition === "left" && iconNode,
829
1342
  content,
830
1343
  iconPosition === "right" && iconNode
@@ -1136,14 +1649,13 @@ var sheetVariants = cva(
1136
1649
  }
1137
1650
  );
1138
1651
  function SheetContent({ className, portalClassName, side, children, ...props }) {
1139
- const resolvedBorderDegree = useResolvedBorderDegree();
1140
1652
  return /* @__PURE__ */ jsx(SheetPortal, { children: /* @__PURE__ */ jsxs("div", { className: portalClassName, children: [
1141
1653
  /* @__PURE__ */ jsx(SheetOverlay, {}),
1142
1654
  /* @__PURE__ */ jsxs(
1143
1655
  SheetPrimitive.Content,
1144
1656
  {
1145
1657
  "data-slot": "sheet-content",
1146
- className: cn(sheetVariants({ side }), borderColorClassForDegree(resolvedBorderDegree), className),
1658
+ className: cn(sheetVariants({ side }), className),
1147
1659
  ...props,
1148
1660
  children: [
1149
1661
  children,
@@ -1297,7 +1809,6 @@ function DialogOverlay({ className, ...props }) {
1297
1809
  }
1298
1810
  function DialogContent({ className, children, ...props }) {
1299
1811
  const portalClassName = useNPortalScope();
1300
- const resolvedBorderDegree = useResolvedBorderDegree();
1301
1812
  return /* @__PURE__ */ jsx(DialogPortal, { "data-slot": "dialog-portal", children: /* @__PURE__ */ jsxs("div", { className: portalClassName, children: [
1302
1813
  /* @__PURE__ */ jsx(DialogOverlay, {}),
1303
1814
  /* @__PURE__ */ jsxs(
@@ -1305,8 +1816,7 @@ function DialogContent({ className, children, ...props }) {
1305
1816
  {
1306
1817
  "data-slot": "dialog-content",
1307
1818
  className: cn(
1308
- "bg-card data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-sm translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border border-border p-6 shadow-lg duration-200",
1309
- borderColorClassForDegree(resolvedBorderDegree),
1819
+ "bg-card text-card-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-sm translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg najm-border border-border p-6 shadow-lg duration-200",
1310
1820
  className
1311
1821
  ),
1312
1822
  ...props,
@@ -2199,7 +2709,6 @@ function DropdownMenuSubContent({ className, ...props }) {
2199
2709
  }
2200
2710
  function DropdownMenuContent({ className, sideOffset = 4, ...props }) {
2201
2711
  const container = React.useContext(NajmThemeContainerCtx);
2202
- const resolvedBorderDegree = useResolvedBorderDegree();
2203
2712
  useNajmPortalLayerStyles();
2204
2713
  return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { container: container ?? void 0, children: /* @__PURE__ */ jsx(
2205
2714
  DropdownMenuPrimitive.Content,
@@ -2208,7 +2717,6 @@ function DropdownMenuContent({ className, sideOffset = 4, ...props }) {
2208
2717
  sideOffset,
2209
2718
  className: cn(
2210
2719
  "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-[10000] min-w-[8rem] overflow-hidden rounded-md border border-border p-1 shadow-md",
2211
- borderColorClassForDegree(resolvedBorderDegree),
2212
2720
  className
2213
2721
  ),
2214
2722
  ...props
@@ -2279,7 +2787,6 @@ function PopoverAnchor({ ...props }) {
2279
2787
  }
2280
2788
  function PopoverContent({ className, align = "center", sideOffset = 4, ...props }) {
2281
2789
  const container = React.useContext(NajmThemeContainerCtx);
2282
- const resolvedBorderDegree = useResolvedBorderDegree();
2283
2790
  useNajmPortalLayerStyles();
2284
2791
  return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { container: container ?? void 0, children: /* @__PURE__ */ jsx(
2285
2792
  PopoverPrimitive.Content,
@@ -2289,7 +2796,6 @@ function PopoverContent({ className, align = "center", sideOffset = 4, ...props
2289
2796
  sideOffset,
2290
2797
  className: cn(
2291
2798
  "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-[10000] w-72 origin-(--radix-popover-content-transform-origin) rounded-md border border-border p-4 shadow-md outline-none",
2292
- borderColorClassForDegree(resolvedBorderDegree),
2293
2799
  className
2294
2800
  ),
2295
2801
  ...props
@@ -2989,7 +3495,7 @@ function Avatar({
2989
3495
  children: [
2990
3496
  hasChildren ? children : hasShortcut ? /* @__PURE__ */ jsxs(Fragment, { children: [
2991
3497
  src && /* @__PURE__ */ jsx(
2992
- "img",
3498
+ AvatarPrimitive.Image,
2993
3499
  {
2994
3500
  "data-slot": "avatar-image",
2995
3501
  src,
@@ -2998,7 +3504,7 @@ function Avatar({
2998
3504
  }
2999
3505
  ),
3000
3506
  /* @__PURE__ */ jsx(
3001
- "span",
3507
+ AvatarPrimitive.Fallback,
3002
3508
  {
3003
3509
  "data-slot": "avatar-fallback",
3004
3510
  className: cn(fallbackVariants({ size, shape }), fallbackClassName),
@@ -3023,7 +3529,7 @@ function Avatar({
3023
3529
  }
3024
3530
  function AvatarImage({ className, ...props }) {
3025
3531
  return /* @__PURE__ */ jsx(
3026
- "img",
3532
+ AvatarPrimitive.Image,
3027
3533
  {
3028
3534
  "data-slot": "avatar-image",
3029
3535
  className: cn("aspect-square size-full", className),
@@ -3033,11 +3539,10 @@ function AvatarImage({ className, ...props }) {
3033
3539
  }
3034
3540
  function AvatarFallback({
3035
3541
  className,
3036
- delayMs: _delayMs,
3037
3542
  ...props
3038
3543
  }) {
3039
3544
  return /* @__PURE__ */ jsx(
3040
- "span",
3545
+ AvatarPrimitive.Fallback,
3041
3546
  {
3042
3547
  "data-slot": "avatar-fallback",
3043
3548
  className: cn("flex size-full items-center justify-center rounded-full bg-muted", className),
@@ -3878,7 +4383,7 @@ function NAvatar({
3878
4383
  {
3879
4384
  src: imageSrc,
3880
4385
  alt: alt || label,
3881
- className: cn("absolute inset-0 z-10 object-cover", classNames?.image)
4386
+ className: cn("object-cover", classNames?.image)
3882
4387
  }
3883
4388
  ),
3884
4389
  /* @__PURE__ */ jsx(
@@ -3936,18 +4441,18 @@ function NCard({
3936
4441
  noPadding = false,
3937
4442
  separator = false,
3938
4443
  bordered,
3939
- borderDegree,
3940
4444
  className,
3941
4445
  classNames,
3942
4446
  onClick
3943
4447
  }) {
3944
4448
  const isEmpty = empty ?? noData ?? false;
3945
4449
  const resolvedEmptyText = emptyText ?? noDataText ?? "No data available";
3946
- const resolvedBorderDegree = useResolvedBorderDegree({
3947
- borderDegree,
3948
- bordered,
3949
- fallback: "default"
3950
- });
4450
+ const recipe = useNajmComponentStyle("card");
4451
+ const recipeRadius = resolveRadiusValue(recipe?.radius);
4452
+ const recipeStyle = recipeRadius || recipe?.borderWidth ? {
4453
+ ...recipeRadius ? { borderRadius: recipeRadius } : {},
4454
+ ...recipe?.borderWidth ? { borderWidth: recipe.borderWidth } : {}
4455
+ } : void 0;
3951
4456
  let actionSlot = null;
3952
4457
  let footerSlot = null;
3953
4458
  const mainChildren = [];
@@ -3966,18 +4471,16 @@ function NCard({
3966
4471
  });
3967
4472
  const hasHeader = !!(title || description || actionSlot);
3968
4473
  const iconSize = description ? "h-8 w-8" : "h-5 w-5";
3969
- const isStrong = resolvedBorderDegree === "strong";
3970
- const isNone = resolvedBorderDegree === "none";
3971
4474
  return /* @__PURE__ */ jsxs(
3972
4475
  Card,
3973
4476
  {
3974
- "data-bordered": bordered ? "true" : void 0,
3975
- "data-border-degree": resolvedBorderDegree,
4477
+ "data-bordered": bordered === false ? "false" : bordered ? "true" : void 0,
3976
4478
  onClick,
4479
+ style: recipeStyle,
3977
4480
  className: cn(
3978
4481
  "flex flex-col",
3979
4482
  !noPadding && "p-4 gap-3",
3980
- isNone ? "border-transparent" : `${borderColorClassForDegree(resolvedBorderDegree)} ${isStrong ? "shadow-none" : ""}`,
4483
+ surfaceBorderClasses(bordered),
3981
4484
  classNames?.root,
3982
4485
  className
3983
4486
  ),
@@ -4166,7 +4669,6 @@ function DefaultCard({
4166
4669
  change,
4167
4670
  onClick,
4168
4671
  bordered,
4169
- borderDegree,
4170
4672
  className,
4171
4673
  classNames
4172
4674
  }) {
@@ -4176,7 +4678,6 @@ function DefaultCard({
4176
4678
  noPadding: true,
4177
4679
  onClick,
4178
4680
  bordered,
4179
- borderDegree,
4180
4681
  className: cn(
4181
4682
  "group p-4 transition-colors",
4182
4683
  onClick && "cursor-pointer hover:border-border/60 hover:bg-accent/40",
@@ -4233,7 +4734,6 @@ function UsageCard({
4233
4734
  countLabel,
4234
4735
  onClick,
4235
4736
  bordered,
4236
- borderDegree,
4237
4737
  className,
4238
4738
  classNames
4239
4739
  }) {
@@ -4245,7 +4745,6 @@ function UsageCard({
4245
4745
  noPadding: true,
4246
4746
  onClick,
4247
4747
  bordered,
4248
- borderDegree,
4249
4748
  className: cn(
4250
4749
  "group min-h-[116px] px-4 py-4 transition-colors",
4251
4750
  onClick && "cursor-pointer hover:bg-accent/30",
@@ -4290,14 +4789,13 @@ function UsageCard({
4290
4789
  }
4291
4790
  );
4292
4791
  }
4293
- function CompactCard({ icon, label, value, unit, iconColor, onClick, bordered, borderDegree, className, classNames }) {
4792
+ function CompactCard({ icon, label, value, unit, iconColor, onClick, bordered, className, classNames }) {
4294
4793
  return /* @__PURE__ */ jsxs(
4295
4794
  NCard,
4296
4795
  {
4297
4796
  noPadding: true,
4298
4797
  onClick,
4299
4798
  bordered,
4300
- borderDegree,
4301
4799
  className: cn(
4302
4800
  !bordered && "border-0",
4303
4801
  "bg-foreground/10 p-3 shadow-none",
@@ -5116,7 +5614,7 @@ function NFolderIcon({ size = "md", className }) {
5116
5614
  return /* @__PURE__ */ jsx("span", { className: cn(dim, "inline-flex shrink-0 items-center justify-center", className), children: /* @__PURE__ */ jsx(Folder, { size: iconSize, className: "text-sky-500", fill: "currentColor", strokeWidth: 1.5 }) });
5117
5615
  }
5118
5616
  var NO_SHADE = /* @__PURE__ */ new Set(["black", "white"]);
5119
- var PRESETS = {
5617
+ var PRESETS2 = {
5120
5618
  muted: "border-muted-foreground",
5121
5619
  primary: "border-primary",
5122
5620
  accent: "border-accent",
@@ -5148,15 +5646,11 @@ var FOCUS_INTERACTIVE_BASE = "border focus-within:border-primary";
5148
5646
  var HOVER_INTERACTIVE_BASE = "hover:border-primary";
5149
5647
  var STATIC_BASE = "border";
5150
5648
  var BaseInput = React__default.forwardRef(
5151
- ({ children, variant = "default", status = "default", bordered, borderDegree, borderColor, className, disabled = false, onHover, onClick, hasIcon, ...rest }, ref) => {
5649
+ ({ children, variant = "default", status = "default", bordered, borderColor, className, disabled = false, onHover, onClick, hasIcon, ...rest }, ref) => {
5152
5650
  const isGhost = variant === "ghost";
5153
5651
  const isError = status === "error";
5154
- const resolvedBorderDegree = useResolvedBorderDegree({
5155
- borderDegree,
5156
- bordered,
5157
- fallback: "default"
5158
- });
5159
5652
  const hasExplicitColor = !!borderColor;
5653
+ const isBordered = bordered !== false;
5160
5654
  let colorClass = "";
5161
5655
  let borderClass = "";
5162
5656
  if (!isGhost) {
@@ -5164,17 +5658,17 @@ var BaseInput = React__default.forwardRef(
5164
5658
  borderClass = ERROR_BORDER;
5165
5659
  } else if (hasExplicitColor) {
5166
5660
  borderClass = `${STATIC_BASE} ${FOCUS_INTERACTIVE_BASE} ${HOVER_INTERACTIVE_BASE}`;
5167
- colorClass = PRESETS[borderColor] ?? (NO_SHADE.has(borderColor) ? `border-${borderColor}` : `border-${borderColor}-600`);
5661
+ colorClass = PRESETS2[borderColor] ?? (NO_SHADE.has(borderColor) ? `border-${borderColor}` : `border-${borderColor}-600`);
5168
5662
  } else {
5169
- const restingBorderClass = inputBorderColorClassForDegree(resolvedBorderDegree);
5170
- borderClass = resolvedBorderDegree === "default" ? `${STATIC_BASE} ${restingBorderClass} hover:border-input focus-within:border-primary/70` : `${STATIC_BASE} ${restingBorderClass} focus-within:border-primary/70`;
5663
+ const restingBorderClass = inputBorderClasses(isBordered);
5664
+ borderClass = isBordered ? `${STATIC_BASE} ${restingBorderClass} hover:border-input focus-within:border-primary/70` : restingBorderClass;
5171
5665
  }
5172
5666
  }
5173
5667
  return /* @__PURE__ */ jsx(
5174
5668
  "div",
5175
5669
  {
5176
5670
  ref,
5177
- "data-border-degree": isGhost ? void 0 : resolvedBorderDegree,
5671
+ "data-bordered": !isGhost && !isBordered ? "false" : !isGhost ? "true" : void 0,
5178
5672
  className: cn(
5179
5673
  inputVariants({ variant, status, hasIcon, disabled }),
5180
5674
  !isGhost && borderClass,
@@ -5199,33 +5693,33 @@ function resolveIcon(icon) {
5199
5693
  if (!icon) return null;
5200
5694
  return /* @__PURE__ */ jsx(NIcon, { icon, size: 16 });
5201
5695
  }
5202
- var TextInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, disabled = false, ...props }) => {
5696
+ var TextInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderColor, disabled = false, ...props }) => {
5203
5697
  const shouldDisplayIcon = Boolean(icon) && showIcon;
5204
5698
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5205
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-2", className), disabled, children: [
5699
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), disabled, children: [
5206
5700
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5207
5701
  /* @__PURE__ */ jsx(Input, { placeholder, value, onChange: (ev) => onChange(ev.target.value), className: "p-0 border-0 shadow-none bg-transparent dark:bg-transparent focus-visible:ring-0 focus-visible:ring-transparent focus-visible:ring-offset-0 text-muted-foreground", disabled, ...props })
5208
5702
  ] });
5209
5703
  };
5210
- var NumberInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor }) => {
5704
+ var NumberInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderColor }) => {
5211
5705
  const shouldDisplayIcon = Boolean(icon) && showIcon;
5212
5706
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5213
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-2", className), children: [
5707
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), children: [
5214
5708
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5215
5709
  /* @__PURE__ */ jsx(Input, { type: "number", placeholder, value: value ?? "", onChange: (ev) => onChange(Number(ev.target.value)), className: "p-0 border-0 shadow-none bg-transparent dark:bg-transparent focus-visible:ring-0 focus-visible:ring-transparent focus-visible:ring-offset-0 text-muted-foreground" })
5216
5710
  ] });
5217
5711
  };
5218
- var PasswordInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor }) => {
5712
+ var PasswordInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderColor }) => {
5219
5713
  const [showPassword, setShowPassword] = useState(false);
5220
5714
  const shouldDisplayIcon = Boolean(icon) && showIcon;
5221
5715
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5222
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-2", className), children: [
5716
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), children: [
5223
5717
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5224
5718
  /* @__PURE__ */ jsx(Input, { type: showPassword ? "text" : "password", placeholder, value, onChange: (ev) => onChange(ev.target.value), className: "p-0 border-0 shadow-none bg-transparent dark:bg-transparent focus-visible:ring-0 focus-visible:ring-transparent focus-visible:ring-offset-0 text-muted-foreground" }),
5225
5719
  showPassword ? /* @__PURE__ */ jsx(Eye, { className: "absolute right-2 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground cursor-pointer", onClick: () => setShowPassword(false) }) : /* @__PURE__ */ jsx(EyeOff, { className: "absolute right-2 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground cursor-pointer", onClick: () => setShowPassword(true) })
5226
5720
  ] });
5227
5721
  };
5228
- var TextAreaInput = ({ value, onChange, placeholder = "", className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, rows }) => /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("items-start", className), children: /* @__PURE__ */ jsx(
5722
+ var TextAreaInput = ({ value, onChange, placeholder = "", className = "", variant = "default", status = "default", bordered, borderColor, rows }) => /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className: cn("items-start", className), children: /* @__PURE__ */ jsx(
5229
5723
  Textarea,
5230
5724
  {
5231
5725
  rows,
@@ -5242,7 +5736,7 @@ function renderItems(items) {
5242
5736
  return /* @__PURE__ */ jsx(SelectItem, { value, children: label }, value);
5243
5737
  });
5244
5738
  }
5245
- var SelectInput = ({ placeholder = "", value, onChange, icon, showIcon = true, iconColor, items, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, disabled = false }) => {
5739
+ var SelectInput = ({ placeholder = "", value, onChange, icon, showIcon = true, iconColor, items, className = "", variant = "default", status = "default", bordered, borderColor, disabled = false }) => {
5246
5740
  const shouldDisplayIcon = Boolean(icon) && showIcon && !value;
5247
5741
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5248
5742
  const displayLabel = value ? (() => {
@@ -5250,7 +5744,7 @@ var SelectInput = ({ placeholder = "", value, onChange, icon, showIcon = true, i
5250
5744
  return typeof found === "string" ? found : found?.label ?? value;
5251
5745
  })() : "";
5252
5746
  return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
5253
- /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: "pointer-events-none", children: [
5747
+ /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: "pointer-events-none", children: [
5254
5748
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5255
5749
  /* @__PURE__ */ jsx("span", { className: cn("flex-1 truncate text-sm", !displayLabel && "text-muted-foreground"), children: displayLabel || placeholder }),
5256
5750
  /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 shrink-0 opacity-50" })
@@ -5268,7 +5762,7 @@ var SelectInput = ({ placeholder = "", value, onChange, icon, showIcon = true, i
5268
5762
  ] }, String(value))
5269
5763
  ] });
5270
5764
  };
5271
- var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...", emptyMessage = "No results found.", value, onChange, icon, showIcon = true, iconColor, items = [], className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, disabled = false, allowFreeText = false }) => {
5765
+ var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...", emptyMessage = "No results found.", value, onChange, icon, showIcon = true, iconColor, items = [], className = "", variant = "default", status = "default", bordered, borderColor, disabled = false, allowFreeText = false }) => {
5272
5766
  const [open, setOpen] = useState(false);
5273
5767
  const [query, setQuery] = useState("");
5274
5768
  const normalizedItems = items.map((item) => typeof item === "string" ? { value: item, label: item } : item);
@@ -5288,7 +5782,7 @@ var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...
5288
5782
  setOpen(o);
5289
5783
  if (!o) setQuery("");
5290
5784
  }, children: [
5291
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("cursor-pointer", className), children: [
5785
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("cursor-pointer", className), children: [
5292
5786
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5293
5787
  /* @__PURE__ */ jsx("span", { className: cn("flex-1 truncate text-sm", !displayLabel && "text-muted-foreground"), children: displayLabel || placeholder }),
5294
5788
  /* @__PURE__ */ jsx(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-50" })
@@ -5327,7 +5821,7 @@ var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...
5327
5821
  ] }) })
5328
5822
  ] });
5329
5823
  };
5330
- var MultiSelectInput = ({ placeholder = "Select items...", value = [], onChange, icon, showIcon = true, iconColor, items, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, disabled = false, searchPlaceholder = "Search...", emptyMessage = "No items found.", maxDisplay = 3, showSearch = true }) => {
5824
+ var MultiSelectInput = ({ placeholder = "Select items...", value = [], onChange, icon, showIcon = true, iconColor, items, className = "", variant = "default", status = "default", bordered, borderColor, disabled = false, searchPlaceholder = "Search...", emptyMessage = "No items found.", maxDisplay = 3, showSearch = true }) => {
5331
5825
  const [open, setOpen] = useState(false);
5332
5826
  const shouldDisplayIcon = Boolean(icon) && showIcon && value.length === 0;
5333
5827
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
@@ -5341,7 +5835,7 @@ var MultiSelectInput = ({ placeholder = "Select items...", value = [], onChange,
5341
5835
  const displayedItems = value.slice(0, maxDisplay);
5342
5836
  const remainingCount = value.length - maxDisplay;
5343
5837
  return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
5344
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-2 cursor-pointer", className, disabled && "cursor-not-allowed opacity-50"), children: [
5838
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2 cursor-pointer", className, disabled && "cursor-not-allowed opacity-50"), children: [
5345
5839
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5346
5840
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 flex-1 overflow-hidden", children: value.length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: placeholder }) : /* @__PURE__ */ jsxs(Fragment, { children: [
5347
5841
  displayedItems.map((itemValue) => /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "text-xs px-2 py-0.5 gap-1", children: [
@@ -5375,7 +5869,7 @@ var MultiSelectInput = ({ placeholder = "Select items...", value = [], onChange,
5375
5869
  ] });
5376
5870
  };
5377
5871
  var layoutVariants = cva("flex items-start", { variants: { layout: { column: "flex-col gap-4", row: "flex-row gap-7" } }, defaultVariants: { layout: "row" } });
5378
- var RadioGroupInput = ({ value, onChange, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, layout = "row", items }) => /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderDegree, borderColor, className, children: /* @__PURE__ */ jsx(RadioGroup2, { onValueChange: onChange, value, className: layoutVariants({ layout }), children: items.map((item) => {
5872
+ var RadioGroupInput = ({ value, onChange, className = "", variant = "default", status = "default", bordered, borderColor, layout = "row", items }) => /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className, children: /* @__PURE__ */ jsx(RadioGroup2, { onValueChange: onChange, value, className: layoutVariants({ layout }), children: items.map((item) => {
5379
5873
  const itemValue = typeof item === "string" ? item : item.value;
5380
5874
  const itemLabel = typeof item === "string" ? item : item.label;
5381
5875
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center space-y-0", children: [
@@ -5383,7 +5877,7 @@ var RadioGroupInput = ({ value, onChange, className = "", variant = "default", s
5383
5877
  /* @__PURE__ */ jsx(Label, { className: "text-sm font-normal peer-disabled:opacity-70 ml-1", children: itemLabel })
5384
5878
  ] }, itemValue);
5385
5879
  }) }) });
5386
- var CheckboxInput = ({ value, onChange, helper, label, checkboxClassName, className, variant = "default", status = "default", bordered, borderDegree, borderColor }) => /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("flex gap-2 items-center", className), children: [
5880
+ var CheckboxInput = ({ value, onChange, helper, label, checkboxClassName, className, variant = "default", status = "default", bordered, borderColor }) => /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("flex gap-2 items-center", className), children: [
5387
5881
  /* @__PURE__ */ jsx(Checkbox, { checked: value, onCheckedChange: onChange, className: cn("cursor-pointer transition-colors duration-200 border-primary", checkboxClassName) }),
5388
5882
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
5389
5883
  /* @__PURE__ */ jsx(Label, { className: "cursor-pointer text-muted-foreground", onClick: () => onChange(!value), children: label }),
@@ -5408,7 +5902,6 @@ function CheckboxGroupInput({
5408
5902
  variant = "default",
5409
5903
  status = "default",
5410
5904
  bordered,
5411
- borderDegree,
5412
5905
  borderColor,
5413
5906
  disabled = false
5414
5907
  }) {
@@ -5416,7 +5909,7 @@ function CheckboxGroupInput({
5416
5909
  const next = checked ? [...value, itemValue] : value.filter((v) => v !== itemValue);
5417
5910
  onChange(next);
5418
5911
  };
5419
- return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("flex-wrap", className), disabled, children: /* @__PURE__ */ jsx("div", { className: cn(layoutVariants2({ layout })), children: items.map((item) => {
5912
+ return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className: cn("flex-wrap", className), disabled, children: /* @__PURE__ */ jsx("div", { className: cn(layoutVariants2({ layout })), children: items.map((item) => {
5420
5913
  const itemValue = typeof item === "string" ? item : item.value;
5421
5914
  const itemLabel = typeof item === "string" ? item : item.label;
5422
5915
  const checked = value.includes(itemValue);
@@ -5433,7 +5926,7 @@ function CheckboxGroupInput({
5433
5926
  ] }, itemValue);
5434
5927
  }) }) });
5435
5928
  }
5436
- var SwitchInput = ({ value, onChange, label = "", helper, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, icon, showIcon = true, iconPosition = "label", iconColor }) => /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-2 justify-between items-center", className), children: [
5929
+ var SwitchInput = ({ value, onChange, label = "", helper, className = "", variant = "default", status = "default", bordered, borderColor, icon, showIcon = true, iconPosition = "label", iconColor }) => /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2 justify-between items-center", className), children: [
5437
5930
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
5438
5931
  /* @__PURE__ */ jsxs(Label, { className: "flex items-center gap-2", children: [
5439
5932
  iconPosition === "label" && icon && showIcon && /* @__PURE__ */ jsx("span", { className: "w-4 h-4", children: resolveIcon(icon) }),
@@ -5446,10 +5939,10 @@ var SwitchInput = ({ value, onChange, label = "", helper, className = "", varian
5446
5939
  /* @__PURE__ */ jsx(Switch, { checked: value, onCheckedChange: onChange })
5447
5940
  ] })
5448
5941
  ] });
5449
- var DateInput = ({ value, onChange, placeholder = "Pick a date", className = "", icon, showIcon = true, iconColor, variant = "default", status = "default", bordered, borderDegree, borderColor }) => {
5942
+ var DateInput = ({ value, onChange, placeholder = "Pick a date", className = "", icon, showIcon = true, iconColor, variant = "default", status = "default", bordered, borderColor }) => {
5450
5943
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5451
5944
  const toDateString = (date) => date?.toISOString().split("T")[0];
5452
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className, children: [
5945
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className, children: [
5453
5946
  /* @__PURE__ */ jsxs(Popover, { children: [
5454
5947
  /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx("div", { className: cn("w-full flex items-center cursor-pointer gap-2 justify-start text-left font-normal", !value && "text-foreground"), children: /* @__PURE__ */ jsx(Label, { className: "text-muted-foreground cursor-pointer", children: value ? format(typeof value === "string" ? new Date(value) : value, "PPP") : placeholder }) }) }),
5455
5948
  /* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsx(Calendar, { mode: "single", selected: typeof value === "string" ? new Date(value) : value, onSelect: (date) => onChange(toDateString(date)), captionLayout: "dropdown" }) })
@@ -5464,7 +5957,7 @@ function truncateFilename(filename, maxLength = 25) {
5464
5957
  const name = extIndex !== -1 ? filename.slice(0, extIndex) : filename;
5465
5958
  return `${name.slice(0, maxLength - ext.length - 3)}...${ext}`;
5466
5959
  }
5467
- var FileInput = ({ value, onChange, placeholder = "No file chosen", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor }) => {
5960
+ var FileInput = ({ value, onChange, placeholder = "No file chosen", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderColor }) => {
5468
5961
  const fileInputRef = useRef(null);
5469
5962
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5470
5963
  const displayFilename = () => {
@@ -5472,7 +5965,7 @@ var FileInput = ({ value, onChange, placeholder = "No file chosen", icon, showIc
5472
5965
  const filename = typeof value === "string" ? value.split(/[\\/]/).pop() || "" : value.name;
5473
5966
  return truncateFilename(filename);
5474
5967
  };
5475
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("flex px-0 p-0 text-muted-foreground", className), onClick: () => fileInputRef.current?.click(), children: [
5968
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("flex px-0 p-0 text-muted-foreground", className), onClick: () => fileInputRef.current?.click(), children: [
5476
5969
  /* @__PURE__ */ jsx("input", { type: "file", ref: fileInputRef, onChange: (e) => onChange(e.target.files?.[0] || null), className: "hidden" }),
5477
5970
  /* @__PURE__ */ jsxs("div", { className: "bg-muted flex h-full items-center px-3", children: [
5478
5971
  showIcon && (icon ? /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }) : /* @__PURE__ */ jsx(FileUp, { className: cn(iconProps.className) })),
@@ -5498,18 +5991,12 @@ function NUploader({
5498
5991
  listTitle = "Uploaded files",
5499
5992
  className,
5500
5993
  dropzoneClassName,
5501
- borderDegree,
5502
5994
  onFilesSelected,
5503
5995
  onCancel,
5504
5996
  onRemove
5505
5997
  }) {
5506
5998
  const inputRef = useRef(null);
5507
5999
  const [isDragging, setIsDragging] = useState(false);
5508
- const resolvedBorderDegree = useResolvedBorderDegree({
5509
- borderDegree,
5510
- fallback: "default"
5511
- });
5512
- const dropzoneBorderClass = borderColorClassForDegree(resolvedBorderDegree);
5513
6000
  const emit = useCallback(
5514
6001
  (files) => {
5515
6002
  if (!files || disabled) return;
@@ -5553,8 +6040,7 @@ function NUploader({
5553
6040
  onDragLeave,
5554
6041
  onDrop,
5555
6042
  className: cn(
5556
- "flex flex-col items-center justify-center gap-3 rounded-2xl border-2 border-dashed px-6 py-10 text-center transition-colors",
5557
- dropzoneBorderClass,
6043
+ "flex flex-col items-center justify-center gap-3 rounded-2xl border-2 border-dashed border-border px-6 py-10 text-center transition-colors",
5558
6044
  "bg-muted/40 hover:bg-muted/60",
5559
6045
  isDragging && "border-primary bg-primary/5",
5560
6046
  disabled && "cursor-not-allowed opacity-60",
@@ -5790,18 +6276,52 @@ function ImageInput({
5790
6276
  renderFileInput()
5791
6277
  ] });
5792
6278
  }
5793
- var StarRatingInput = ({ value, onChange, maxStars = 5, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor }) => {
6279
+ var StarRatingInput = ({ value, onChange, maxStars = 5, className = "", variant = "default", status = "default", bordered, borderColor }) => {
5794
6280
  const stars = Array.from({ length: maxStars }, (_, i) => /* @__PURE__ */ jsx(Star, { onClick: () => onChange(i + 1), className: cn("cursor-pointer h-8 w-8", i < value ? "fill-orange-400 text-orange-400" : "fill-[#d6d6d6] text-[#d6d6d6]") }, i));
5795
- return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-2", className), children: stars });
6281
+ return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), children: stars });
5796
6282
  };
5797
6283
  var DEFAULT_COLORS = ["#222222", "#e11d48", "#ea580c", "#16a34a", "#db2777", "#2563eb", "#9333ea", "#eab308"];
5798
- var ColorArrayInput = ({ value, onChange, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, colors = DEFAULT_COLORS }) => {
6284
+ var ColorArrayInput = ({ value, onChange, className = "", variant = "default", status = "default", bordered, borderColor, colors = DEFAULT_COLORS }) => {
5799
6285
  const [selectedColor, setSelectedColor] = useState(value || "");
5800
- return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("flex flex-wrap gap-2", className), children: colors.map((color) => /* @__PURE__ */ jsx("div", { className: cn("flex h-9 w-9 items-center justify-center cursor-pointer rounded-full transition-transform hover:scale-105", selectedColor === color && "ring-2 ring-offset-2"), onClick: () => {
6286
+ return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className: cn("flex flex-wrap gap-2", className), children: colors.map((color) => /* @__PURE__ */ jsx("div", { className: cn("flex h-9 w-9 items-center justify-center cursor-pointer rounded-full transition-transform hover:scale-105", selectedColor === color && "ring-2 ring-offset-2"), onClick: () => {
5801
6287
  setSelectedColor(color);
5802
6288
  onChange(color);
5803
6289
  }, children: /* @__PURE__ */ jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-full", style: { backgroundColor: color }, children: selectedColor === color && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-white" }) }) }, color)) });
5804
6290
  };
6291
+ var toOklch = converter("oklch");
6292
+ function parseColor(input) {
6293
+ return parse((input ?? "").trim());
6294
+ }
6295
+ function formatColor(input, format2) {
6296
+ const c = parseColor(input);
6297
+ if (!c) return input;
6298
+ switch (format2) {
6299
+ case "hex":
6300
+ return formatHex(c) ?? input;
6301
+ case "rgb":
6302
+ return formatRgb(c) ?? input;
6303
+ case "hsl":
6304
+ return formatHsl(c) ?? input;
6305
+ case "oklch": {
6306
+ const o = toOklch(c);
6307
+ if (!o) return input;
6308
+ const l = +o.l.toFixed(4);
6309
+ const ch = +(o.c ?? 0).toFixed(4);
6310
+ const h = +(o.h ?? 0).toFixed(2);
6311
+ return `oklch(${l} ${ch} ${h})`;
6312
+ }
6313
+ }
6314
+ }
6315
+ function detectFormat(input) {
6316
+ const value = (input ?? "").trim().toLowerCase();
6317
+ if (value.startsWith("oklch")) return "oklch";
6318
+ if (value.startsWith("hsl")) return "hsl";
6319
+ if (value.startsWith("rgb")) return "rgb";
6320
+ return "hex";
6321
+ }
6322
+ function toPickerHex(input) {
6323
+ return formatHex(parseColor(input) ?? parseColor("#000000")) ?? "#000000";
6324
+ }
5805
6325
  var PRESET_COLORS = [
5806
6326
  "#EF4444",
5807
6327
  "#F97316",
@@ -5824,7 +6344,14 @@ var PRESET_COLORS = [
5824
6344
  "#6B7280",
5825
6345
  "#000000"
5826
6346
  ];
5827
- function ColorPickerInput({
6347
+ var DEFAULT_FORMATS = ["hex", "rgb", "hsl", "oklch"];
6348
+ function ColorPickerInput(props) {
6349
+ if (props.mode === "popover") {
6350
+ return /* @__PURE__ */ jsx(PopoverColorPicker, { ...props });
6351
+ }
6352
+ return /* @__PURE__ */ jsx(SwatchesColorPicker, { ...props });
6353
+ }
6354
+ function SwatchesColorPicker({
5828
6355
  value = "#000000",
5829
6356
  onChange,
5830
6357
  colors = PRESET_COLORS,
@@ -5832,9 +6359,9 @@ function ColorPickerInput({
5832
6359
  variant = "default",
5833
6360
  status = "default",
5834
6361
  bordered,
5835
- borderDegree,
5836
6362
  borderColor,
5837
- disabled = false
6363
+ disabled = false,
6364
+ hideSwatches = false
5838
6365
  }) {
5839
6366
  const inputRef = useRef(null);
5840
6367
  return /* @__PURE__ */ jsxs(
@@ -5843,7 +6370,6 @@ function ColorPickerInput({
5843
6370
  variant,
5844
6371
  status,
5845
6372
  bordered,
5846
- borderDegree,
5847
6373
  borderColor,
5848
6374
  className: cn("flex-col gap-3 items-start p-3", className),
5849
6375
  disabled,
@@ -5863,14 +6389,14 @@ function ColorPickerInput({
5863
6389
  {
5864
6390
  ref: inputRef,
5865
6391
  type: "color",
5866
- value,
6392
+ value: toPickerHex(value),
5867
6393
  onChange: (e) => onChange(e.target.value),
5868
6394
  disabled,
5869
6395
  className: "sr-only"
5870
6396
  }
5871
6397
  )
5872
6398
  ] }),
5873
- /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: colors.map((color) => /* @__PURE__ */ jsx(
6399
+ !hideSwatches && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: colors.map((color) => /* @__PURE__ */ jsx(
5874
6400
  "button",
5875
6401
  {
5876
6402
  type: "button",
@@ -5880,7 +6406,7 @@ function ColorPickerInput({
5880
6406
  },
5881
6407
  disabled,
5882
6408
  className: cn(
5883
- "w-6 h-6 rounded-md border border-border transition-transform hover:scale-110",
6409
+ "w-6 h-6 rounded-md border border-border transition-transform hover:scale-110 cursor-pointer",
5884
6410
  value === color && "ring-2 ring-primary ring-offset-1"
5885
6411
  ),
5886
6412
  style: { backgroundColor: color },
@@ -5892,6 +6418,121 @@ function ColorPickerInput({
5892
6418
  }
5893
6419
  );
5894
6420
  }
6421
+ function PopoverColorPicker({
6422
+ value = "#000000",
6423
+ onChange,
6424
+ colors = PRESET_COLORS,
6425
+ className,
6426
+ variant = "default",
6427
+ status = "default",
6428
+ bordered,
6429
+ borderColor,
6430
+ disabled = false,
6431
+ hideSwatches = false,
6432
+ formats = DEFAULT_FORMATS,
6433
+ output = "preserve"
6434
+ }) {
6435
+ const initialFormat = formats.includes(detectFormat(value)) ? detectFormat(value) : formats[0] ?? "hex";
6436
+ const [activeFormat, setActiveFormat] = useState(initialFormat);
6437
+ const [draft, setDraft] = useState(value);
6438
+ useEffect(() => {
6439
+ setDraft(value);
6440
+ }, [value]);
6441
+ const outputFormat = output;
6442
+ const emit = (raw) => {
6443
+ if (outputFormat === "preserve") {
6444
+ onChange(raw);
6445
+ } else {
6446
+ onChange(formatColor(raw, outputFormat));
6447
+ }
6448
+ };
6449
+ const handlePickerChange = (hex) => {
6450
+ setDraft(hex);
6451
+ emit(hex);
6452
+ };
6453
+ const handleTextChange = (text) => {
6454
+ setDraft(text);
6455
+ if (parseColor(text)) emit(text);
6456
+ };
6457
+ const handleTabChange = (next) => {
6458
+ setActiveFormat(next);
6459
+ if (parseColor(draft)) setDraft(formatColor(draft, next));
6460
+ };
6461
+ const handlePreset = (color) => {
6462
+ setDraft(color);
6463
+ emit(color);
6464
+ };
6465
+ return /* @__PURE__ */ jsxs(Popover, { children: [
6466
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(
6467
+ "button",
6468
+ {
6469
+ type: "button",
6470
+ disabled,
6471
+ className: cn(
6472
+ "flex items-center gap-3 w-full rounded-md border border-border bg-background px-3 py-2 text-left cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed",
6473
+ status === "error" && "border-destructive",
6474
+ className
6475
+ ),
6476
+ children: [
6477
+ /* @__PURE__ */ jsx(
6478
+ "span",
6479
+ {
6480
+ className: "w-8 h-8 rounded-md border border-border shrink-0",
6481
+ style: { backgroundColor: toPickerHex(value) }
6482
+ }
6483
+ ),
6484
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground font-mono truncate", children: value })
6485
+ ]
6486
+ }
6487
+ ) }),
6488
+ /* @__PURE__ */ jsxs(PopoverContent, { className: "w-64 flex flex-col gap-3", align: "start", children: [
6489
+ /* @__PURE__ */ jsx(
6490
+ HexColorPicker,
6491
+ {
6492
+ color: toPickerHex(draft),
6493
+ onChange: handlePickerChange,
6494
+ style: { width: "100%" }
6495
+ }
6496
+ ),
6497
+ formats.length > 1 && /* @__PURE__ */ jsx("div", { className: "flex gap-1 rounded-md bg-muted p-1", children: formats.map((fmt) => /* @__PURE__ */ jsx(
6498
+ "button",
6499
+ {
6500
+ type: "button",
6501
+ onClick: () => handleTabChange(fmt),
6502
+ className: cn(
6503
+ "flex-1 rounded-sm px-1.5 py-1 text-xs font-medium uppercase cursor-pointer transition-colors",
6504
+ activeFormat === fmt ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
6505
+ ),
6506
+ children: fmt
6507
+ },
6508
+ fmt
6509
+ )) }),
6510
+ /* @__PURE__ */ jsx(
6511
+ "input",
6512
+ {
6513
+ type: "text",
6514
+ value: draft,
6515
+ onChange: (e) => handleTextChange(e.target.value),
6516
+ spellCheck: false,
6517
+ className: "w-full rounded-md border border-border bg-background px-2 py-1.5 text-sm font-mono outline-none focus-visible:ring-2 focus-visible:ring-ring"
6518
+ }
6519
+ ),
6520
+ !hideSwatches && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: colors.map((color) => /* @__PURE__ */ jsx(
6521
+ "button",
6522
+ {
6523
+ type: "button",
6524
+ onClick: () => handlePreset(color),
6525
+ className: cn(
6526
+ "w-5 h-5 rounded-md border border-border transition-transform hover:scale-110 cursor-pointer"
6527
+ ),
6528
+ style: { backgroundColor: color },
6529
+ title: color
6530
+ },
6531
+ color
6532
+ )) })
6533
+ ] })
6534
+ ] });
6535
+ }
5895
6536
  var DEFAULT_OPTIONS = [
5896
6537
  { value: 5, label: "Excellent" },
5897
6538
  { value: 4, label: "Good" },
@@ -5932,7 +6573,6 @@ function EmojiInput({
5932
6573
  variant = "default",
5933
6574
  status = "default",
5934
6575
  bordered,
5935
- borderDegree,
5936
6576
  borderColor,
5937
6577
  disabled = false
5938
6578
  }) {
@@ -5942,7 +6582,6 @@ function EmojiInput({
5942
6582
  variant,
5943
6583
  status,
5944
6584
  bordered,
5945
- borderDegree,
5946
6585
  borderColor,
5947
6586
  className: cn("gap-3 flex-wrap", className),
5948
6587
  disabled,
@@ -6014,7 +6653,6 @@ function PhoneInput({
6014
6653
  variant = "default",
6015
6654
  status = "default",
6016
6655
  bordered,
6017
- borderDegree,
6018
6656
  borderColor
6019
6657
  }) {
6020
6658
  const phoneThemeVars = {
@@ -6039,7 +6677,7 @@ function PhoneInput({
6039
6677
  "--react-international-phone-dropdown-preferred-list-divider-color": "var(--border)",
6040
6678
  "--react-international-phone-dropdown-shadow": "0 16px 40px color-mix(in oklch, var(--background), transparent 55%)"
6041
6679
  };
6042
- return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-0 overflow-visible p-0!", className), disabled, children: /* @__PURE__ */ jsx(
6680
+ return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-0 overflow-visible p-0!", className), disabled, children: /* @__PURE__ */ jsx(
6043
6681
  PhoneInput$1,
6044
6682
  {
6045
6683
  className: "w-full",
@@ -6100,7 +6738,7 @@ function PhoneInput({
6100
6738
  }
6101
6739
  ) });
6102
6740
  }
6103
- var TimeInput = ({ value = "", onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, format24 = true, showSeconds = false, disabled = false }) => {
6741
+ var TimeInput = ({ value = "", onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderColor, format24 = true, showSeconds = false, disabled = false }) => {
6104
6742
  const [inputValue, setInputValue] = useState(value);
6105
6743
  const [isValid, setIsValid] = useState(true);
6106
6744
  useEffect(() => {
@@ -6148,7 +6786,7 @@ var TimeInput = ({ value = "", onChange, placeholder = "", icon, showIcon = true
6148
6786
  };
6149
6787
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
6150
6788
  const currentStatus = !isValid ? "error" : status;
6151
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status: currentStatus, bordered, borderDegree, borderColor, className: cn("gap-2", className), children: [
6789
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status: currentStatus, bordered, borderColor, className: cn("gap-2", className), children: [
6152
6790
  showIcon && (icon ? /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }) : /* @__PURE__ */ jsx(Clock, { className: iconProps.className, style: iconProps.style })),
6153
6791
  /* @__PURE__ */ jsx(Input, { type: "text", placeholder: placeholder || (showSeconds ? "HH:MM:SS" : "HH:MM"), value: inputValue, onChange: (e) => handleInputChange(e.target.value), onKeyDown: (e) => {
6154
6792
  if (!/\d/.test(e.key) && !["Backspace", "Delete", "ArrowLeft", "ArrowRight", "Tab"].includes(e.key)) e.preventDefault();
@@ -6577,12 +7215,11 @@ var VARIANT_PRESETS = {
6577
7215
  }
6578
7216
  };
6579
7217
  var VariantContext = createContext({ variant: "default" });
6580
- var VariantProvider = ({ variant = "default", bordered, borderDegree, children }) => /* @__PURE__ */ jsx(VariantContext.Provider, { value: { variant, bordered, borderDegree }, children });
7218
+ var VariantProvider = ({ variant = "default", bordered, children }) => /* @__PURE__ */ jsx(VariantContext.Provider, { value: { variant, bordered }, children });
6581
7219
  var useVariant = () => useContext(VariantContext).variant;
6582
7220
  var useBordered = () => useContext(VariantContext).bordered;
6583
- var useBorderDegree = () => useContext(VariantContext).borderDegree;
6584
7221
  var useVariantPreset = () => VARIANT_PRESETS[useContext(VariantContext).variant];
6585
- function NFormInner({ schema, defaultValues, onSubmit, form: externalForm, variant = "default", bordered, borderDegree, as = "form", className = "", id, devTools, children }) {
7222
+ function NFormInner({ schema, defaultValues, onSubmit, form: externalForm, variant = "default", bordered, as = "form", className = "", id, devTools, children }) {
6586
7223
  const resolver = useMemo(() => schema ? zodResolver(schema) : void 0, [schema]);
6587
7224
  const internalForm = useForm({
6588
7225
  resolver,
@@ -6614,7 +7251,7 @@ function NFormInner({ schema, defaultValues, onSubmit, form: externalForm, varia
6614
7251
  }, [form.formState.errors]);
6615
7252
  const wrapperClass = cn("flex flex-col h-full w-full gap-4", className);
6616
7253
  const submit = form.handleSubmit(onSubmit);
6617
- const inner = /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsx(VariantProvider, { variant, bordered, borderDegree, children: as === "form" ? /* @__PURE__ */ jsx("form", { id, onSubmit: submit, className: wrapperClass, autoComplete: "off", children }) : /* @__PURE__ */ jsx("div", { id, className: wrapperClass, onKeyDown: (e) => {
7254
+ const inner = /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsx(VariantProvider, { variant, bordered, children: as === "form" ? /* @__PURE__ */ jsx("form", { id, onSubmit: submit, className: wrapperClass, autoComplete: "off", children }) : /* @__PURE__ */ jsx("div", { id, className: wrapperClass, onKeyDown: (e) => {
6618
7255
  if (e.key === "Enter" && e.target.tagName !== "TEXTAREA") {
6619
7256
  e.preventDefault();
6620
7257
  void submit();
@@ -6677,7 +7314,6 @@ var FormInput = ({ name, type, formLabel, formDescription, required = false, dis
6677
7314
  const prefix = usePrefix();
6678
7315
  const preset = useVariantPreset();
6679
7316
  const contextBordered = useBordered();
6680
- const contextBorderDegree = useBorderDegree();
6681
7317
  const fieldName = prefix ? `${prefix}.${name}` : name;
6682
7318
  if (!InputComponent) return null;
6683
7319
  const getDefaultValue = () => {
@@ -6708,7 +7344,7 @@ var FormInput = ({ name, type, formLabel, formDescription, required = false, dis
6708
7344
  formLabel,
6709
7345
  required && !disabled && !readOnly && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
6710
7346
  ] }),
6711
- /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(InputComponent, { value: field.value ?? getDefaultValue(), onChange: handleChange, status: hasError && !isHidden ? "error" : "default", bordered: contextBordered, borderDegree: contextBorderDegree, icon: formLabel ? void 0 : icon, iconColor: formLabel ? void 0 : iconColor, disabled, readOnly, ...inputRest, className: slot.input }) }),
7347
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(InputComponent, { value: field.value ?? getDefaultValue(), onChange: handleChange, status: hasError && !isHidden ? "error" : "default", bordered: contextBordered, icon: formLabel ? void 0 : icon, iconColor: formLabel ? void 0 : iconColor, disabled, readOnly, ...inputRest, className: slot.input }) }),
6712
7348
  !hasError && !disabled && !readOnly && formDescription && /* @__PURE__ */ jsx(FormDescription, { className: slot.description, children: formDescription }),
6713
7349
  !isHidden && /* @__PURE__ */ jsx(FormMessage, { className: slot.error })
6714
7350
  ] });
@@ -7039,7 +7675,6 @@ function WizardForm({
7039
7675
  submitLabel = "Submit",
7040
7676
  variant = "default",
7041
7677
  bordered,
7042
- borderDegree,
7043
7678
  className,
7044
7679
  classNames,
7045
7680
  footerSlot
@@ -7099,7 +7734,7 @@ function WizardForm({
7099
7734
  classNames
7100
7735
  }
7101
7736
  ),
7102
- /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsx(VariantProvider, { variant, bordered, borderDegree, children: /* @__PURE__ */ jsxs(
7737
+ /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsx(VariantProvider, { variant, bordered, children: /* @__PURE__ */ jsxs(
7103
7738
  "form",
7104
7739
  {
7105
7740
  id: `step-${currentStepConfig.id}`,
@@ -7133,18 +7768,12 @@ var handler = {
7133
7768
  }
7134
7769
  };
7135
7770
  useTableStore.use = new Proxy({}, handler);
7136
- var actionButtonClass = (bordered, danger, borderClass) => cn(
7771
+ var actionButtonClass = (bordered, danger) => cn(
7137
7772
  "flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition-colors",
7138
7773
  danger ? "hover:bg-red-500/10 hover:text-red-400" : "hover:bg-muted hover:text-foreground",
7139
- bordered && `border ${borderClass ?? "border-muted-foreground"}`
7774
+ bordered && "border border-muted-foreground"
7140
7775
  );
7141
- function TableActionCell({ row, onView, onEdit, onDelete, openRowMenu, menuButton, bordered, borderDegree }) {
7142
- const resolvedBorderDegree = useResolvedBorderDegree({
7143
- borderDegree,
7144
- bordered,
7145
- fallback: "default"
7146
- });
7147
- const borderClass = borderColorClassForDegree(resolvedBorderDegree);
7776
+ function TableActionCell({ row, onView, onEdit, onDelete, openRowMenu, menuButton, bordered }) {
7148
7777
  if (menuButton && openRowMenu) {
7149
7778
  return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center gap-1", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(
7150
7779
  "button",
@@ -7167,7 +7796,7 @@ function TableActionCell({ row, onView, onEdit, onDelete, openRowMenu, menuButto
7167
7796
  type: "button",
7168
7797
  "aria-label": "View",
7169
7798
  onClick: () => onView(row.original),
7170
- className: actionButtonClass(bordered, false, borderClass),
7799
+ className: actionButtonClass(bordered, false),
7171
7800
  children: /* @__PURE__ */ jsx(Eye, { className: "h-3.5 w-3.5" })
7172
7801
  }
7173
7802
  ),
@@ -7177,7 +7806,7 @@ function TableActionCell({ row, onView, onEdit, onDelete, openRowMenu, menuButto
7177
7806
  type: "button",
7178
7807
  "aria-label": "Edit",
7179
7808
  onClick: () => onEdit(row.original),
7180
- className: actionButtonClass(bordered, false, borderClass),
7809
+ className: actionButtonClass(bordered, false),
7181
7810
  children: /* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" })
7182
7811
  }
7183
7812
  ),
@@ -7187,7 +7816,7 @@ function TableActionCell({ row, onView, onEdit, onDelete, openRowMenu, menuButto
7187
7816
  type: "button",
7188
7817
  "aria-label": "Delete",
7189
7818
  onClick: () => onDelete(row.original),
7190
- className: actionButtonClass(bordered, true, borderClass),
7819
+ className: actionButtonClass(bordered, true),
7191
7820
  children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" })
7192
7821
  }
7193
7822
  )
@@ -7263,7 +7892,6 @@ var createTableStore = () => {
7263
7892
  className: "",
7264
7893
  classNames: {},
7265
7894
  bordered: void 0,
7266
- borderDegree: void 0,
7267
7895
  headerClassName: "bg-card",
7268
7896
  headerColor: "primary",
7269
7897
  showCheckbox: true,
@@ -7517,7 +8145,6 @@ function useTable() {
7517
8145
  const openRowMenu = useTableStore.use.openRowMenu();
7518
8146
  const menuButton = useTableStore.use.menuButton();
7519
8147
  const bordered = useTableStore.use.bordered();
7520
- const borderDegree = useTableStore.use.borderDegree();
7521
8148
  const CardComponent = useTableStore.use.CardComponent();
7522
8149
  const dynamicHeight = useTableStore.use.dynamicHeight();
7523
8150
  const viewMode = useTableStore.use.viewMode();
@@ -7548,14 +8175,14 @@ function useTable() {
7548
8175
  {
7549
8176
  id: "actions",
7550
8177
  header: () => isMenuActions ? null : React__default.createElement("div", { className: "flex w-full justify-start text-left" }, "Actions"),
7551
- cell: ({ row }) => React__default.createElement(TableActionCell, { row, onView, onEdit, onDelete, openRowMenu, menuButton, bordered, borderDegree }),
8178
+ cell: ({ row }) => React__default.createElement(TableActionCell, { row, onView, onEdit, onDelete, openRowMenu, menuButton, bordered }),
7552
8179
  enableSorting: false,
7553
8180
  enableHiding: false
7554
8181
  }
7555
8182
  ];
7556
8183
  }
7557
8184
  return effectiveColumns;
7558
- }, [columns, CardComponent, hasActions, onView, onEdit, onDelete, openRowMenu, menuButton, bordered, borderDegree]);
8185
+ }, [columns, CardComponent, hasActions, onView, onEdit, onDelete, openRowMenu, menuButton, bordered]);
7559
8186
  const notifyStateChange = useCallback((state) => {
7560
8187
  onStateChange?.(state);
7561
8188
  }, [onStateChange]);
@@ -7748,6 +8375,12 @@ function EditableCell({ cell, onCellEdit }) {
7748
8375
  ] });
7749
8376
  }
7750
8377
  function NTableContent({ effectiveMode }) {
8378
+ const recipe = useNajmComponentStyle("table");
8379
+ const recipeRadius = resolveRadiusValue(recipe?.radius);
8380
+ const recipeStyle = recipeRadius || recipe?.borderWidth ? {
8381
+ ...recipeRadius ? { borderRadius: recipeRadius } : {},
8382
+ ...recipe?.borderWidth ? { borderWidth: recipe.borderWidth } : {}
8383
+ } : void 0;
7751
8384
  const table = useTableStore.use.table();
7752
8385
  const storeIsTableView = useTableStore.use.isTableView();
7753
8386
  const columns = useTableStore.use.columns();
@@ -7766,15 +8399,6 @@ function NTableContent({ effectiveMode }) {
7766
8399
  const showContent = useTableStore.use.showContent();
7767
8400
  const classNames = useTableStore.use.classNames();
7768
8401
  const bordered = useTableStore.use.bordered();
7769
- const borderDegree = useTableStore.use.borderDegree();
7770
- const resolvedBorderDegree = useResolvedBorderDegree({
7771
- borderDegree,
7772
- bordered,
7773
- fallback: "default"
7774
- });
7775
- const tableBorderClass = borderColorClassForDegree(resolvedBorderDegree);
7776
- const isStrong = resolvedBorderDegree === "strong";
7777
- const useDegreeBorder = bordered || borderDegree || resolvedBorderDegree !== "default";
7778
8402
  const showCheckbox = useTableStore.use.showCheckbox();
7779
8403
  const selectedRowId = useTableStore.use.selectedRowId();
7780
8404
  const renderSubRow = useTableStore.use.renderSubRow();
@@ -7801,16 +8425,16 @@ function NTableContent({ effectiveMode }) {
7801
8425
  NajmScroll,
7802
8426
  {
7803
8427
  axis: "both",
7804
- "data-border-degree": resolvedBorderDegree,
8428
+ "data-bordered": bordered === false ? "false" : bordered ? "true" : void 0,
7805
8429
  className: cn(
7806
8430
  "min-h-0 flex-1 overflow-hidden rounded-md bg-card",
7807
- useDegreeBorder ? `border ${tableBorderClass}` : "shadow-sm",
7808
- isStrong && "shadow-none",
8431
+ bordered === true ? surfaceBorderClasses(true) : "shadow-sm",
7809
8432
  classNames?.content
7810
8433
  ),
8434
+ style: recipeStyle,
7811
8435
  onContextMenu: handleBackgroundContextMenu,
7812
8436
  children: /* @__PURE__ */ jsxs(Table, { children: [
7813
- /* @__PURE__ */ jsx(TableHeader, { "data-ntable-table-header": true, className: cn("bg-card sticky top-0 z-10", colorStyle?.text, headerClassName, useDegreeBorder && "[&_tr]:border-border", classNames?.tableHeader), children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsxs(TableRow, { className: cn("hover:bg-transparent", useDegreeBorder && "border-border"), children: [
8437
+ /* @__PURE__ */ jsx(TableHeader, { "data-ntable-table-header": true, className: cn("bg-card sticky top-0 z-10", colorStyle?.text, headerClassName, bordered === true && "[&_tr]:border-border", classNames?.tableHeader), children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsxs(TableRow, { className: cn("hover:bg-transparent", bordered === true && "border-border"), children: [
7814
8438
  showCheckbox && /* @__PURE__ */ jsx(TableHead, { className: cn("w-10 text-foreground h-12 text-center", colorStyle?.bg), children: /* @__PURE__ */ jsx(
7815
8439
  Checkbox,
7816
8440
  {
@@ -7843,7 +8467,7 @@ function NTableContent({ effectiveMode }) {
7843
8467
  e.nativeEvent[ROW_CONTEXT_HANDLED] = true;
7844
8468
  onRowContextMenu(e, row.original);
7845
8469
  } : void 0,
7846
- className: cn(colorStyle?.row, classNames?.row, onRowClick && "cursor-pointer", isSelectedByRowId && "bg-primary/5 hover:bg-primary/5", useDegreeBorder && "border-border"),
8470
+ className: cn(colorStyle?.row, classNames?.row, onRowClick && "cursor-pointer", isSelectedByRowId && "bg-primary/5 hover:bg-primary/5", bordered === true && "border-border"),
7847
8471
  children: [
7848
8472
  showCheckbox && /* @__PURE__ */ jsx(TableCell, { className: "h-14 w-10 text-center", children: /* @__PURE__ */ jsx(
7849
8473
  Checkbox,
@@ -7866,7 +8490,7 @@ function NTableContent({ effectiveMode }) {
7866
8490
  },
7867
8491
  className: cn(
7868
8492
  "flex h-6 w-6 items-center justify-center rounded hover:bg-muted",
7869
- useDegreeBorder && `border ${tableBorderClass}`
8493
+ bordered === true && "border border-border"
7870
8494
  ),
7871
8495
  children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
7872
8496
  }
@@ -7887,34 +8511,32 @@ function NTableContent({ effectiveMode }) {
7887
8511
  }
7888
8512
  );
7889
8513
  }
7890
- function NDataCardShell({ row, onClick, onContextMenu, actions, children, className, showCheckbox = true, selectedRowId, openRowMenu, menuButton, bordered, borderDegree }) {
8514
+ function NDataCardShell({ row, onClick, onContextMenu, actions, children, className, showCheckbox = true, selectedRowId, openRowMenu, menuButton, bordered }) {
8515
+ const recipe = useNajmComponentStyle("table");
8516
+ const recipeRadius = resolveRadiusValue(recipe?.radius);
8517
+ const recipeStyle = recipeRadius || recipe?.borderWidth ? {
8518
+ ...recipeRadius ? { borderRadius: recipeRadius } : {},
8519
+ ...recipe?.borderWidth ? { borderWidth: recipe.borderWidth } : {}
8520
+ } : void 0;
7891
8521
  const canExpand = row.getCanExpand();
7892
8522
  const isExpanded = canExpand && row.getIsExpanded();
7893
8523
  const isSelected = row.getIsSelected();
7894
8524
  const isHighlighted = selectedRowId != null && row.original?.id === selectedRowId;
7895
8525
  const isActive = isSelected || isHighlighted;
7896
8526
  const useMenuButton = menuButton && openRowMenu;
7897
- const resolvedBorderDegree = useResolvedBorderDegree({
7898
- borderDegree,
7899
- bordered,
7900
- fallback: "default"
7901
- });
7902
- const isStrong = resolvedBorderDegree === "strong";
7903
- const isNone = resolvedBorderDegree === "none";
7904
- const borderClass = borderColorClassForDegree(resolvedBorderDegree);
7905
8527
  return /* @__PURE__ */ jsxs(
7906
8528
  "div",
7907
8529
  {
7908
8530
  "data-row": "true",
7909
8531
  "data-row-id": row.id,
7910
- "data-border-degree": resolvedBorderDegree,
8532
+ "data-bordered": bordered === false ? "false" : bordered ? "true" : void 0,
7911
8533
  onClick,
7912
8534
  onContextMenu,
8535
+ style: recipeStyle,
7913
8536
  className: cn(
7914
8537
  "relative group w-full rounded-lg bg-card",
7915
- isNone ? "border-transparent" : `border ${borderClass}`,
7916
- isStrong && "shadow-none",
7917
- isActive && (bordered || resolvedBorderDegree !== "default" || borderDegree ? "border-primary" : "ring-2 ring-primary ring-offset-1 ring-offset-background"),
8538
+ surfaceBorderClasses(bordered),
8539
+ isActive && (bordered ? "border-primary" : "ring-2 ring-primary ring-offset-1 ring-offset-background"),
7918
8540
  onClick && "cursor-pointer",
7919
8541
  className
7920
8542
  ),
@@ -8009,7 +8631,7 @@ function NDataCardShell({ row, onClick, onContextMenu, actions, children, classN
8009
8631
  },
8010
8632
  className: cn(
8011
8633
  "absolute bottom-2 right-2 z-10 flex h-6 w-6 items-center justify-center rounded hover:bg-muted",
8012
- bordered && `border ${borderClass}`
8634
+ bordered && "border border-border"
8013
8635
  ),
8014
8636
  children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
8015
8637
  }
@@ -8046,7 +8668,6 @@ function NTableCards({ effectiveMode }) {
8046
8668
  const showContent = useTableStore.use.showContent();
8047
8669
  const classNames = useTableStore.use.classNames();
8048
8670
  const bordered = useTableStore.use.bordered();
8049
- const borderDegree = useTableStore.use.borderDegree();
8050
8671
  const renderSubRow = useTableStore.use.renderSubRow();
8051
8672
  const userGetRowCanExpand = useTableStore.use.getRowCanExpand();
8052
8673
  const handleContainerContextMenu = useCallback((e) => {
@@ -8149,7 +8770,6 @@ function NTableCards({ effectiveMode }) {
8149
8770
  openRowMenu,
8150
8771
  menuButton,
8151
8772
  bordered,
8152
- borderDegree,
8153
8773
  children: /* @__PURE__ */ jsx(
8154
8774
  CardComponent,
8155
8775
  {
@@ -8180,14 +8800,6 @@ function NTablePagination() {
8180
8800
  const setPagination = useTableStore.use.setPagination();
8181
8801
  const isPaginationControlled = useTableStore.use.isPaginationControlled();
8182
8802
  const bordered = useTableStore.use.bordered();
8183
- const borderDegree = useTableStore.use.borderDegree();
8184
- const resolvedBorderDegree = useResolvedBorderDegree({
8185
- borderDegree,
8186
- bordered,
8187
- fallback: "default"
8188
- });
8189
- const triggerBorderClass = borderColorClassForDegree(resolvedBorderDegree);
8190
- const useDegreeBorder = bordered || borderDegree || resolvedBorderDegree !== "default";
8191
8803
  if (!table || !showContent || !showPagination || viewMode === "json" || viewMode === "files") return null;
8192
8804
  const filteredRows = table.getFilteredRowModel().rows;
8193
8805
  const selectedRows = table.getFilteredSelectedRowModel().rows;
@@ -8225,8 +8837,8 @@ function NTablePagination() {
8225
8837
  /* @__PURE__ */ jsx(
8226
8838
  SelectTrigger,
8227
8839
  {
8228
- "data-border-degree": useDegreeBorder ? resolvedBorderDegree : void 0,
8229
- className: cn("h-8 w-[80px]", useDegreeBorder && triggerBorderClass),
8840
+ "data-bordered": bordered ? "true" : void 0,
8841
+ className: cn("h-8 w-[80px]", bordered && "najm-border border-border"),
8230
8842
  children: /* @__PURE__ */ jsx(SelectValue, { placeholder: pageSize })
8231
8843
  }
8232
8844
  ),
@@ -8257,28 +8869,25 @@ function NTablePagination() {
8257
8869
  function SearchFilter({ placeholder }) {
8258
8870
  const table = useTableStore.use.table();
8259
8871
  const bordered = useTableStore.use.bordered();
8260
- const borderDegree = useTableStore.use.borderDegree();
8261
8872
  if (!table) return null;
8262
8873
  const value = table.getState().globalFilter ?? "";
8263
- return /* @__PURE__ */ jsx(TextInput, { icon: Search, value, onChange: (v) => table.setGlobalFilter(v), placeholder: placeholder ?? "Search\u2026", bordered, borderDegree });
8874
+ return /* @__PURE__ */ jsx(TextInput, { icon: Search, value, onChange: (v) => table.setGlobalFilter(v), placeholder: placeholder ?? "Search\u2026", bordered });
8264
8875
  }
8265
8876
  function TextFilter({ name, placeholder }) {
8266
8877
  const table = useTableStore.use.table();
8267
8878
  const bordered = useTableStore.use.bordered();
8268
- const borderDegree = useTableStore.use.borderDegree();
8269
8879
  const column = table?.getColumn?.(name);
8270
8880
  if (!column) return null;
8271
- return /* @__PURE__ */ jsx(TextInput, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value), placeholder, bordered, borderDegree });
8881
+ return /* @__PURE__ */ jsx(TextInput, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value), placeholder, bordered });
8272
8882
  }
8273
8883
  function SelectFilter({ name, options, placeholder, inputType }) {
8274
8884
  const table = useTableStore.use.table();
8275
8885
  const bordered = useTableStore.use.bordered();
8276
- const borderDegree = useTableStore.use.borderDegree();
8277
8886
  const column = table?.getColumn?.(name);
8278
8887
  if (!column) return null;
8279
8888
  const allOptions = [{ value: "__clear__", label: "All" }, ...options.map((o) => typeof o === "string" ? { value: o, label: o } : o)];
8280
8889
  const InputComponent = inputType === "combobox" ? ComboboxInput : SelectInput;
8281
- return /* @__PURE__ */ jsx(InputComponent, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value === "" || value === "__clear__" ? void 0 : value), items: allOptions, placeholder: placeholder || "Filter...", bordered, borderDegree });
8890
+ return /* @__PURE__ */ jsx(InputComponent, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value === "" || value === "__clear__" ? void 0 : value), items: allOptions, placeholder: placeholder || "Filter...", bordered });
8282
8891
  }
8283
8892
  function defaultWrapperClass(filter) {
8284
8893
  return filter.type === "search" ? "flex-1 min-w-[160px] max-w-sm" : "w-full sm:w-40 shrink-0";
@@ -8286,7 +8895,6 @@ function defaultWrapperClass(filter) {
8286
8895
  function RenderFilter({ filter }) {
8287
8896
  const table = useTableStore.use.table();
8288
8897
  const bordered = useTableStore.use.bordered();
8289
- const borderDegree = useTableStore.use.borderDegree();
8290
8898
  if (filter.type === "search") {
8291
8899
  return /* @__PURE__ */ jsx(SearchFilter, { placeholder: filter.placeholder });
8292
8900
  }
@@ -8298,7 +8906,6 @@ function RenderFilter({ filter }) {
8298
8906
  onChange: filter.onChange,
8299
8907
  placeholder: filter.placeholder,
8300
8908
  bordered,
8301
- borderDegree,
8302
8909
  className: "w-full"
8303
8910
  }
8304
8911
  );
@@ -8312,7 +8919,6 @@ function RenderFilter({ filter }) {
8312
8919
  onChange: filter.onChange,
8313
8920
  placeholder: filter.placeholder,
8314
8921
  bordered,
8315
- borderDegree,
8316
8922
  className: "w-full"
8317
8923
  }
8318
8924
  );
@@ -8331,7 +8937,6 @@ function RenderFilter({ filter }) {
8331
8937
  showIcon: true,
8332
8938
  disabled: filter.disabled,
8333
8939
  bordered,
8334
- borderDegree,
8335
8940
  className: "w-full"
8336
8941
  }
8337
8942
  );
@@ -8347,7 +8952,6 @@ function RenderFilter({ filter }) {
8347
8952
  showIcon: true,
8348
8953
  disabled: filter.disabled,
8349
8954
  bordered,
8350
- borderDegree,
8351
8955
  className: "w-full"
8352
8956
  }
8353
8957
  );
@@ -8376,12 +8980,6 @@ function TableAddButton() {
8376
8980
  const addButtonText = useTableStore.use.addButtonText();
8377
8981
  const headerColor = useTableStore.use.headerColor();
8378
8982
  const bordered = useTableStore.use.bordered();
8379
- const borderDegree = useTableStore.use.borderDegree();
8380
- const resolvedBorderDegree = useResolvedBorderDegree({
8381
- borderDegree,
8382
- bordered,
8383
- fallback: "default"
8384
- });
8385
8983
  if (!showAddButton) return null;
8386
8984
  const accentHex = headerColor ? HEADER_HEX[headerColor] : void 0;
8387
8985
  const btnStyle = accentHex ? { backgroundColor: accentHex } : void 0;
@@ -8395,7 +8993,7 @@ function TableAddButton() {
8395
8993
  style: btnStyle,
8396
8994
  "aria-label": addButtonText || "Create",
8397
8995
  title: addButtonText || "Create",
8398
- "data-border-degree": bordered ? resolvedBorderDegree : void 0,
8996
+ "data-bordered": bordered ? "true" : void 0,
8399
8997
  className: `h-10 w-10 shrink-0 cursor-pointer flex items-center justify-center rounded-lg text-white transition-opacity ${baseCls} ${borderedCls}`,
8400
8998
  children: /* @__PURE__ */ jsx(Plus, { className: "h-5 w-5" })
8401
8999
  }
@@ -8412,7 +9010,6 @@ function TableSettingsMenu() {
8412
9010
  const cardComponent = useTableStore.use.CardComponent();
8413
9011
  const table = useTableStore.use.table();
8414
9012
  const bordered = useTableStore.use.bordered();
8415
- const borderDegree = useTableStore.use.borderDegree();
8416
9013
  if (!showViewToggle && !showColumnVisibility) return null;
8417
9014
  const allModes = ["table", "cards", "json", "files"];
8418
9015
  const filteredModes = availableModes ?? allModes;
@@ -8431,7 +9028,7 @@ function TableSettingsMenu() {
8431
9028
  const hasModes = modeItems.length > 0;
8432
9029
  const hasColumns = columns.length > 0;
8433
9030
  return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
8434
- /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(BaseInput, { "aria-label": "Table settings", className: "w-auto cursor-pointer px-3", bordered, borderDegree, children: /* @__PURE__ */ jsx(SlidersHorizontal, { className: "h-4 w-4 shrink-0 text-muted-foreground" }) }) }),
9031
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(BaseInput, { "aria-label": "Table settings", className: "w-auto cursor-pointer px-3", bordered, children: /* @__PURE__ */ jsx(SlidersHorizontal, { className: "h-4 w-4 shrink-0 text-muted-foreground" }) }) }),
8435
9032
  /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-56 bg-card", children: [
8436
9033
  showViewToggle && hasModes && /* @__PURE__ */ jsxs(Fragment, { children: [
8437
9034
  /* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "flex items-center gap-2", children: [
@@ -8757,7 +9354,6 @@ function NTable(props) {
8757
9354
  className: props.className ?? "",
8758
9355
  classNames: props.classNames ?? {},
8759
9356
  bordered: props.bordered,
8760
- borderDegree: props.borderDegree,
8761
9357
  headerClassName: props.headerClassName ?? "bg-card",
8762
9358
  headerColor: props.headerColor ?? "primary",
8763
9359
  showCheckbox: props.showCheckbox ?? true,
@@ -9193,7 +9789,7 @@ function NSmartPasteDialog({
9193
9789
  function NSidebarHeader({ children, collapsed, className, classNames }) {
9194
9790
  if (!children) return null;
9195
9791
  return /* @__PURE__ */ jsx("div", { className: cn(
9196
- "flex items-center h-14 min-h-14 px-4 border-b border-border/70 shrink-0 gap-2 justify-start",
9792
+ "flex items-center h-14 min-h-14 px-4 border-b border-sidebar-border/70 shrink-0 gap-2 justify-start",
9197
9793
  classNames?.sidebarHeader,
9198
9794
  className
9199
9795
  ), children });
@@ -9206,8 +9802,7 @@ function NSidebarLogo({
9206
9802
  collapsed = false
9207
9803
  }) {
9208
9804
  if (!icon && !title && !subtitle) return null;
9209
- const IconNode = React__default.isValidElement(icon) ? icon : typeof icon === "function" || typeof icon === "object" && icon !== null && "$$typeof" in icon ? React__default.createElement(icon, { className: "h-6 w-6 text-primary" }) : icon;
9210
- const collapsedCenter = collapsed ? { marginLeft: "calc(var(--rail, 4rem) / 2 - 2.25rem)" } : void 0;
9805
+ const IconNode = React__default.isValidElement(icon) ? icon : typeof icon === "function" || typeof icon === "object" && icon !== null && "$$typeof" in icon ? React__default.createElement(icon, { className: "h-6 w-6 text-sidebar-primary" }) : icon;
9211
9806
  return /* @__PURE__ */ jsxs(
9212
9807
  "button",
9213
9808
  {
@@ -9221,14 +9816,16 @@ function NSidebarLogo({
9221
9816
  IconNode && /* @__PURE__ */ jsx(
9222
9817
  "div",
9223
9818
  {
9224
- className: "size-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0",
9225
- style: collapsedCenter,
9819
+ className: cn(
9820
+ "size-10 rounded-lg bg-sidebar-primary/10 flex items-center justify-center shrink-0",
9821
+ collapsed && "ml-[calc((var(--rail,4rem)-var(--sidebar-edge-width,0px))/2-var(--spacing,0.25rem)-var(--spacing,0.25rem)-var(--spacing,0.25rem)-var(--spacing,0.25rem)-var(--spacing,0.25rem)-var(--spacing,0.25rem)-var(--spacing,0.25rem)-var(--spacing,0.25rem)-var(--spacing,0.25rem))]"
9822
+ ),
9226
9823
  children: IconNode
9227
9824
  }
9228
9825
  ),
9229
9826
  !collapsed && (title || subtitle) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col ", children: [
9230
- title && /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-foreground leading-tight truncate", children: title }),
9231
- subtitle && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground leading-tight truncate", children: subtitle })
9827
+ title && /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-sidebar-foreground leading-tight truncate", children: title }),
9828
+ subtitle && /* @__PURE__ */ jsx("span", { className: "text-xs text-sidebar-foreground/60 leading-tight truncate", children: subtitle })
9232
9829
  ] })
9233
9830
  ]
9234
9831
  }
@@ -9263,8 +9860,8 @@ function NSidebarItem({
9263
9860
  const baseClasses = cn(
9264
9861
  "flex items-center gap-3 w-full rounded-md text-sm px-2 font-medium transition-colors h-8 text-left",
9265
9862
  depth > 0 && "pl-7",
9266
- collapsed && "pl-[calc(var(--rail,4rem)/2_-_1.5rem)]",
9267
- item.disabled ? "opacity-50 cursor-not-allowed" : active ? "cursor-pointer bg-primary text-primary-foreground" : "cursor-pointer text-muted-foreground hover:bg-accent hover:text-accent-foreground",
9863
+ collapsed && "pl-[calc((var(--rail,4rem)-var(--sidebar-edge-width,0px))/2-var(--spacing,0.25rem)-var(--spacing,0.25rem)-var(--spacing,0.25rem)-var(--spacing,0.25rem)-var(--spacing,0.25rem)-var(--spacing,0.25rem))]",
9864
+ item.disabled ? "opacity-50 cursor-not-allowed" : active ? "cursor-pointer bg-sidebar-primary text-sidebar-primary-foreground" : "cursor-pointer text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
9268
9865
  classNames?.sidebarItem
9269
9866
  );
9270
9867
  const handleClick = () => {
@@ -9349,10 +9946,10 @@ function NSidebarSection({
9349
9946
  "data-sidebar-section": true,
9350
9947
  className: cn(
9351
9948
  "flex flex-col gap-1",
9352
- showSectionSeparators && !isFirst && "border-t border-border/70 pt-3"
9949
+ showSectionSeparators && !isFirst && "border-t border-sidebar-border/70 pt-3"
9353
9950
  ),
9354
9951
  children: [
9355
- showSectionLabels && group.sectionLabel && (collapsed ? /* @__PURE__ */ jsx("div", { className: "h-5" }) : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 h-5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground", children: [
9952
+ showSectionLabels && group.sectionLabel && (collapsed ? /* @__PURE__ */ jsx("div", { className: "h-5" }) : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 h-5 text-[11px] font-semibold uppercase tracking-wider text-sidebar-foreground/60", children: [
9356
9953
  showSectionIcons && group.sectionIcon && /* @__PURE__ */ jsx(group.sectionIcon, { className: "h-3.5 w-3.5 shrink-0" }),
9357
9954
  /* @__PURE__ */ jsx("span", { children: group.sectionLabel })
9358
9955
  ] })),
@@ -9383,9 +9980,10 @@ function NSidebarContent({
9383
9980
  showSectionLabels,
9384
9981
  showSectionIcons,
9385
9982
  showSectionSeparators,
9983
+ contentStyle,
9386
9984
  classNames
9387
9985
  }) {
9388
- return /* @__PURE__ */ jsx(NajmScroll, { axis: "y", className: "flex-1", children: /* @__PURE__ */ jsx("nav", { className: "flex flex-col gap-3 px-4 py-2", children: groups.map((group, gi) => /* @__PURE__ */ jsx(
9986
+ return /* @__PURE__ */ jsx(NajmScroll, { axis: "y", className: "flex-1", children: /* @__PURE__ */ jsx("nav", { className: "flex flex-col gap-3 px-4 py-2", style: contentStyle, children: groups.map((group, gi) => /* @__PURE__ */ jsx(
9389
9987
  NSidebarSection,
9390
9988
  {
9391
9989
  group,
@@ -9411,7 +10009,7 @@ function DefaultFooter({
9411
10009
  collapsed = false
9412
10010
  }) {
9413
10011
  if (!onSettings && !onLogout) return null;
9414
- const itemClass = "flex h-8 w-full cursor-pointer items-center gap-3 rounded-md px-2 text-left text-sm font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors";
10012
+ const itemClass = "flex h-8 w-full cursor-pointer items-center gap-3 rounded-md px-2 text-left text-sm font-medium text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground transition-colors";
9415
10013
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
9416
10014
  onSettings && /* @__PURE__ */ jsxs("button", { type: "button", onClick: onSettings, className: itemClass, "aria-label": settingsLabel, title: settingsLabel, children: [
9417
10015
  /* @__PURE__ */ jsx(Settings, { className: "h-4 w-4 shrink-0" }),
@@ -9443,7 +10041,7 @@ function NSidebarFooter({
9443
10041
  const showCollapseInFooter = showCollapseButton && !isMobile;
9444
10042
  const CollapseIcon = collapsed ? PanelLeftOpen : PanelLeftClose;
9445
10043
  if (!footerContent && !showCollapseInFooter) return null;
9446
- return /* @__PURE__ */ jsxs("div", { className: cn("border-t border-border/70 px-4 py-2 shrink-0 flex flex-col gap-1", classNames?.sidebarFooter, className), children: [
10044
+ return /* @__PURE__ */ jsxs("div", { className: cn("border-t border-sidebar-border/70 px-4 py-2 shrink-0 flex flex-col gap-1", classNames?.sidebarFooter, className), children: [
9447
10045
  footerContent,
9448
10046
  showCollapseInFooter && /* @__PURE__ */ jsxs(
9449
10047
  "button",
@@ -9451,7 +10049,7 @@ function NSidebarFooter({
9451
10049
  type: "button",
9452
10050
  onClick: onToggleCollapsed,
9453
10051
  className: cn(
9454
- "flex items-center w-full cursor-pointer rounded-md text-sm font-medium transition-colors h-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground",
10052
+ "flex items-center w-full cursor-pointer rounded-md text-sm font-medium transition-colors h-8 text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
9455
10053
  "gap-3 px-2 text-left"
9456
10054
  ),
9457
10055
  "aria-label": collapsed ? expandLabel : collapseLabel,
@@ -9475,18 +10073,9 @@ function NSidebarMobile({
9475
10073
  hamburgerClassName,
9476
10074
  showHamburgerButton = true,
9477
10075
  children,
9478
- bordered,
9479
- borderDegree
10076
+ bordered
9480
10077
  }) {
9481
10078
  const mobileClass = mobileBreakpoint === "sm" ? "sm:hidden" : mobileBreakpoint === "lg" ? "lg:hidden" : "md:hidden";
9482
- const resolvedBorderDegree = useResolvedBorderDegree({
9483
- borderDegree,
9484
- bordered,
9485
- fallback: "default"
9486
- });
9487
- const isStrong = resolvedBorderDegree === "strong";
9488
- const isNone = resolvedBorderDegree === "none";
9489
- const mobileBorderClass = isNone ? "border-transparent" : borderColorClassForDegree(resolvedBorderDegree);
9490
10079
  return /* @__PURE__ */ jsxs(Fragment, { children: [
9491
10080
  showHamburgerButton && /* @__PURE__ */ jsx(
9492
10081
  "button",
@@ -9494,7 +10083,7 @@ function NSidebarMobile({
9494
10083
  type: "button",
9495
10084
  onClick: onOpen,
9496
10085
  className: cn(
9497
- "fixed top-3 left-3 z-50 p-2 rounded-lg bg-card border shadow-md text-muted-foreground hover:text-foreground hover:bg-accent transition-colors",
10086
+ "fixed top-3 left-3 z-50 p-2 rounded-lg bg-sidebar najm-border border-sidebar-border shadow-md text-sidebar-foreground hover:text-sidebar-accent-foreground hover:bg-sidebar-accent transition-colors",
9498
10087
  mobileClass,
9499
10088
  hamburgerClassName,
9500
10089
  open && "hidden"
@@ -9514,11 +10103,10 @@ function NSidebarMobile({
9514
10103
  /* @__PURE__ */ jsxs(
9515
10104
  "aside",
9516
10105
  {
9517
- "data-border-degree": resolvedBorderDegree,
10106
+ "data-bordered": bordered === false ? "false" : bordered ? "true" : void 0,
9518
10107
  className: cn(
9519
- "fixed inset-y-0 left-0 z-50 bg-card flex flex-col transition-transform duration-200",
9520
- // When global strong is on, we want a strong border, not a soft `border-r` edge.
9521
- isStrong ? `border ${mobileBorderClass} shadow-none` : isNone ? "border-transparent" : `border-r ${mobileBorderClass}`,
10108
+ "fixed inset-y-0 left-0 z-50 bg-sidebar text-sidebar-foreground flex flex-col transition-transform duration-200",
10109
+ sidebarBorderClasses(bordered, "right"),
9522
10110
  mobileClass,
9523
10111
  open ? "translate-x-0" : "-translate-x-full"
9524
10112
  ),
@@ -9529,7 +10117,7 @@ function NSidebarMobile({
9529
10117
  {
9530
10118
  type: "button",
9531
10119
  onClick: onClose,
9532
- className: "absolute top-3 right-3 z-10 p-1 rounded-md hover:bg-accent text-muted-foreground",
10120
+ className: "absolute top-3 right-3 z-10 p-1 rounded-md hover:bg-sidebar-accent text-sidebar-foreground/70",
9533
10121
  "aria-label": closeLabel,
9534
10122
  children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
9535
10123
  }
@@ -9565,12 +10153,11 @@ function NSidebar({
9565
10153
  defaultCollapsed = false,
9566
10154
  onCollapsedChange,
9567
10155
  showCollapseButton = true,
9568
- collapseButtonPosition = "footer",
9569
- showSectionLabels = true,
10156
+ collapseButtonPosition = "rail",
10157
+ showSectionLabels,
9570
10158
  showSectionIcons = true,
9571
- showSectionSeparators = false,
10159
+ showSectionSeparators,
9572
10160
  bordered,
9573
- borderDegree,
9574
10161
  footer,
9575
10162
  className,
9576
10163
  classNames,
@@ -9595,6 +10182,7 @@ function NSidebar({
9595
10182
  logoutLabel,
9596
10183
  widths
9597
10184
  }) {
10185
+ const recipe = useNajmComponentStyle("sidebar");
9598
10186
  const [_mobileOpen, _setMobileOpen] = useState(defaultMobileOpen);
9599
10187
  const [_collapsed, _setCollapsed] = useState(defaultCollapsed);
9600
10188
  const isControlled = mobileOpenProp !== void 0;
@@ -9604,30 +10192,68 @@ function NSidebar({
9604
10192
  if (!isControlled) _setMobileOpen(open);
9605
10193
  onMobileOpenChange?.(open);
9606
10194
  };
9607
- const handleToggleCollapsed = useCallback(() => {
9608
- const next = !collapsed;
10195
+ const [railDragging, setRailDragging] = useState(false);
10196
+ const suppressRailClickRef = useRef(false);
10197
+ const setCollapsedState = useCallback((next) => {
10198
+ if (next === collapsed) return;
9609
10199
  if (collapsedProp === void 0) _setCollapsed(next);
9610
10200
  onCollapsedChange?.(next);
9611
10201
  }, [collapsed, collapsedProp, onCollapsedChange]);
10202
+ const handleToggleCollapsed = useCallback(() => {
10203
+ setCollapsedState(!collapsed);
10204
+ }, [collapsed, setCollapsedState]);
10205
+ const handleRailPointerDown = useCallback((e) => {
10206
+ if (e.button !== 0) return;
10207
+ const startX = e.clientX;
10208
+ const startCollapsed = collapsed;
10209
+ const threshold = 24;
10210
+ let resolved = false;
10211
+ setRailDragging(true);
10212
+ const onMove = (ev) => {
10213
+ const dx = ev.clientX - startX;
10214
+ if (!resolved && !startCollapsed && dx < -threshold) {
10215
+ resolved = true;
10216
+ suppressRailClickRef.current = true;
10217
+ setCollapsedState(true);
10218
+ } else if (!resolved && startCollapsed && dx > threshold) {
10219
+ resolved = true;
10220
+ suppressRailClickRef.current = true;
10221
+ setCollapsedState(false);
10222
+ }
10223
+ };
10224
+ const onUp = (ev) => {
10225
+ window.removeEventListener("pointermove", onMove);
10226
+ window.removeEventListener("pointerup", onUp);
10227
+ setRailDragging(false);
10228
+ if (resolved || Math.abs(ev.clientX - startX) >= 4) suppressRailClickRef.current = true;
10229
+ };
10230
+ window.addEventListener("pointermove", onMove);
10231
+ window.addEventListener("pointerup", onUp);
10232
+ }, [collapsed, setCollapsedState]);
10233
+ const handleRailClick = useCallback(() => {
10234
+ if (suppressRailClickRef.current) {
10235
+ suppressRailClickRef.current = false;
10236
+ return;
10237
+ }
10238
+ handleToggleCollapsed();
10239
+ }, [handleToggleCollapsed]);
9612
10240
  const handleNavigate = useCallback((href) => {
9613
10241
  onNavigate?.(href);
9614
10242
  if (closeOnNavigate) setMobileOpen(false);
9615
10243
  }, [onNavigate, closeOnNavigate]);
9616
10244
  const groups = useMemo(() => buildGroups(navItems), [navItems]);
9617
- const resolvedBorderDegree = useResolvedBorderDegree({
9618
- borderDegree,
9619
- bordered,
9620
- fallback: "default"
9621
- });
9622
- const sidebarShellBorderClass = borderColorClassForDegree(resolvedBorderDegree);
9623
- const isStrong = resolvedBorderDegree === "strong";
9624
- const isNone = resolvedBorderDegree === "none";
9625
10245
  const desktopClass = mobileBreakpoint === "sm" ? "hidden sm:flex" : mobileBreakpoint === "lg" ? "hidden lg:flex" : "hidden md:flex";
9626
10246
  const expandedWidth = widths?.expanded ?? 240;
9627
10247
  const collapsedWidth = widths?.collapsed ?? 64;
9628
10248
  const mobileWidth = widths?.mobile ?? expandedWidth;
9629
10249
  const railVar = typeof collapsedWidth === "number" ? `${collapsedWidth}px` : collapsedWidth;
10250
+ const sidebarEdgeWidth = bordered === false ? "0px" : recipe?.borderWidth ?? "var(--border-width, 1px)";
9630
10251
  const showEdgeCollapse = showCollapseButton && collapseButtonPosition === "edge";
10252
+ const showRailCollapse = showCollapseButton && collapseButtonPosition === "rail";
10253
+ const effectiveShowSectionLabels = showSectionLabels ?? recipe?.showSectionLabels ?? true;
10254
+ const effectiveShowSectionSeparators = showSectionSeparators ?? recipe?.showSectionSeparators ?? false;
10255
+ const contentSlot = recipe?.slots?.content;
10256
+ const contentStyle = contentSlot?.paddingTop ? { paddingTop: contentSlot.paddingTop } : void 0;
9631
10257
  const defaultLogoContent = logoIcon || logoTitle || logoSubtitle ? /* @__PURE__ */ jsx(NSidebarLogo, { icon: logoIcon, title: logoTitle, subtitle: logoSubtitle, onClick: onLogoClick, collapsed }) : null;
9632
10258
  const headerContent = logo ?? defaultLogoContent;
9633
10259
  const contentProps = {
@@ -9637,9 +10263,10 @@ function NSidebar({
9637
10263
  onNavigate: handleNavigate,
9638
10264
  linkComponent,
9639
10265
  collapsed,
9640
- showSectionLabels,
10266
+ showSectionLabels: effectiveShowSectionLabels,
9641
10267
  showSectionIcons,
9642
- showSectionSeparators,
10268
+ showSectionSeparators: effectiveShowSectionSeparators,
10269
+ contentStyle,
9643
10270
  classNames
9644
10271
  };
9645
10272
  const footerProps = {
@@ -9679,25 +10306,44 @@ function NSidebar({
9679
10306
  hamburgerClassName,
9680
10307
  showHamburgerButton,
9681
10308
  bordered,
9682
- borderDegree,
9683
10309
  children: mobileInner
9684
10310
  }
9685
10311
  ),
9686
10312
  /* @__PURE__ */ jsxs(
9687
10313
  "aside",
9688
10314
  {
9689
- "data-border-degree": resolvedBorderDegree,
10315
+ "data-bordered": bordered === false ? "false" : bordered ? "true" : void 0,
9690
10316
  className: cn(
9691
10317
  desktopClass,
9692
- "relative z-10 flex flex-col h-full bg-card transition-all duration-200",
9693
- isNone ? "border-r border-transparent" : cn("border-r", sidebarShellBorderClass),
9694
- isStrong && "shadow-none",
10318
+ "relative z-10 flex flex-col h-full bg-sidebar text-sidebar-foreground transition-all duration-200",
10319
+ sidebarBorderClasses(bordered, "right"),
9695
10320
  classNames?.sidebar,
9696
10321
  className
9697
10322
  ),
9698
- style: { width: collapsed ? collapsedWidth : expandedWidth, ["--rail"]: railVar },
10323
+ style: {
10324
+ width: collapsed ? collapsedWidth : expandedWidth,
10325
+ ["--rail"]: railVar,
10326
+ ["--sidebar-edge-width"]: sidebarEdgeWidth,
10327
+ ...bordered !== false && recipe?.borderWidth ? { borderRightWidth: recipe.borderWidth } : {}
10328
+ },
9699
10329
  children: [
9700
10330
  sidebarInner,
10331
+ showRailCollapse && /* @__PURE__ */ jsxs(
10332
+ "button",
10333
+ {
10334
+ type: "button",
10335
+ "aria-label": collapsed ? expandLabel : collapseLabel,
10336
+ title: collapsed ? expandLabel : collapseLabel,
10337
+ "data-dragging": railDragging ? "true" : void 0,
10338
+ onPointerDown: handleRailPointerDown,
10339
+ onClick: handleRailClick,
10340
+ className: "group/rail absolute inset-y-0 right-0 z-20 flex w-3 translate-x-1/2 cursor-ew-resize touch-none select-none items-center justify-center border-0 bg-transparent p-0",
10341
+ children: [
10342
+ /* @__PURE__ */ jsx("span", { className: "absolute inset-y-0 right-1/2 w-0.5 translate-x-1/2 bg-sidebar-ring opacity-0 transition-opacity duration-150 group-hover/rail:opacity-100 group-data-[dragging=true]/rail:opacity-100" }),
10343
+ /* @__PURE__ */ jsx("span", { className: "relative h-9 w-1 rounded-full bg-sidebar-border transition-all duration-150 group-hover/rail:h-12 group-hover/rail:bg-sidebar-ring group-data-[dragging=true]/rail:bg-sidebar-ring" })
10344
+ ]
10345
+ }
10346
+ ),
9701
10347
  showEdgeCollapse && /* @__PURE__ */ jsx(
9702
10348
  "button",
9703
10349
  {
@@ -9705,7 +10351,7 @@ function NSidebar({
9705
10351
  onClick: handleToggleCollapsed,
9706
10352
  "aria-label": collapsed ? expandLabel : collapseLabel,
9707
10353
  title: collapsed ? expandLabel : collapseLabel,
9708
- className: "absolute right-0 top-7 z-20 flex size-6 -translate-y-1/2 translate-x-1/2 cursor-pointer items-center justify-center rounded-full border border-border bg-card text-muted-foreground shadow-sm transition-colors hover:bg-accent hover:text-foreground",
10354
+ className: "absolute right-0 top-7 z-20 flex size-6 -translate-y-1/2 translate-x-1/2 cursor-pointer items-center justify-center rounded-full border border-sidebar-border bg-sidebar text-sidebar-foreground shadow-sm transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
9709
10355
  children: collapsed ? /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(ChevronLeft, { className: "h-3.5 w-3.5" })
9710
10356
  }
9711
10357
  )
@@ -9933,6 +10579,29 @@ function NCommandPalette({
9933
10579
  ] })
9934
10580
  ] });
9935
10581
  }
10582
+ function NPageLayout({
10583
+ as: Comp = "main",
10584
+ className,
10585
+ style,
10586
+ ...props
10587
+ }) {
10588
+ const { layout } = useNajmDesign();
10589
+ const pageGutter = layout?.pageGutter ?? "var(--page-gutter, 24px)";
10590
+ const sectionGap = layout?.sectionGap ?? "var(--section-gap, 20px)";
10591
+ return /* @__PURE__ */ jsx(
10592
+ Comp,
10593
+ {
10594
+ className: cn("flex min-w-0 flex-col", className),
10595
+ style: {
10596
+ gap: sectionGap,
10597
+ paddingInline: pageGutter,
10598
+ paddingBlock: sectionGap,
10599
+ ...style
10600
+ },
10601
+ ...props
10602
+ }
10603
+ );
10604
+ }
9936
10605
  function NPageHeaderActions({ children, className }) {
9937
10606
  return /* @__PURE__ */ jsx("div", { className: cn("flex shrink-0 items-center gap-2 sm:gap-3", className), children });
9938
10607
  }
@@ -9952,11 +10621,12 @@ function getSlotElements(children, slot) {
9952
10621
  const matches = React__default.Children.toArray(children).filter((child) => isPageHeaderSlot(child, slot));
9953
10622
  return matches.length > 0 ? matches : void 0;
9954
10623
  }
9955
- function NPageHeader({ icon: Icon2, title, subtitle, actions, filters, top, search, children, className, headerClassName, bordered, borderDegree }) {
10624
+ function NPageHeader({ icon: Icon2, title, subtitle, actions, filters, top, search, children, className, headerClassName, card, bordered }) {
9956
10625
  const [internalSearch, setInternalSearch] = useState("");
10626
+ const recipe = useNajmComponentStyle("pageHeader");
9957
10627
  const searchValue = search?.value ?? internalSearch;
9958
10628
  const handleSearchChange = useCallback((e) => {
9959
- setInternalSearch(e.target.value);
10629
+ setInternalSearch(e.currentTarget.value);
9960
10630
  search?.onChange?.(e);
9961
10631
  }, [search?.onChange]);
9962
10632
  const slottedActions = getSlotElements(children, NPageHeaderActions);
@@ -9965,21 +10635,21 @@ function NPageHeader({ icon: Icon2, title, subtitle, actions, filters, top, sear
9965
10635
  const resolvedActions = slottedActions ?? actions;
9966
10636
  const resolvedFilters = slottedFilters ?? filters;
9967
10637
  const resolvedTop = slottedTop ?? top;
9968
- const resolvedBorderDegree = useResolvedBorderDegree({
9969
- borderDegree,
9970
- bordered,
9971
- fallback: "default"
9972
- });
9973
- const hasBorderShell = bordered || Boolean(borderDegree) || resolvedBorderDegree !== "default";
9974
- const isStrong = resolvedBorderDegree === "strong";
10638
+ const isCard = card ?? recipe?.card ?? bordered === true;
10639
+ const recipeRadius = resolveRadiusValue(recipe?.radius);
10640
+ const recipeStyle = recipeRadius || recipe?.borderWidth ? {
10641
+ ...recipeRadius ? { borderRadius: recipeRadius } : {},
10642
+ ...recipe?.borderWidth ? { borderWidth: recipe.borderWidth } : {}
10643
+ } : void 0;
9975
10644
  return /* @__PURE__ */ jsxs(
9976
10645
  "div",
9977
10646
  {
9978
10647
  "data-slot": "page-header",
9979
- "data-border-degree": hasBorderShell ? resolvedBorderDegree : void 0,
10648
+ "data-card": isCard ? "true" : void 0,
10649
+ "data-bordered": bordered === false ? "false" : bordered ? "true" : void 0,
10650
+ style: recipeStyle,
9980
10651
  className: cn(
9981
- hasBorderShell ? cn("border rounded-xl bg-card shadow-none", borderColorClassForDegree(resolvedBorderDegree)) : "border-b border-border",
9982
- isStrong && "shadow-none",
10652
+ isCard ? cn("rounded-xl bg-card shadow-none", surfaceBorderClasses(true)) : cn("border-b", surfaceBorderClasses(true, "bottom").replace("najm-border-b", "najm-border-b")),
9983
10653
  className
9984
10654
  ),
9985
10655
  children: [
@@ -10042,4 +10712,4 @@ function NInspectorSheet({ open, onClose, title, children }) {
10042
10712
  ] }) });
10043
10713
  }
10044
10714
 
10045
- export { Alert, NCard as AsyncCard, Avatar, AvatarFallback, AvatarGroup, AvatarImage, AvatarStatus, Badge, BaseInput, Button, Calendar, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CheckboxGroupInput, CheckboxInput, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorArrayInput, ColorPickerInput, Combobox, ComboboxInput, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, DateInput, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, DynamicArray_default as DynamicArray, EmojiInput, FileImportButton, FileInput, Form, FormControl, FormDescription, FormField, FormInput, FormItem, FormLabel, FormMessage, IconButton, ImageInput, Indicator, Input, Label, LangInput, MultiSelectInput, NAlert, NAppShell, NCard as NAsyncCard, NAvatar, NBadge, NBulkActionsBar, NButton, NCard, NCardAction, NCardFooter, NCommandPalette, NConfirmDialog, NContextMenu, NDataCardShell, NDeleteDialog, NDeleteDialogContent, NDetailCard, NDetailItem, NDetailList, NDialog, NEmptyState, NErrorBoundary, NErrorState, NFileBrowser, NFileTypeIcon, NFilterBar, NFolderIcon, NForm, NFormSectionHeader, NIcon, NIndicator, NInspectorSheet, NLoadingState, NMultiDialog, NNavbar, NPageHeader, NPageHeaderActions, NPageHeaderFilters, NPageHeaderTop, NPortalScopeProvider, NProgress, NRowActions, NSection, NSectionHeader, NSectionInfo, NSectionWithInfo, NSheet, NSidebar, NSidebarContent, NSidebarFooter, NSidebarHeader, NSidebarItem, NSidebarLogo, NSidebarMobile, NSidebarSection, NSkeleton, NSkeletonCalendar, NSkeletonChart, NSkeletonDonut, NSkeletonEventList, NSkeletonWidget, NSkeletonWidgets, NSlider, NSmartPasteDialog, NSpinner, NStatCard, NStatCardSkeleton, Swap as NSwap, NTable, NTableCardRoot, NTableCards, NTableContent, NTableHeader, NTableJson, NTableLoadingSkeleton, NTablePagination, NTableRowSkeleton, NTableSkeleton, NTabs, NUploader, NViewBody, NViewToggle, NajmScroll, NajmThemeProvider, NativeSelect, NumberInput, PasswordInput, PhoneInput, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PrefixProvider, Progress, RadioGroup2 as RadioGroup, RadioGroupInput, RadioGroupItem, RepeatingFields, ScrollArea, SearchField, SearchField as SearchInput, SegmentedControl, Select, SelectContent, SelectGroup, SelectInput, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator3 as Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SimpleTooltip, NSkeleton as Skeleton, Slider, SliderInput, StarRatingInput, StatusPill, StepIndicator, StepsHeader, StepsProgress, Swap, SwapIndeterminate, SwapOff, SwapOn, Switch, SwitchInput, TAB_COLORS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, TableStoreContext, Tabs, TabsContent, TabsList, TabsTrigger, TextAreaInput, TextInput, Textarea, TimeInput, Toaster, Toggle, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, VariantProvider, WizardForm, alertVariants, avatarVariants, badgeColorVariants, badgeVariants, borderColorClassForDegree, buildDefaultFileColumns, buttonVariants, cn, composePreset, createDialogStore, createTableStore, dialogVariants, formatFileBytes, formatFileRelative, getIconColorProps, indicatorVariants, inputBorderColorClassForDegree, resolveBorderDegree, resolvePreset, resolveSlot, sliderVariants, surfaceBorderClasses, swapVariants, toggleVariants, tooltipContentVariants, truncateByCharacters, useClickOutside, useContextMenu, useDebouncedValue, useDelayedLoading, useDialog, useDialogStore, useDynamicPageSize, useFormField, useFormSubmission, useInfiniteScroll, useKeyboard, useLocalStorageState, useNForm, useNPortalScope, useNajmAppearance, usePrefix, useResolvedBorderDegree, useSelection, useStepNavigation, useStorageContextMenu, useStoreSync, useTable, useTableKeyboard, useTableStore, useVariant, useVariantPreset };
10715
+ export { Alert, NCard as AsyncCard, Avatar, AvatarFallback, AvatarGroup, AvatarImage, AvatarStatus, Badge, BaseInput, Button, Calendar, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CheckboxGroupInput, CheckboxInput, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorArrayInput, ColorPickerInput, Combobox, ComboboxInput, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, DateInput, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, DynamicArray_default as DynamicArray, EmojiInput, FileImportButton, FileInput, Form, FormControl, FormDescription, FormField, FormInput, FormItem, FormLabel, FormMessage, IconButton, ImageInput, Indicator, Input, Label, LangInput, MultiSelectInput, NAJM_COMPONENT_NAMES, NAlert, NAppShell, NCard as NAsyncCard, NAvatar, NBadge, NBulkActionsBar, NButton, NCard, NCardAction, NCardFooter, NCommandPalette, NConfirmDialog, NContextMenu, NDataCardShell, NDeleteDialog, NDeleteDialogContent, NDetailCard, NDetailItem, NDetailList, NDialog, NEmptyState, NErrorBoundary, NErrorState, NFileBrowser, NFileTypeIcon, NFilterBar, NFolderIcon, NForm, NFormSectionHeader, NIcon, NIndicator, NInspectorSheet, NLoadingState, NMultiDialog, NNavbar, NPageHeader, NPageHeaderActions, NPageHeaderFilters, NPageHeaderTop, NPageLayout, NPortalScopeProvider, NProgress, NRowActions, NSection, NSectionHeader, NSectionInfo, NSectionWithInfo, NSheet, NSidebar, NSidebarContent, NSidebarFooter, NSidebarHeader, NSidebarItem, NSidebarLogo, NSidebarMobile, NSidebarSection, NSkeleton, NSkeletonCalendar, NSkeletonChart, NSkeletonDonut, NSkeletonEventList, NSkeletonWidget, NSkeletonWidgets, NSlider, NSmartPasteDialog, NSpinner, NStatCard, NStatCardSkeleton, Swap as NSwap, NTable, NTableCardRoot, NTableCards, NTableContent, NTableHeader, NTableJson, NTableLoadingSkeleton, NTablePagination, NTableRowSkeleton, NTableSkeleton, NTabs, NUploader, NViewBody, NViewToggle, NajmDesignProvider, NajmScroll, NajmThemeProvider, NativeSelect, NumberInput, PasswordInput, PhoneInput, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PrefixProvider, Progress, RADIUS_VALUE_MAP, RadioGroup2 as RadioGroup, RadioGroupInput, RadioGroupItem, RepeatingFields, ScrollArea, SearchField, SearchField as SearchInput, SegmentedControl, Select, SelectContent, SelectGroup, SelectInput, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator3 as Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SimpleTooltip, NSkeleton as Skeleton, Slider, SliderInput, StarRatingInput, StatusPill, StepIndicator, StepsHeader, StepsProgress, Swap, SwapIndeterminate, SwapOff, SwapOn, Switch, SwitchInput, TAB_COLORS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, TableStoreContext, Tabs, TabsContent, TabsList, TabsTrigger, TextAreaInput, TextInput, Textarea, TimeInput, Toaster, Toggle, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, VariantProvider, WizardForm, alertVariants, avatarVariants, badgeColorVariants, badgeVariants, buildDefaultFileColumns, buttonVariants, cn, composePreset, createDialogStore, createTableStore, defineNajmDesignConfig, defineNajmThemeConfig, detectFormat, dialogVariants, formatColor, formatFileBytes, formatFileRelative, getIconColorProps, indicatorVariants, inputBorderClasses, parseColor, parseNajmDesignConfig, parseNajmThemeConfig, resolvePreset, resolveRadiusValue, resolveSlot, resolveVariantAlias, sidebarBorderClasses, sliderVariants, stringifyNajmDesignConfig, stringifyNajmThemeConfig, surfaceBorderClasses, swapVariants, toPickerHex, toggleVariants, tooltipContentVariants, truncateByCharacters, useClickOutside, useContextMenu, useDebouncedValue, useDelayedLoading, useDialog, useDialogStore, useDynamicPageSize, useFormField, useFormSubmission, useInfiniteScroll, useKeyboard, useLocalStorageState, useNForm, useNPortalScope, useNajmAppearance, useNajmComponentStyle, useNajmDesign, usePrefix, useSelection, useStepNavigation, useStorageContextMenu, useStoreSync, useTable, useTableKeyboard, useTableStore, useVariant, useVariantPreset };