najm-kit 0.0.8 → 0.0.10

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
@@ -1,9 +1,9 @@
1
- import * as React38 from 'react';
2
- import React38__default, { createContext, useContext, useCallback, useEffect, useState, useRef, useLayoutEffect, useMemo } from 'react';
1
+ import * as React from 'react';
2
+ import React__default, { createContext, useContext, useCallback, useEffect, useState, useRef, useLayoutEffect, useMemo } from 'react';
3
3
  import { Slot } from '@radix-ui/react-slot';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import * as LucideIcons from 'lucide-react';
6
- import { ChevronDown, AlertTriangle, RefreshCw, LoaderCircleIcon, X, XIcon, ChevronRightIcon, CheckIcon, CircleIcon, ChevronDownIcon, ChevronUpIcon, ChevronLeftIcon, SearchIcon, Table as Table$1, FileJson, ChevronRight, CheckSquare, FilePlus, FolderPlus, Trash2, Share2, Move, ClipboardPaste, Copy, Scissors, Pencil, Download, Eye, ArrowUpDown, Loader2, ChevronUp, Folder, UploadCloud, CheckCircle2, AlertCircle, EyeOff, ChevronsUpDown, Check, Calendar as Calendar$1, FileUp, Star, Globe, Clock, Search, Upload, Plus, MoreVertical, Edit, ChevronsLeft, ChevronLeft, ChevronsRight, Merge, PanelLeftOpen, PanelLeftClose, Menu, LogOut, Image, ArrowUp, ArrowDown, LoaderPinwheelIcon, LoaderIcon, ArrowUpRight, ArrowDownRight, SlidersHorizontal, Columns3, Settings, SearchX, Inbox, List, LayoutGrid, Code, FolderOpen } from 'lucide-react';
6
+ import { ChevronDown, AlertTriangle, RefreshCw, LoaderCircleIcon, X, XIcon, ChevronRightIcon, CheckIcon, CircleIcon, ChevronDownIcon, ChevronUpIcon, ChevronLeftIcon, SearchIcon, Table as Table$1, FileJson, ChevronRight, CheckSquare, FilePlus, FolderPlus, Trash2, Share2, Move, ClipboardPaste, Copy, Scissors, Pencil, Download, Eye, ArrowUpDown, Loader2, ChevronUp, Folder, EyeOff, ChevronsUpDown, Check, Calendar as Calendar$1, FileUp, UploadCloud, CheckCircle2, AlertCircle, Star, Globe, Clock, Search, Upload, Plus, MoreVertical, Edit, ChevronsLeft, ChevronLeft, ChevronsRight, Merge, PanelLeftOpen, PanelLeftClose, Menu, LogOut, Image, ArrowUp, ArrowDown, LoaderPinwheelIcon, LoaderIcon, ArrowUpRight, ArrowDownRight, SlidersHorizontal, Columns3, Settings, SearchX, Inbox, List, LayoutGrid, Code, FolderOpen } from 'lucide-react';
7
7
  import { cva } from 'class-variance-authority';
8
8
  import { clsx } from 'clsx';
9
9
  import { twMerge } from 'tailwind-merge';
@@ -54,6 +54,8 @@ var lightMode = {
54
54
  destructive: "0 84.2% 60.2%",
55
55
  "destructive-foreground": "0 0% 98%",
56
56
  border: "0 0% 89.8%",
57
+ "border-subtle": "0 0% 95%",
58
+ "border-strong": "0 0% 30%",
57
59
  input: "0 0% 89.8%",
58
60
  radius: "0.5rem"
59
61
  };
@@ -73,6 +75,8 @@ var darkMode = {
73
75
  destructive: "0 84% 60%",
74
76
  "destructive-foreground": "0 0% 100%",
75
77
  border: "240 6% 15%",
78
+ "border-subtle": "240 6% 11%",
79
+ "border-strong": "0 0% 78%",
76
80
  input: "240 6% 15%",
77
81
  radius: "0.5rem"
78
82
  };
@@ -162,37 +166,106 @@ function tokensToStyle(tokens, accentOnly) {
162
166
  }
163
167
  return style;
164
168
  }
165
- var NajmThemeDepthContext = React38.createContext(0);
166
- var NajmThemeContainerCtx = React38.createContext(null);
169
+ var NajmThemeDepthContext = React.createContext(0);
170
+ var NajmThemeContainerCtx = React.createContext(null);
171
+ var DEFAULT_APPEARANCE = {
172
+ borderDegree: "default"
173
+ };
174
+ var NajmAppearanceContext = React.createContext(DEFAULT_APPEARANCE);
175
+ function useNajmAppearance() {
176
+ return React.useContext(NajmAppearanceContext);
177
+ }
167
178
  function NajmThemeProvider({
168
179
  preset,
169
180
  mode,
170
181
  accent,
171
182
  tokens,
172
183
  accentOnly,
184
+ appearance,
173
185
  className,
174
186
  asChild,
175
187
  children
176
188
  }) {
177
- const depth = React38.useContext(NajmThemeDepthContext);
189
+ const depth = React.useContext(NajmThemeDepthContext);
178
190
  const isRoot = depth === 0;
179
- const resolved = React38.useMemo(() => {
191
+ const parentAppearance = React.useContext(NajmAppearanceContext);
192
+ const shouldApplyThemeTokens = isRoot || Boolean(preset || mode || tokens);
193
+ const resolved = React.useMemo(() => {
194
+ if (!shouldApplyThemeTokens) return null;
180
195
  if (tokens) return tokens;
181
196
  if (preset) return resolvePreset(preset);
182
197
  if (mode) return composePreset(mode, accent ?? "neutral");
183
198
  return resolvePreset("light");
184
- }, [preset, mode, accent, tokens]);
185
- const style = React38.useMemo(() => tokensToStyle(resolved, accentOnly), [resolved, accentOnly]);
199
+ }, [preset, mode, accent, tokens, shouldApplyThemeTokens]);
200
+ const style = React.useMemo(() => resolved ? tokensToStyle(resolved, accentOnly) : void 0, [resolved, accentOnly]);
186
201
  const Comp = asChild ? Slot : "div";
187
- const [container, setContainer] = React38.useState(null);
188
- React38.useEffect(() => {
202
+ const [container, setContainer] = React.useState(null);
203
+ const resolvedAppearance = React.useMemo(
204
+ () => ({ ...parentAppearance, ...appearance ?? {} }),
205
+ [parentAppearance, appearance]
206
+ );
207
+ React.useEffect(() => {
189
208
  if (!isRoot) return;
190
209
  const root = document.documentElement;
191
- const entries = Object.entries(style);
210
+ const entries = Object.entries(style ?? {});
192
211
  entries.forEach(([k, v]) => root.style.setProperty(k, v));
193
212
  return () => entries.forEach(([k]) => root.style.removeProperty(k));
194
213
  }, [style, isRoot]);
195
- return /* @__PURE__ */ jsx(NajmThemeDepthContext.Provider, { value: depth + 1, children: /* @__PURE__ */ jsx(NajmThemeContainerCtx.Provider, { value: container, children: /* @__PURE__ */ jsx(Comp, { ref: setContainer, "data-najm-theme": preset ?? `${mode ?? "light"}-${accent ?? "neutral"}`, className, style, children }) }) });
214
+ 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
+ Comp,
216
+ {
217
+ ref: setContainer,
218
+ "data-najm-theme": preset ?? `${mode ?? "light"}-${accent ?? "neutral"}`,
219
+ className,
220
+ style,
221
+ children
222
+ }
223
+ ) }) }) });
224
+ }
225
+
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";
243
+ }
244
+ }
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";
255
+ }
256
+ }
257
+ function useResolvedBorderDegree(options = {}) {
258
+ const appearance = useNajmAppearance();
259
+ return resolveBorderDegree(
260
+ options.borderDegree,
261
+ options.bordered,
262
+ appearance.borderDegree,
263
+ options.fallback
264
+ );
265
+ }
266
+ function surfaceBorderClasses(degree) {
267
+ if (degree === "none") return "border border-transparent";
268
+ return `border ${borderColorClassForDegree(degree)}`;
196
269
  }
197
270
  var EDITABLE_INPUT_TYPES = /* @__PURE__ */ new Set([
198
271
  "text",
@@ -391,8 +464,8 @@ var NIcon = ({
391
464
  height: size,
392
465
  ...style
393
466
  };
394
- if (React38__default.isValidElement(icon)) {
395
- return React38__default.cloneElement(icon, {
467
+ if (React__default.isValidElement(icon)) {
468
+ return React__default.cloneElement(icon, {
396
469
  className: cn(className, icon.props.className),
397
470
  onClick,
398
471
  ...rest
@@ -510,7 +583,7 @@ function renderIcon(icon) {
510
583
  if (!icon) return null;
511
584
  return /* @__PURE__ */ jsx(NIcon, { "aria-hidden": "true", icon, className: "shrink-0" });
512
585
  }
513
- var Button = React38.forwardRef(
586
+ var Button = React.forwardRef(
514
587
  ({
515
588
  className,
516
589
  variant,
@@ -526,17 +599,23 @@ var Button = React38.forwardRef(
526
599
  loaderPosition = "left",
527
600
  leftIcon,
528
601
  rightIcon,
529
- bordered = false,
602
+ bordered,
603
+ borderDegree,
530
604
  disabled,
531
605
  children,
532
606
  onClick,
533
607
  ...props
534
608
  }, ref) => {
535
- const [pending, setPending] = React38.useState(false);
609
+ const [pending, setPending] = React.useState(false);
536
610
  const isLoading = loading || pending;
537
611
  const isDisabled = disabled || disabledWhileLoading && isLoading;
538
612
  const Comp = asChild ? Slot : "button";
539
- const handleClick = React38.useCallback(
613
+ const resolvedBorderDegree = useResolvedBorderDegree({
614
+ borderDegree,
615
+ bordered,
616
+ fallback: "default"
617
+ });
618
+ const handleClick = React.useCallback(
540
619
  (event) => {
541
620
  if (isDisabled) {
542
621
  event.preventDefault();
@@ -565,12 +644,22 @@ var Button = React38.forwardRef(
565
644
  "data-slot": "button",
566
645
  "data-loading": isLoading || void 0,
567
646
  "data-disabled": isDisabled || void 0,
647
+ "data-border-degree": variant === "outline" || bordered || borderDegree ? resolvedBorderDegree : void 0,
568
648
  "aria-busy": isLoading || void 0,
569
649
  "aria-disabled": asChild && isDisabled ? true : void 0,
570
650
  disabled: !asChild ? isDisabled : void 0,
571
651
  className: cn(
572
652
  buttonVariants({ variant, size, rounded, fullWidth }),
573
- bordered && "border border-muted-foreground",
653
+ // Outline buttons always have a border; let the resolved degree drive its color.
654
+ variant === "outline" && borderColorClassForDegree(resolvedBorderDegree),
655
+ // 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(
660
+ "border",
661
+ borderDegree ? borderColorClassForDegree(resolvedBorderDegree) : "border-muted-foreground"
662
+ ),
574
663
  className
575
664
  ),
576
665
  onClick: handleClick,
@@ -1032,27 +1121,28 @@ function SheetOverlay({ className, ...props }) {
1032
1121
  );
1033
1122
  }
1034
1123
  var sheetVariants = cva(
1035
- "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500 fixed z-50 gap-4 shadow-lg transition ease-in-out",
1124
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500 fixed z-50 gap-4 shadow-lg transition ease-in-out border-border",
1036
1125
  {
1037
1126
  variants: {
1038
1127
  side: {
1039
- top: "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 border-b border-border",
1040
- bottom: "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 border-t border-border",
1041
- left: "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r border-border sm:max-w-sm",
1042
- right: "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l border-border sm:max-w-sm"
1128
+ top: "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 border-b",
1129
+ bottom: "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 border-t",
1130
+ left: "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
1131
+ right: "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm"
1043
1132
  }
1044
1133
  },
1045
1134
  defaultVariants: { side: "right" }
1046
1135
  }
1047
1136
  );
1048
1137
  function SheetContent({ className, portalClassName, side, children, ...props }) {
1138
+ const resolvedBorderDegree = useResolvedBorderDegree();
1049
1139
  return /* @__PURE__ */ jsx(SheetPortal, { children: /* @__PURE__ */ jsxs("div", { className: portalClassName, children: [
1050
1140
  /* @__PURE__ */ jsx(SheetOverlay, {}),
1051
1141
  /* @__PURE__ */ jsxs(
1052
1142
  SheetPrimitive.Content,
1053
1143
  {
1054
1144
  "data-slot": "sheet-content",
1055
- className: cn(sheetVariants({ side }), className),
1145
+ className: cn(sheetVariants({ side }), borderColorClassForDegree(resolvedBorderDegree), className),
1056
1146
  ...props,
1057
1147
  children: [
1058
1148
  children,
@@ -1209,6 +1299,7 @@ function DialogOverlay({ className, ...props }) {
1209
1299
  }
1210
1300
  function DialogContent({ className, children, ...props }) {
1211
1301
  const portalClassName = useNPortalScope();
1302
+ const resolvedBorderDegree = useResolvedBorderDegree();
1212
1303
  return /* @__PURE__ */ jsx(DialogPortal, { "data-slot": "dialog-portal", children: /* @__PURE__ */ jsxs("div", { className: portalClassName, children: [
1213
1304
  /* @__PURE__ */ jsx(DialogOverlay, {}),
1214
1305
  /* @__PURE__ */ jsxs(
@@ -1216,7 +1307,8 @@ function DialogContent({ className, children, ...props }) {
1216
1307
  {
1217
1308
  "data-slot": "dialog-content",
1218
1309
  className: cn(
1219
- "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 p-6 shadow-lg duration-200",
1310
+ "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",
1311
+ borderColorClassForDegree(resolvedBorderDegree),
1220
1312
  className
1221
1313
  ),
1222
1314
  ...props,
@@ -1475,9 +1567,9 @@ var dialogVariants = cva(
1475
1567
  );
1476
1568
  var CONTENT_ACTIONS_SELECTOR = '[data-najm-dialog-actions="content"], [data-najm-wizard-form="true"]';
1477
1569
  function useContentOwnsActions() {
1478
- const [contentElement, setContentElement] = React38__default.useState(null);
1479
- const [contentOwnsActions, setContentOwnsActions] = React38__default.useState(false);
1480
- React38__default.useLayoutEffect(() => {
1570
+ const [contentElement, setContentElement] = React__default.useState(null);
1571
+ const [contentOwnsActions, setContentOwnsActions] = React__default.useState(false);
1572
+ React__default.useLayoutEffect(() => {
1481
1573
  if (!contentElement) {
1482
1574
  setContentOwnsActions(false);
1483
1575
  return;
@@ -1624,8 +1716,8 @@ function NDirectDialog({
1624
1716
  closeOnPrimary = true,
1625
1717
  closeOnSecondary = true
1626
1718
  }) {
1627
- const [internalOpen, setInternalOpen] = React38__default.useState(defaultOpen);
1628
- const [primaryLoading, setPrimaryLoading] = React38__default.useState(false);
1719
+ const [internalOpen, setInternalOpen] = React__default.useState(defaultOpen);
1720
+ const [primaryLoading, setPrimaryLoading] = React__default.useState(false);
1629
1721
  const isControlled = open !== void 0;
1630
1722
  const currentOpen = isControlled ? open : internalOpen;
1631
1723
  const setOpen = (nextOpen) => {
@@ -1890,7 +1982,7 @@ function useDialog(store) {
1890
1982
  description: options.description,
1891
1983
  size: options.size || "sm",
1892
1984
  className: options.className,
1893
- render: ({ dialog, zIndex, confirm, cancel, onOpenChange }) => React38__default.createElement(NDeleteDialog, {
1985
+ render: ({ dialog, zIndex, confirm, cancel, onOpenChange }) => React__default.createElement(NDeleteDialog, {
1894
1986
  itemName: options.itemName,
1895
1987
  itemType: options.itemType,
1896
1988
  icon: options.icon,
@@ -2088,7 +2180,7 @@ function DropdownMenuSubContent({ className, ...props }) {
2088
2180
  {
2089
2181
  "data-slot": "dropdown-menu-sub-content",
2090
2182
  className: cn(
2091
- "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-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg",
2183
+ "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=top]:slide-in-from-bottom-2 data-[side=right]:slide-in-from-left-2 z-[10000] min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg",
2092
2184
  className
2093
2185
  ),
2094
2186
  ...props
@@ -2096,14 +2188,16 @@ function DropdownMenuSubContent({ className, ...props }) {
2096
2188
  );
2097
2189
  }
2098
2190
  function DropdownMenuContent({ className, sideOffset = 4, ...props }) {
2099
- const container = React38.useContext(NajmThemeContainerCtx);
2191
+ const container = React.useContext(NajmThemeContainerCtx);
2192
+ const resolvedBorderDegree = useResolvedBorderDegree();
2100
2193
  return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { container: container ?? void 0, children: /* @__PURE__ */ jsx(
2101
2194
  DropdownMenuPrimitive.Content,
2102
2195
  {
2103
2196
  "data-slot": "dropdown-menu-content",
2104
2197
  sideOffset,
2105
2198
  className: cn(
2106
- "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-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md",
2199
+ "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",
2200
+ borderColorClassForDegree(resolvedBorderDegree),
2107
2201
  className
2108
2202
  ),
2109
2203
  ...props
@@ -2173,7 +2267,8 @@ function PopoverAnchor({ ...props }) {
2173
2267
  return /* @__PURE__ */ jsx(PopoverPrimitive.Anchor, { "data-slot": "popover-anchor", ...props });
2174
2268
  }
2175
2269
  function PopoverContent({ className, align = "center", sideOffset = 4, ...props }) {
2176
- const container = React38.useContext(NajmThemeContainerCtx);
2270
+ const container = React.useContext(NajmThemeContainerCtx);
2271
+ const resolvedBorderDegree = useResolvedBorderDegree();
2177
2272
  return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { container: container ?? void 0, children: /* @__PURE__ */ jsx(
2178
2273
  PopoverPrimitive.Content,
2179
2274
  {
@@ -2181,7 +2276,8 @@ function PopoverContent({ className, align = "center", sideOffset = 4, ...props
2181
2276
  align,
2182
2277
  sideOffset,
2183
2278
  className: cn(
2184
- "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-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-none",
2279
+ "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",
2280
+ borderColorClassForDegree(resolvedBorderDegree),
2185
2281
  className
2186
2282
  ),
2187
2283
  ...props
@@ -2221,13 +2317,13 @@ function SelectScrollDownButton({ className, ...props }) {
2221
2317
  return /* @__PURE__ */ jsx(SelectPrimitive.ScrollDownButton, { "data-slot": "select-scroll-down-button", className: cn("flex cursor-default items-center justify-center py-1", className), ...props, children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4" }) });
2222
2318
  }
2223
2319
  function SelectContent({ className, children, position = "popper", ...props }) {
2224
- const container = React38.useContext(NajmThemeContainerCtx);
2320
+ const container = React.useContext(NajmThemeContainerCtx);
2225
2321
  return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { container: container ?? void 0, children: /* @__PURE__ */ jsxs(
2226
2322
  SelectPrimitive.Content,
2227
2323
  {
2228
2324
  "data-slot": "select-content",
2229
2325
  className: cn(
2230
- "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 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] overflow-hidden rounded-md border shadow-md",
2326
+ "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 relative z-[10000] max-h-(--radix-select-content-available-height) min-w-[8rem] overflow-hidden rounded-md border shadow-md",
2231
2327
  position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1 w-[var(--radix-select-trigger-width)]",
2232
2328
  className
2233
2329
  ),
@@ -2261,7 +2357,7 @@ function SelectItem({ className, children, ...props }) {
2261
2357
  function SelectSeparator({ className, ...props }) {
2262
2358
  return /* @__PURE__ */ jsx(SelectPrimitive.Separator, { "data-slot": "select-separator", className: cn("bg-muted pointer-events-none -mx-1 my-1 h-px", className), ...props });
2263
2359
  }
2264
- var NativeSelect = React38.forwardRef(
2360
+ var NativeSelect = React.forwardRef(
2265
2361
  ({ className, options, placeholder, value, ...props }, ref) => {
2266
2362
  const hasValue = value !== void 0 && value !== "";
2267
2363
  return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
@@ -2592,7 +2688,7 @@ function TooltipTrigger({ ...props }) {
2592
2688
  return /* @__PURE__ */ jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
2593
2689
  }
2594
2690
  var tooltipContentVariants = cva(
2595
- "animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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-50 w-fit origin-(--radix-tooltip-content-transform-origin) overflow-hidden rounded-md px-3 py-1.5 text-xs text-balance",
2691
+ "animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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-fit origin-(--radix-tooltip-content-transform-origin) overflow-hidden rounded-md px-3 py-1.5 text-xs text-balance",
2596
2692
  {
2597
2693
  variants: {
2598
2694
  variant: {
@@ -2604,7 +2700,7 @@ var tooltipContentVariants = cva(
2604
2700
  }
2605
2701
  );
2606
2702
  function TooltipContent({ className, sideOffset = 4, variant, children, ...props }) {
2607
- const container = React38.useContext(NajmThemeContainerCtx);
2703
+ const container = React.useContext(NajmThemeContainerCtx);
2608
2704
  return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { container: container ?? void 0, children: /* @__PURE__ */ jsx(
2609
2705
  TooltipPrimitive.Content,
2610
2706
  {
@@ -2865,7 +2961,7 @@ function Avatar({
2865
2961
  ...props
2866
2962
  }) {
2867
2963
  const hasShortcut = src !== void 0 || fallback !== void 0;
2868
- const hasChildren = React38.Children.count(children) > 0;
2964
+ const hasChildren = React.Children.count(children) > 0;
2869
2965
  return /* @__PURE__ */ jsxs(
2870
2966
  AvatarPrimitive.Root,
2871
2967
  {
@@ -2959,9 +3055,9 @@ function AvatarGroup({ ring = true, className, children, ...props }) {
2959
3055
  "data-slot": "avatar-group",
2960
3056
  className: cn("flex -space-x-2", className),
2961
3057
  ...props,
2962
- children: ring ? React38.Children.map(children, (child) => {
2963
- if (React38.isValidElement(child) && child.type === Avatar) {
2964
- return React38.cloneElement(child, { ring: true, ...child.props });
3058
+ children: ring ? React.Children.map(children, (child) => {
3059
+ if (React.isValidElement(child) && child.type === Avatar) {
3060
+ return React.cloneElement(child, { ring: true, ...child.props });
2965
3061
  }
2966
3062
  return child;
2967
3063
  }) : children
@@ -3028,7 +3124,7 @@ function Swap({
3028
3124
  className,
3029
3125
  ...props
3030
3126
  }) {
3031
- const [internalChecked, setInternalChecked] = React38.useState(defaultChecked);
3127
+ const [internalChecked, setInternalChecked] = React.useState(defaultChecked);
3032
3128
  const isControlled = controlledChecked !== void 0 || controlledState !== void 0;
3033
3129
  const currentState = getDerivedState(
3034
3130
  isControlled ? controlledChecked ?? false : internalChecked,
@@ -3036,7 +3132,7 @@ function Swap({
3036
3132
  );
3037
3133
  const dataState = currentState === "indeterminate" ? "indeterminate" : currentState ? "on" : "off";
3038
3134
  const ariaPressed = currentState === "indeterminate" ? "mixed" : currentState;
3039
- const handleClick = React38.useCallback((event) => {
3135
+ const handleClick = React.useCallback((event) => {
3040
3136
  onClick?.(event);
3041
3137
  if (event.defaultPrevented) return;
3042
3138
  if (disabled) return;
@@ -3240,7 +3336,7 @@ var sizeClasses = {
3240
3336
  md: "h-8 w-8",
3241
3337
  lg: "h-10 w-10"
3242
3338
  };
3243
- var IconButton = React38.forwardRef(
3339
+ var IconButton = React.forwardRef(
3244
3340
  ({
3245
3341
  className,
3246
3342
  variant = "ghost",
@@ -3352,7 +3448,7 @@ var toneClasses = {
3352
3448
  ring: "border-primary/30"
3353
3449
  }
3354
3450
  };
3355
- var StatusPill = React38.forwardRef(
3451
+ var StatusPill = React.forwardRef(
3356
3452
  ({ className, tone = "neutral", pulse = false, label, ...props }, ref) => {
3357
3453
  const c = toneClasses[tone];
3358
3454
  return /* @__PURE__ */ jsxs(
@@ -3410,20 +3506,20 @@ function Toaster({ ...props }) {
3410
3506
  );
3411
3507
  }
3412
3508
  var Form = FormProvider;
3413
- var FormFieldContext = React38.createContext({});
3509
+ var FormFieldContext = React.createContext({});
3414
3510
  var FormField = ({ ...props }) => /* @__PURE__ */ jsx(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx(Controller, { ...props }) });
3415
3511
  var useFormField = () => {
3416
- const fieldContext = React38.useContext(FormFieldContext);
3417
- const itemContext = React38.useContext(FormItemContext);
3512
+ const fieldContext = React.useContext(FormFieldContext);
3513
+ const itemContext = React.useContext(FormItemContext);
3418
3514
  const { getFieldState, formState } = useFormContext();
3419
3515
  const fieldState = getFieldState(fieldContext.name, formState);
3420
3516
  if (!fieldContext) throw new Error("useFormField should be used within <FormField>");
3421
3517
  const { id } = itemContext;
3422
3518
  return { id, name: fieldContext.name, formItemId: `${id}-form-item`, formDescriptionId: `${id}-form-item-description`, formMessageId: `${id}-form-item-message`, ...fieldState };
3423
3519
  };
3424
- var FormItemContext = React38.createContext({});
3520
+ var FormItemContext = React.createContext({});
3425
3521
  function FormItem({ className, ...props }) {
3426
- const id = React38.useId();
3522
+ const id = React.useId();
3427
3523
  return /* @__PURE__ */ jsx(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx("div", { "data-slot": "form-item", className: cn("grid gap-2", className), ...props }) });
3428
3524
  }
3429
3525
  function FormLabel({ className, ...props }) {
@@ -3567,7 +3663,7 @@ function NErrorState({ title = "Something went wrong", message, onRetry, retryLa
3567
3663
  ] });
3568
3664
  }
3569
3665
  function NEmptyState({ title = "No data", description, icon, action, className }) {
3570
- const iconContent = icon ? React38__default.isValidElement(icon) ? icon : React38__default.createElement(icon, { className: "h-8 w-8" }) : null;
3666
+ const iconContent = icon ? React__default.isValidElement(icon) ? icon : React__default.createElement(icon, { className: "h-8 w-8" }) : null;
3571
3667
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-center justify-center gap-3 py-12", className), children: [
3572
3668
  iconContent && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground/50", children: iconContent }),
3573
3669
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
@@ -3577,7 +3673,7 @@ function NEmptyState({ title = "No data", description, icon, action, className }
3577
3673
  action && /* @__PURE__ */ jsx("div", { className: "mt-2", children: action })
3578
3674
  ] });
3579
3675
  }
3580
- var NErrorBoundary = class extends React38__default.Component {
3676
+ var NErrorBoundary = class extends React__default.Component {
3581
3677
  constructor(props) {
3582
3678
  super(props);
3583
3679
  this.state = { hasError: false, error: null };
@@ -3823,18 +3919,24 @@ function NCard({
3823
3919
  onRetry,
3824
3920
  noPadding = false,
3825
3921
  separator = false,
3826
- bordered = false,
3922
+ bordered,
3923
+ borderDegree,
3827
3924
  className,
3828
3925
  classNames,
3829
3926
  onClick
3830
3927
  }) {
3831
3928
  const isEmpty = empty ?? noData ?? false;
3832
3929
  const resolvedEmptyText = emptyText ?? noDataText ?? "No data available";
3930
+ const resolvedBorderDegree = useResolvedBorderDegree({
3931
+ borderDegree,
3932
+ bordered,
3933
+ fallback: "default"
3934
+ });
3833
3935
  let actionSlot = null;
3834
3936
  let footerSlot = null;
3835
3937
  const mainChildren = [];
3836
- React38__default.Children.forEach(children, (child) => {
3837
- if (React38__default.isValidElement(child)) {
3938
+ React__default.Children.forEach(children, (child) => {
3939
+ if (React__default.isValidElement(child)) {
3838
3940
  if (child.type === NCardAction) {
3839
3941
  actionSlot = child;
3840
3942
  } else if (child.type === NCardFooter) {
@@ -3848,15 +3950,18 @@ function NCard({
3848
3950
  });
3849
3951
  const hasHeader = !!(title || description || actionSlot);
3850
3952
  const iconSize = description ? "h-8 w-8" : "h-5 w-5";
3953
+ const isStrong = resolvedBorderDegree === "strong";
3954
+ const isNone = resolvedBorderDegree === "none";
3851
3955
  return /* @__PURE__ */ jsxs(
3852
3956
  Card,
3853
3957
  {
3854
3958
  "data-bordered": bordered ? "true" : void 0,
3959
+ "data-border-degree": resolvedBorderDegree,
3855
3960
  onClick,
3856
3961
  className: cn(
3857
3962
  "flex flex-col",
3858
3963
  !noPadding && "p-4 gap-3",
3859
- bordered && "border border-muted-foreground shadow-none",
3964
+ isNone ? "border-transparent" : `${borderColorClassForDegree(resolvedBorderDegree)} ${isStrong ? "shadow-none" : ""}`,
3860
3965
  classNames?.root,
3861
3966
  className
3862
3967
  ),
@@ -3871,7 +3976,7 @@ function NCard({
3871
3976
  ] }),
3872
3977
  actionSlot && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 shrink-0 ml-2", children: actionSlot })
3873
3978
  ] }),
3874
- hasHeader && separator && /* @__PURE__ */ jsx("div", { className: "border-t" }),
3979
+ hasHeader && separator && /* @__PURE__ */ jsx("div", { className: "border-t border-border" }),
3875
3980
  /* @__PURE__ */ jsx(CardContent, { className: cn("flex flex-col flex-1 m-0 p-0", classNames?.content), children: loading && skeleton ? skeleton : loading ? /* @__PURE__ */ jsx(NLoadingState, { label: loadingText }) : error ? /* @__PURE__ */ jsx(
3876
3981
  NErrorState,
3877
3982
  {
@@ -3879,7 +3984,7 @@ function NCard({
3879
3984
  onRetry
3880
3985
  }
3881
3986
  ) : isEmpty ? /* @__PURE__ */ jsx(NEmptyState, { title: resolvedEmptyText }) : mainChildren }),
3882
- footerSlot && /* @__PURE__ */ jsx(CardFooter, { className: cn("p-0 pt-3 border-t mt-auto", classNames?.footer), children: footerSlot })
3987
+ footerSlot && /* @__PURE__ */ jsx(CardFooter, { className: cn("p-0 pt-3 border-t border-border mt-auto", classNames?.footer), children: footerSlot })
3883
3988
  ]
3884
3989
  }
3885
3990
  );
@@ -4045,6 +4150,7 @@ function DefaultCard({
4045
4150
  change,
4046
4151
  onClick,
4047
4152
  bordered,
4153
+ borderDegree,
4048
4154
  className,
4049
4155
  classNames
4050
4156
  }) {
@@ -4054,6 +4160,7 @@ function DefaultCard({
4054
4160
  noPadding: true,
4055
4161
  onClick,
4056
4162
  bordered,
4163
+ borderDegree,
4057
4164
  className: cn(
4058
4165
  "group p-4 transition-colors",
4059
4166
  onClick && "cursor-pointer hover:border-border/60 hover:bg-accent/40",
@@ -4110,6 +4217,7 @@ function UsageCard({
4110
4217
  countLabel,
4111
4218
  onClick,
4112
4219
  bordered,
4220
+ borderDegree,
4113
4221
  className,
4114
4222
  classNames
4115
4223
  }) {
@@ -4121,6 +4229,7 @@ function UsageCard({
4121
4229
  noPadding: true,
4122
4230
  onClick,
4123
4231
  bordered,
4232
+ borderDegree,
4124
4233
  className: cn(
4125
4234
  "group min-h-[116px] px-4 py-4 transition-colors",
4126
4235
  onClick && "cursor-pointer hover:bg-accent/30",
@@ -4165,13 +4274,14 @@ function UsageCard({
4165
4274
  }
4166
4275
  );
4167
4276
  }
4168
- function CompactCard({ icon, label, value, unit, iconColor, onClick, bordered, className, classNames }) {
4277
+ function CompactCard({ icon, label, value, unit, iconColor, onClick, bordered, borderDegree, className, classNames }) {
4169
4278
  return /* @__PURE__ */ jsxs(
4170
4279
  NCard,
4171
4280
  {
4172
4281
  noPadding: true,
4173
4282
  onClick,
4174
4283
  bordered,
4284
+ borderDegree,
4175
4285
  className: cn(
4176
4286
  !bordered && "border-0",
4177
4287
  "bg-foreground/10 p-3 shadow-none",
@@ -4360,7 +4470,7 @@ function NContextMenu({ x, y, items, onAction, onClose, className }) {
4360
4470
  role: "menu",
4361
4471
  "data-context-menu": true,
4362
4472
  className: cn(
4363
- "fixed z-50 w-48 rounded-lg border border-border bg-popover py-1 shadow-xl text-popover-foreground",
4473
+ "fixed z-[10000] w-48 rounded-lg border border-border bg-popover py-1 shadow-xl text-popover-foreground",
4364
4474
  className
4365
4475
  ),
4366
4476
  style: { left: pos.left, top: pos.top },
@@ -4368,7 +4478,7 @@ function NContextMenu({ x, y, items, onAction, onClose, className }) {
4368
4478
  children: items.map((item) => {
4369
4479
  const Icon2 = item.icon;
4370
4480
  const hasSub = !!item.submenu?.length;
4371
- return /* @__PURE__ */ jsxs(React38__default.Fragment, { children: [
4481
+ return /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
4372
4482
  item.separatorBefore && /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-border/60" }),
4373
4483
  /* @__PURE__ */ jsxs(
4374
4484
  "div",
@@ -4989,188 +5099,6 @@ function NFolderIcon({ size = "md", className }) {
4989
5099
  const iconSize = size === "xl" ? 72 : size === "lg" ? 56 : size === "md" ? 28 : 18;
4990
5100
  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 }) });
4991
5101
  }
4992
- function formatBytes2(bytes) {
4993
- if (!bytes && bytes !== 0) return "";
4994
- if (bytes < 1024) return `${bytes} B`;
4995
- if (bytes < 1024 ** 2) return `${(bytes / 1024).toFixed(0)} KB`;
4996
- if (bytes < 1024 ** 3) return `${(bytes / 1024 ** 2).toFixed(1)} MB`;
4997
- return `${(bytes / 1024 ** 3).toFixed(2)} GB`;
4998
- }
4999
- function NUploader({
5000
- title = "Upload Files",
5001
- subtitle,
5002
- accept,
5003
- multiple = true,
5004
- disabled = false,
5005
- items = [],
5006
- listTitle = "Uploaded files",
5007
- className,
5008
- dropzoneClassName,
5009
- onFilesSelected,
5010
- onCancel,
5011
- onRemove
5012
- }) {
5013
- const inputRef = useRef(null);
5014
- const [isDragging, setIsDragging] = useState(false);
5015
- const emit = useCallback(
5016
- (files) => {
5017
- if (!files || disabled) return;
5018
- const arr = Array.from(files);
5019
- if (arr.length) onFilesSelected?.(arr);
5020
- },
5021
- [disabled, onFilesSelected]
5022
- );
5023
- const onDragOver = (e) => {
5024
- e.preventDefault();
5025
- if (!disabled) setIsDragging(true);
5026
- };
5027
- const onDragLeave = (e) => {
5028
- e.preventDefault();
5029
- setIsDragging(false);
5030
- };
5031
- const onDrop = (e) => {
5032
- e.preventDefault();
5033
- setIsDragging(false);
5034
- emit(e.dataTransfer.files);
5035
- };
5036
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
5037
- (title || subtitle) && /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
5038
- title && /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold uppercase tracking-wide text-foreground", children: title }),
5039
- subtitle && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: subtitle })
5040
- ] }),
5041
- /* @__PURE__ */ jsxs(
5042
- "div",
5043
- {
5044
- role: "button",
5045
- tabIndex: disabled ? -1 : 0,
5046
- "aria-disabled": disabled,
5047
- onClick: () => !disabled && inputRef.current?.click(),
5048
- onKeyDown: (e) => {
5049
- if (!disabled && (e.key === "Enter" || e.key === " ")) {
5050
- e.preventDefault();
5051
- inputRef.current?.click();
5052
- }
5053
- },
5054
- onDragOver,
5055
- onDragLeave,
5056
- onDrop,
5057
- className: cn(
5058
- "flex flex-col items-center justify-center gap-3 rounded-2xl border-2 border-dashed px-6 py-10 text-center transition-colors",
5059
- "border-border bg-muted/40 hover:bg-muted/60",
5060
- isDragging && "border-primary bg-primary/5",
5061
- disabled && "cursor-not-allowed opacity-60",
5062
- !disabled && "cursor-pointer",
5063
- dropzoneClassName
5064
- ),
5065
- children: [
5066
- /* @__PURE__ */ jsx(
5067
- "input",
5068
- {
5069
- ref: inputRef,
5070
- type: "file",
5071
- accept,
5072
- multiple,
5073
- className: "hidden",
5074
- onChange: (e) => {
5075
- emit(e.target.files);
5076
- e.target.value = "";
5077
- }
5078
- }
5079
- ),
5080
- /* @__PURE__ */ jsx("div", { className: "flex h-14 w-14 items-center justify-center rounded-full bg-primary/10 text-primary", children: /* @__PURE__ */ jsx(UploadCloud, { className: "h-7 w-7" }) }),
5081
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Drag & Drop your files here" }),
5082
- /* @__PURE__ */ jsx("p", { className: "text-xs uppercase tracking-wider text-muted-foreground/70", children: "or" }),
5083
- /* @__PURE__ */ jsx(
5084
- Button,
5085
- {
5086
- type: "button",
5087
- size: "sm",
5088
- disabled,
5089
- onClick: (e) => {
5090
- e.stopPropagation();
5091
- inputRef.current?.click();
5092
- },
5093
- children: "Browse Files"
5094
- }
5095
- )
5096
- ]
5097
- }
5098
- ),
5099
- items.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
5100
- listTitle && /* @__PURE__ */ jsx("p", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: listTitle }),
5101
- /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2", children: items.map((item) => /* @__PURE__ */ jsx(
5102
- UploaderRow,
5103
- {
5104
- item,
5105
- onCancel,
5106
- onRemove
5107
- },
5108
- item.id
5109
- )) })
5110
- ] })
5111
- ] });
5112
- }
5113
- function UploaderRow({ item, onCancel, onRemove }) {
5114
- const status = item.status ?? "uploading";
5115
- const progress = Math.max(0, Math.min(100, item.progress ?? 0));
5116
- const isDone = status === "done";
5117
- const isError = status === "error";
5118
- return /* @__PURE__ */ jsxs(
5119
- "li",
5120
- {
5121
- className: cn(
5122
- "flex items-center gap-3 rounded-xl border bg-card px-3 py-2.5 shadow-sm",
5123
- isError ? "border-destructive/30" : "border-border"
5124
- ),
5125
- children: [
5126
- /* @__PURE__ */ jsx(
5127
- NFileTypeIcon,
5128
- {
5129
- mimeType: item.mimeType,
5130
- fileName: item.name,
5131
- size: "md"
5132
- }
5133
- ),
5134
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
5135
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
5136
- /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium text-foreground", children: item.name }),
5137
- /* @__PURE__ */ jsx(
5138
- "span",
5139
- {
5140
- className: cn(
5141
- "shrink-0 text-xs tabular-nums",
5142
- isError ? "text-destructive" : "text-muted-foreground"
5143
- ),
5144
- children: isDone ? formatBytes2(item.size) : isError ? "Failed" : `${Math.round(progress)}%`
5145
- }
5146
- )
5147
- ] }),
5148
- !isDone && !isError && /* @__PURE__ */ jsx(Progress, { value: progress, className: "h-1.5" }),
5149
- isError && item.error && /* @__PURE__ */ jsx("span", { className: "text-xs text-destructive", children: item.error })
5150
- ] }),
5151
- /* @__PURE__ */ jsx("div", { className: "shrink-0", children: isDone ? /* @__PURE__ */ jsx(CheckCircle2, { className: "h-5 w-5 text-emerald-500" }) : isError ? /* @__PURE__ */ jsx(
5152
- "button",
5153
- {
5154
- type: "button",
5155
- "aria-label": "Remove",
5156
- onClick: () => onRemove?.(item.id),
5157
- className: "rounded-full p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
5158
- children: /* @__PURE__ */ jsx(AlertCircle, { className: "h-5 w-5 text-destructive" })
5159
- }
5160
- ) : /* @__PURE__ */ jsx(
5161
- "button",
5162
- {
5163
- type: "button",
5164
- "aria-label": "Cancel upload",
5165
- onClick: () => onCancel?.(item.id),
5166
- className: "rounded-full p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
5167
- children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
5168
- }
5169
- ) })
5170
- ]
5171
- }
5172
- );
5173
- }
5174
5102
  var NO_SHADE = /* @__PURE__ */ new Set(["black", "white"]);
5175
5103
  var PRESETS = {
5176
5104
  muted: "border-muted-foreground",
@@ -5199,23 +5127,42 @@ var inputVariants = cva(
5199
5127
  defaultVariants: { variant: "default", status: "default", hasIcon: false, disabled: false }
5200
5128
  }
5201
5129
  );
5202
- var BORDER_INTERACTIVE = "border hover:border-primary focus-within:border-primary";
5203
5130
  var ERROR_BORDER = "border !border-red-600";
5204
- var BaseInput = React38__default.forwardRef(
5205
- ({ children, variant = "default", status = "default", bordered = false, borderColor, className, disabled = false, onHover, onClick, hasIcon, ...rest }, ref) => {
5131
+ var FOCUS_INTERACTIVE_BASE = "border focus-within:border-primary";
5132
+ var HOVER_INTERACTIVE_BASE = "hover:border-primary";
5133
+ var STATIC_BASE = "border";
5134
+ var BaseInput = React__default.forwardRef(
5135
+ ({ children, variant = "default", status = "default", bordered, borderDegree, borderColor, className, disabled = false, onHover, onClick, hasIcon, ...rest }, ref) => {
5206
5136
  const isGhost = variant === "ghost";
5207
5137
  const isError = status === "error";
5208
- const effectiveBorderColor = borderColor ?? (bordered ? "muted" : void 0);
5209
- const showBorder = !isGhost && (!!effectiveBorderColor || isError);
5210
- const colorClass = effectiveBorderColor ? PRESETS[effectiveBorderColor] ?? (NO_SHADE.has(effectiveBorderColor) ? `border-${effectiveBorderColor}` : `border-${effectiveBorderColor}-600`) : "";
5138
+ const resolvedBorderDegree = useResolvedBorderDegree({
5139
+ borderDegree,
5140
+ bordered,
5141
+ fallback: "default"
5142
+ });
5143
+ const hasExplicitColor = !!borderColor;
5144
+ let colorClass = "";
5145
+ let borderClass = "";
5146
+ if (!isGhost) {
5147
+ if (isError) {
5148
+ borderClass = ERROR_BORDER;
5149
+ } else if (hasExplicitColor) {
5150
+ borderClass = `${STATIC_BASE} ${FOCUS_INTERACTIVE_BASE} ${HOVER_INTERACTIVE_BASE}`;
5151
+ colorClass = PRESETS[borderColor] ?? (NO_SHADE.has(borderColor) ? `border-${borderColor}` : `border-${borderColor}-600`);
5152
+ } else {
5153
+ const restingBorderClass = inputBorderColorClassForDegree(resolvedBorderDegree);
5154
+ borderClass = resolvedBorderDegree === "default" ? `${STATIC_BASE} ${restingBorderClass} hover:border-input focus-within:border-primary/70` : `${STATIC_BASE} ${restingBorderClass} focus-within:border-primary/70`;
5155
+ }
5156
+ }
5211
5157
  return /* @__PURE__ */ jsx(
5212
5158
  "div",
5213
5159
  {
5214
5160
  ref,
5161
+ "data-border-degree": isGhost ? void 0 : resolvedBorderDegree,
5215
5162
  className: cn(
5216
5163
  inputVariants({ variant, status, hasIcon, disabled }),
5217
- showBorder && (isError ? ERROR_BORDER : BORDER_INTERACTIVE),
5218
- showBorder && colorClass,
5164
+ !isGhost && borderClass,
5165
+ !isGhost && colorClass,
5219
5166
  className
5220
5167
  ),
5221
5168
  onMouseEnter: disabled ? void 0 : onHover,
@@ -5236,33 +5183,33 @@ function resolveIcon(icon) {
5236
5183
  if (!icon) return null;
5237
5184
  return /* @__PURE__ */ jsx(NIcon, { icon, size: 16 });
5238
5185
  }
5239
- var TextInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered = false, borderColor, disabled = false, ...props }) => {
5186
+ var TextInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, disabled = false, ...props }) => {
5240
5187
  const shouldDisplayIcon = Boolean(icon) && showIcon;
5241
5188
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5242
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), disabled, children: [
5189
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-2", className), disabled, children: [
5243
5190
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5244
5191
  /* @__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 })
5245
5192
  ] });
5246
5193
  };
5247
- var NumberInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered = false, borderColor }) => {
5194
+ var NumberInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor }) => {
5248
5195
  const shouldDisplayIcon = Boolean(icon) && showIcon;
5249
5196
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5250
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), children: [
5197
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-2", className), children: [
5251
5198
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5252
5199
  /* @__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" })
5253
5200
  ] });
5254
5201
  };
5255
- var PasswordInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered = false, borderColor }) => {
5202
+ var PasswordInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor }) => {
5256
5203
  const [showPassword, setShowPassword] = useState(false);
5257
5204
  const shouldDisplayIcon = Boolean(icon) && showIcon;
5258
5205
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5259
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), children: [
5206
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-2", className), children: [
5260
5207
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5261
5208
  /* @__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" }),
5262
5209
  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) })
5263
5210
  ] });
5264
5211
  };
5265
- var TextAreaInput = ({ value, onChange, placeholder = "", className = "", variant = "default", status = "default", bordered = false, borderColor, rows }) => /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className: cn("items-start", className), children: /* @__PURE__ */ jsx(
5212
+ 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(
5266
5213
  Textarea,
5267
5214
  {
5268
5215
  rows,
@@ -5279,7 +5226,7 @@ function renderItems(items) {
5279
5226
  return /* @__PURE__ */ jsx(SelectItem, { value, children: label }, value);
5280
5227
  });
5281
5228
  }
5282
- var SelectInput = ({ placeholder = "", value, onChange, icon, showIcon = true, iconColor, items, className = "", variant = "default", status = "default", bordered = false, borderColor, disabled = false }) => {
5229
+ var SelectInput = ({ placeholder = "", value, onChange, icon, showIcon = true, iconColor, items, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, disabled = false }) => {
5283
5230
  const shouldDisplayIcon = Boolean(icon) && showIcon && !value;
5284
5231
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5285
5232
  const displayLabel = value ? (() => {
@@ -5287,7 +5234,7 @@ var SelectInput = ({ placeholder = "", value, onChange, icon, showIcon = true, i
5287
5234
  return typeof found === "string" ? found : found?.label ?? value;
5288
5235
  })() : "";
5289
5236
  return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
5290
- /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: "pointer-events-none", children: [
5237
+ /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: "pointer-events-none", children: [
5291
5238
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5292
5239
  /* @__PURE__ */ jsx("span", { className: cn("flex-1 truncate text-sm", !displayLabel && "text-muted-foreground"), children: displayLabel || placeholder }),
5293
5240
  /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 shrink-0 opacity-50" })
@@ -5305,7 +5252,7 @@ var SelectInput = ({ placeholder = "", value, onChange, icon, showIcon = true, i
5305
5252
  ] }, String(value))
5306
5253
  ] });
5307
5254
  };
5308
- var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...", emptyMessage = "No results found.", value, onChange, icon, showIcon = true, iconColor, items = [], className = "", variant = "default", status = "default", bordered = false, borderColor, disabled = false, allowFreeText = false }) => {
5255
+ 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 }) => {
5309
5256
  const [open, setOpen] = useState(false);
5310
5257
  const [query, setQuery] = useState("");
5311
5258
  const normalizedItems = items.map((item) => typeof item === "string" ? { value: item, label: item } : item);
@@ -5325,7 +5272,7 @@ var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...
5325
5272
  setOpen(o);
5326
5273
  if (!o) setQuery("");
5327
5274
  }, children: [
5328
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("cursor-pointer", className), children: [
5275
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("cursor-pointer", className), children: [
5329
5276
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5330
5277
  /* @__PURE__ */ jsx("span", { className: cn("flex-1 truncate text-sm", !displayLabel && "text-muted-foreground"), children: displayLabel || placeholder }),
5331
5278
  /* @__PURE__ */ jsx(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-50" })
@@ -5364,7 +5311,7 @@ var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...
5364
5311
  ] }) })
5365
5312
  ] });
5366
5313
  };
5367
- var MultiSelectInput = ({ placeholder = "Select items...", value = [], onChange, icon, showIcon = true, iconColor, items, className = "", variant = "default", status = "default", bordered = false, borderColor, disabled = false, searchPlaceholder = "Search...", emptyMessage = "No items found.", maxDisplay = 3, showSearch = true }) => {
5314
+ 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 }) => {
5368
5315
  const [open, setOpen] = useState(false);
5369
5316
  const shouldDisplayIcon = Boolean(icon) && showIcon && value.length === 0;
5370
5317
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
@@ -5378,7 +5325,7 @@ var MultiSelectInput = ({ placeholder = "Select items...", value = [], onChange,
5378
5325
  const displayedItems = value.slice(0, maxDisplay);
5379
5326
  const remainingCount = value.length - maxDisplay;
5380
5327
  return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
5381
- /* @__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: [
5328
+ /* @__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: [
5382
5329
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5383
5330
  /* @__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: [
5384
5331
  displayedItems.map((itemValue) => /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "text-xs px-2 py-0.5 gap-1", children: [
@@ -5412,7 +5359,7 @@ var MultiSelectInput = ({ placeholder = "Select items...", value = [], onChange,
5412
5359
  ] });
5413
5360
  };
5414
5361
  var layoutVariants = cva("flex items-start", { variants: { layout: { column: "flex-col gap-4", row: "flex-row gap-7" } }, defaultVariants: { layout: "row" } });
5415
- var RadioGroupInput = ({ value, onChange, className = "", variant = "default", status = "default", bordered = false, 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) => {
5362
+ 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) => {
5416
5363
  const itemValue = typeof item === "string" ? item : item.value;
5417
5364
  const itemLabel = typeof item === "string" ? item : item.label;
5418
5365
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center space-y-0", children: [
@@ -5420,7 +5367,7 @@ var RadioGroupInput = ({ value, onChange, className = "", variant = "default", s
5420
5367
  /* @__PURE__ */ jsx(Label, { className: "text-sm font-normal peer-disabled:opacity-70 ml-1", children: itemLabel })
5421
5368
  ] }, itemValue);
5422
5369
  }) }) });
5423
- var CheckboxInput = ({ value, onChange, helper, label, checkboxClassName, className, variant = "default", status = "default", bordered = false, borderColor }) => /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("flex gap-2 items-center", className), children: [
5370
+ 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: [
5424
5371
  /* @__PURE__ */ jsx(Checkbox, { checked: value, onCheckedChange: onChange, className: cn("cursor-pointer transition-colors duration-200 border-primary", checkboxClassName) }),
5425
5372
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
5426
5373
  /* @__PURE__ */ jsx(Label, { className: "cursor-pointer text-muted-foreground", onClick: () => onChange(!value), children: label }),
@@ -5444,7 +5391,8 @@ function CheckboxGroupInput({
5444
5391
  className,
5445
5392
  variant = "default",
5446
5393
  status = "default",
5447
- bordered = false,
5394
+ bordered,
5395
+ borderDegree,
5448
5396
  borderColor,
5449
5397
  disabled = false
5450
5398
  }) {
@@ -5452,7 +5400,7 @@ function CheckboxGroupInput({
5452
5400
  const next = checked ? [...value, itemValue] : value.filter((v) => v !== itemValue);
5453
5401
  onChange(next);
5454
5402
  };
5455
- 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) => {
5403
+ 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) => {
5456
5404
  const itemValue = typeof item === "string" ? item : item.value;
5457
5405
  const itemLabel = typeof item === "string" ? item : item.label;
5458
5406
  const checked = value.includes(itemValue);
@@ -5469,7 +5417,7 @@ function CheckboxGroupInput({
5469
5417
  ] }, itemValue);
5470
5418
  }) }) });
5471
5419
  }
5472
- var SwitchInput = ({ value, onChange, label = "", helper, className = "", variant = "default", status = "default", bordered = false, borderColor, icon, showIcon = true, iconPosition = "label", iconColor }) => /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2 justify-between items-center", className), children: [
5420
+ 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: [
5473
5421
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
5474
5422
  /* @__PURE__ */ jsxs(Label, { className: "flex items-center gap-2", children: [
5475
5423
  iconPosition === "label" && icon && showIcon && /* @__PURE__ */ jsx("span", { className: "w-4 h-4", children: resolveIcon(icon) }),
@@ -5482,10 +5430,10 @@ var SwitchInput = ({ value, onChange, label = "", helper, className = "", varian
5482
5430
  /* @__PURE__ */ jsx(Switch, { checked: value, onCheckedChange: onChange })
5483
5431
  ] })
5484
5432
  ] });
5485
- var DateInput = ({ value, onChange, placeholder = "Pick a date", className = "", icon, showIcon = true, iconColor, variant = "default", status = "default", bordered = false, borderColor }) => {
5433
+ var DateInput = ({ value, onChange, placeholder = "Pick a date", className = "", icon, showIcon = true, iconColor, variant = "default", status = "default", bordered, borderDegree, borderColor }) => {
5486
5434
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5487
5435
  const toDateString = (date) => date?.toISOString().split("T")[0];
5488
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className, children: [
5436
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderDegree, borderColor, className, children: [
5489
5437
  /* @__PURE__ */ jsxs(Popover, { children: [
5490
5438
  /* @__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 }) }) }),
5491
5439
  /* @__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" }) })
@@ -5500,7 +5448,7 @@ function truncateFilename(filename, maxLength = 25) {
5500
5448
  const name = extIndex !== -1 ? filename.slice(0, extIndex) : filename;
5501
5449
  return `${name.slice(0, maxLength - ext.length - 3)}...${ext}`;
5502
5450
  }
5503
- var FileInput = ({ value, onChange, placeholder = "No file chosen", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered = false, borderColor }) => {
5451
+ var FileInput = ({ value, onChange, placeholder = "No file chosen", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor }) => {
5504
5452
  const fileInputRef = useRef(null);
5505
5453
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5506
5454
  const displayFilename = () => {
@@ -5508,7 +5456,7 @@ var FileInput = ({ value, onChange, placeholder = "No file chosen", icon, showIc
5508
5456
  const filename = typeof value === "string" ? value.split(/[\\/]/).pop() || "" : value.name;
5509
5457
  return truncateFilename(filename);
5510
5458
  };
5511
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("flex px-0 p-0 text-muted-foreground", className), onClick: () => fileInputRef.current?.click(), children: [
5459
+ 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: [
5512
5460
  /* @__PURE__ */ jsx("input", { type: "file", ref: fileInputRef, onChange: (e) => onChange(e.target.files?.[0] || null), className: "hidden" }),
5513
5461
  /* @__PURE__ */ jsxs("div", { className: "bg-muted flex h-full items-center px-3", children: [
5514
5462
  showIcon && (icon ? /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }) : /* @__PURE__ */ jsx(FileUp, { className: cn(iconProps.className) })),
@@ -5517,6 +5465,195 @@ var FileInput = ({ value, onChange, placeholder = "No file chosen", icon, showIc
5517
5465
  /* @__PURE__ */ jsx(Label, { className: "ml-2 flex-1", children: displayFilename() || /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: placeholder }) })
5518
5466
  ] });
5519
5467
  };
5468
+ function formatBytes2(bytes) {
5469
+ if (!bytes && bytes !== 0) return "";
5470
+ if (bytes < 1024) return `${bytes} B`;
5471
+ if (bytes < 1024 ** 2) return `${(bytes / 1024).toFixed(0)} KB`;
5472
+ if (bytes < 1024 ** 3) return `${(bytes / 1024 ** 2).toFixed(1)} MB`;
5473
+ return `${(bytes / 1024 ** 3).toFixed(2)} GB`;
5474
+ }
5475
+ function NUploader({
5476
+ title = "Upload Files",
5477
+ subtitle,
5478
+ accept,
5479
+ multiple = true,
5480
+ disabled = false,
5481
+ items = [],
5482
+ listTitle = "Uploaded files",
5483
+ className,
5484
+ dropzoneClassName,
5485
+ borderDegree,
5486
+ onFilesSelected,
5487
+ onCancel,
5488
+ onRemove
5489
+ }) {
5490
+ const inputRef = useRef(null);
5491
+ const [isDragging, setIsDragging] = useState(false);
5492
+ const resolvedBorderDegree = useResolvedBorderDegree({
5493
+ borderDegree,
5494
+ fallback: "default"
5495
+ });
5496
+ const dropzoneBorderClass = borderColorClassForDegree(resolvedBorderDegree);
5497
+ const emit = useCallback(
5498
+ (files) => {
5499
+ if (!files || disabled) return;
5500
+ const arr = Array.from(files);
5501
+ if (arr.length) onFilesSelected?.(arr);
5502
+ },
5503
+ [disabled, onFilesSelected]
5504
+ );
5505
+ const onDragOver = (e) => {
5506
+ e.preventDefault();
5507
+ if (!disabled) setIsDragging(true);
5508
+ };
5509
+ const onDragLeave = (e) => {
5510
+ e.preventDefault();
5511
+ setIsDragging(false);
5512
+ };
5513
+ const onDrop = (e) => {
5514
+ e.preventDefault();
5515
+ setIsDragging(false);
5516
+ emit(e.dataTransfer.files);
5517
+ };
5518
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
5519
+ (title || subtitle) && /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
5520
+ title && /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold uppercase tracking-wide text-foreground", children: title }),
5521
+ subtitle && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: subtitle })
5522
+ ] }),
5523
+ /* @__PURE__ */ jsxs(
5524
+ "div",
5525
+ {
5526
+ role: "button",
5527
+ tabIndex: disabled ? -1 : 0,
5528
+ "aria-disabled": disabled,
5529
+ onClick: () => !disabled && inputRef.current?.click(),
5530
+ onKeyDown: (e) => {
5531
+ if (!disabled && (e.key === "Enter" || e.key === " ")) {
5532
+ e.preventDefault();
5533
+ inputRef.current?.click();
5534
+ }
5535
+ },
5536
+ onDragOver,
5537
+ onDragLeave,
5538
+ onDrop,
5539
+ className: cn(
5540
+ "flex flex-col items-center justify-center gap-3 rounded-2xl border-2 border-dashed px-6 py-10 text-center transition-colors",
5541
+ dropzoneBorderClass,
5542
+ "bg-muted/40 hover:bg-muted/60",
5543
+ isDragging && "border-primary bg-primary/5",
5544
+ disabled && "cursor-not-allowed opacity-60",
5545
+ !disabled && "cursor-pointer",
5546
+ dropzoneClassName
5547
+ ),
5548
+ children: [
5549
+ /* @__PURE__ */ jsx(
5550
+ "input",
5551
+ {
5552
+ ref: inputRef,
5553
+ type: "file",
5554
+ accept,
5555
+ multiple,
5556
+ className: "hidden",
5557
+ onChange: (e) => {
5558
+ emit(e.target.files);
5559
+ e.target.value = "";
5560
+ }
5561
+ }
5562
+ ),
5563
+ /* @__PURE__ */ jsx("div", { className: "flex h-14 w-14 items-center justify-center rounded-full bg-primary/10 text-primary", children: /* @__PURE__ */ jsx(UploadCloud, { className: "h-7 w-7" }) }),
5564
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Drag & Drop your files here" }),
5565
+ /* @__PURE__ */ jsx("p", { className: "text-xs uppercase tracking-wider text-muted-foreground/70", children: "or" }),
5566
+ /* @__PURE__ */ jsx(
5567
+ Button,
5568
+ {
5569
+ type: "button",
5570
+ size: "sm",
5571
+ disabled,
5572
+ onClick: (e) => {
5573
+ e.stopPropagation();
5574
+ inputRef.current?.click();
5575
+ },
5576
+ children: "Browse Files"
5577
+ }
5578
+ )
5579
+ ]
5580
+ }
5581
+ ),
5582
+ items.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
5583
+ listTitle && /* @__PURE__ */ jsx("p", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: listTitle }),
5584
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2", children: items.map((item) => /* @__PURE__ */ jsx(
5585
+ UploaderRow,
5586
+ {
5587
+ item,
5588
+ onCancel,
5589
+ onRemove
5590
+ },
5591
+ item.id
5592
+ )) })
5593
+ ] })
5594
+ ] });
5595
+ }
5596
+ function UploaderRow({ item, onCancel, onRemove }) {
5597
+ const status = item.status ?? "uploading";
5598
+ const progress = Math.max(0, Math.min(100, item.progress ?? 0));
5599
+ const isDone = status === "done";
5600
+ const isError = status === "error";
5601
+ return /* @__PURE__ */ jsxs(
5602
+ "li",
5603
+ {
5604
+ className: cn(
5605
+ "flex items-center gap-3 rounded-xl border bg-card px-3 py-2.5 shadow-sm",
5606
+ isError ? "border-destructive/30" : "border-border"
5607
+ ),
5608
+ children: [
5609
+ /* @__PURE__ */ jsx(
5610
+ NFileTypeIcon,
5611
+ {
5612
+ mimeType: item.mimeType,
5613
+ fileName: item.name,
5614
+ size: "md"
5615
+ }
5616
+ ),
5617
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
5618
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
5619
+ /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium text-foreground", children: item.name }),
5620
+ /* @__PURE__ */ jsx(
5621
+ "span",
5622
+ {
5623
+ className: cn(
5624
+ "shrink-0 text-xs tabular-nums",
5625
+ isError ? "text-destructive" : "text-muted-foreground"
5626
+ ),
5627
+ children: isDone ? formatBytes2(item.size) : isError ? "Failed" : `${Math.round(progress)}%`
5628
+ }
5629
+ )
5630
+ ] }),
5631
+ !isDone && !isError && /* @__PURE__ */ jsx(Progress, { value: progress, className: "h-1.5" }),
5632
+ isError && item.error && /* @__PURE__ */ jsx("span", { className: "text-xs text-destructive", children: item.error })
5633
+ ] }),
5634
+ /* @__PURE__ */ jsx("div", { className: "shrink-0", children: isDone ? /* @__PURE__ */ jsx(CheckCircle2, { className: "h-5 w-5 text-emerald-500" }) : isError ? /* @__PURE__ */ jsx(
5635
+ "button",
5636
+ {
5637
+ type: "button",
5638
+ "aria-label": "Remove",
5639
+ onClick: () => onRemove?.(item.id),
5640
+ className: "rounded-full p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
5641
+ children: /* @__PURE__ */ jsx(AlertCircle, { className: "h-5 w-5 text-destructive" })
5642
+ }
5643
+ ) : /* @__PURE__ */ jsx(
5644
+ "button",
5645
+ {
5646
+ type: "button",
5647
+ "aria-label": "Cancel upload",
5648
+ onClick: () => onCancel?.(item.id),
5649
+ className: "rounded-full p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
5650
+ children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
5651
+ }
5652
+ ) })
5653
+ ]
5654
+ }
5655
+ );
5656
+ }
5520
5657
  var IMAGE_SIZE_MAP = {
5521
5658
  sm: "w-16 h-16",
5522
5659
  md: "w-24 h-24",
@@ -5637,14 +5774,14 @@ function ImageInput({
5637
5774
  renderFileInput()
5638
5775
  ] });
5639
5776
  }
5640
- var StarRatingInput = ({ value, onChange, maxStars = 5, className = "", variant = "default", status = "default", bordered = false, borderColor }) => {
5777
+ var StarRatingInput = ({ value, onChange, maxStars = 5, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor }) => {
5641
5778
  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));
5642
- return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), children: stars });
5779
+ return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-2", className), children: stars });
5643
5780
  };
5644
5781
  var DEFAULT_COLORS = ["#222222", "#e11d48", "#ea580c", "#16a34a", "#db2777", "#2563eb", "#9333ea", "#eab308"];
5645
- var ColorArrayInput = ({ value, onChange, className = "", variant = "default", status = "default", bordered = false, borderColor, colors = DEFAULT_COLORS }) => {
5782
+ var ColorArrayInput = ({ value, onChange, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, colors = DEFAULT_COLORS }) => {
5646
5783
  const [selectedColor, setSelectedColor] = useState(value || "");
5647
- 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: () => {
5784
+ 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: () => {
5648
5785
  setSelectedColor(color);
5649
5786
  onChange(color);
5650
5787
  }, 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)) });
@@ -5678,7 +5815,8 @@ function ColorPickerInput({
5678
5815
  className,
5679
5816
  variant = "default",
5680
5817
  status = "default",
5681
- bordered = false,
5818
+ bordered,
5819
+ borderDegree,
5682
5820
  borderColor,
5683
5821
  disabled = false
5684
5822
  }) {
@@ -5689,6 +5827,7 @@ function ColorPickerInput({
5689
5827
  variant,
5690
5828
  status,
5691
5829
  bordered,
5830
+ borderDegree,
5692
5831
  borderColor,
5693
5832
  className: cn("flex-col gap-3 items-start p-3", className),
5694
5833
  disabled,
@@ -5776,7 +5915,8 @@ function EmojiInput({
5776
5915
  className,
5777
5916
  variant = "default",
5778
5917
  status = "default",
5779
- bordered = false,
5918
+ bordered,
5919
+ borderDegree,
5780
5920
  borderColor,
5781
5921
  disabled = false
5782
5922
  }) {
@@ -5786,6 +5926,7 @@ function EmojiInput({
5786
5926
  variant,
5787
5927
  status,
5788
5928
  bordered,
5929
+ borderDegree,
5789
5930
  borderColor,
5790
5931
  className: cn("gap-3 flex-wrap", className),
5791
5932
  disabled,
@@ -5856,7 +5997,8 @@ function PhoneInput({
5856
5997
  className,
5857
5998
  variant = "default",
5858
5999
  status = "default",
5859
- bordered = false,
6000
+ bordered,
6001
+ borderDegree,
5860
6002
  borderColor
5861
6003
  }) {
5862
6004
  const phoneThemeVars = {
@@ -5881,7 +6023,7 @@ function PhoneInput({
5881
6023
  "--react-international-phone-dropdown-preferred-list-divider-color": "hsl(var(--najm-border))",
5882
6024
  "--react-international-phone-dropdown-shadow": "0 16px 40px hsl(var(--najm-background) / 0.45)"
5883
6025
  };
5884
- return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-0 overflow-visible p-0!", className), disabled, children: /* @__PURE__ */ jsx(
6026
+ return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderDegree, borderColor, className: cn("gap-0 overflow-visible p-0!", className), disabled, children: /* @__PURE__ */ jsx(
5885
6027
  PhoneInput$1,
5886
6028
  {
5887
6029
  className: "w-full",
@@ -5931,6 +6073,7 @@ function PhoneInput({
5931
6073
  style: {
5932
6074
  zIndex: 60,
5933
6075
  width: "min(300px, calc(100vw - 32px))",
6076
+ backgroundColor: "hsl(var(--najm-popover))",
5934
6077
  border: "1px solid hsl(var(--najm-border))",
5935
6078
  borderRadius: "8px",
5936
6079
  overflowX: "hidden"
@@ -5941,7 +6084,7 @@ function PhoneInput({
5941
6084
  }
5942
6085
  ) });
5943
6086
  }
5944
- var TimeInput = ({ value = "", onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered = false, borderColor, format24 = true, showSeconds = false, disabled = false }) => {
6087
+ var TimeInput = ({ value = "", onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderDegree, borderColor, format24 = true, showSeconds = false, disabled = false }) => {
5945
6088
  const [inputValue, setInputValue] = useState(value);
5946
6089
  const [isValid, setIsValid] = useState(true);
5947
6090
  useEffect(() => {
@@ -5989,7 +6132,7 @@ var TimeInput = ({ value = "", onChange, placeholder = "", icon, showIcon = true
5989
6132
  };
5990
6133
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5991
6134
  const currentStatus = !isValid ? "error" : status;
5992
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status: currentStatus, bordered, borderColor, className: cn("gap-2", className), children: [
6135
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status: currentStatus, bordered, borderDegree, borderColor, className: cn("gap-2", className), children: [
5993
6136
  showIcon && (icon ? /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }) : /* @__PURE__ */ jsx(Clock, { className: iconProps.className, style: iconProps.style })),
5994
6137
  /* @__PURE__ */ jsx(Input, { type: "text", placeholder: placeholder || (showSeconds ? "HH:MM:SS" : "HH:MM"), value: inputValue, onChange: (e) => handleInputChange(e.target.value), onKeyDown: (e) => {
5995
6138
  if (!/\d/.test(e.key) && !["Backspace", "Delete", "ArrowLeft", "ArrowRight", "Tab"].includes(e.key)) e.preventDefault();
@@ -6074,8 +6217,8 @@ function NSlider({
6074
6217
  return Array.isArray(v) ? [...v] : [v];
6075
6218
  };
6076
6219
  const initialRadix = toRadix(controlledValue ?? defaultValue);
6077
- const [internalValues, setInternalValues] = React38.useState(initialRadix);
6078
- const [active, setActive] = React38.useState(null);
6220
+ const [internalValues, setInternalValues] = React.useState(initialRadix);
6221
+ const [active, setActive] = React.useState(null);
6079
6222
  const currentValues = controlledValue !== void 0 ? toRadix(controlledValue) : internalValues;
6080
6223
  const handleRadix = (arr) => {
6081
6224
  setInternalValues(arr);
@@ -6265,19 +6408,19 @@ function Combobox({
6265
6408
  allowFreeText = false,
6266
6409
  disabled = false
6267
6410
  }) {
6268
- const [open, setOpen] = React38.useState(false);
6269
- const [query, setQuery] = React38.useState("");
6270
- const [highlight, setHighlight] = React38.useState(0);
6271
- const wrapperRef = React38.useRef(null);
6272
- const inputRef = React38.useRef(null);
6273
- const filtered = React38.useMemo(() => {
6411
+ const [open, setOpen] = React.useState(false);
6412
+ const [query, setQuery] = React.useState("");
6413
+ const [highlight, setHighlight] = React.useState(0);
6414
+ const wrapperRef = React.useRef(null);
6415
+ const inputRef = React.useRef(null);
6416
+ const filtered = React.useMemo(() => {
6274
6417
  const q = query.trim().toLowerCase();
6275
6418
  if (!q) return options;
6276
6419
  return options.filter(
6277
6420
  (opt) => opt.label.toLowerCase().includes(q) || opt.value.toLowerCase().includes(q)
6278
6421
  );
6279
6422
  }, [options, query]);
6280
- React38.useEffect(() => {
6423
+ React.useEffect(() => {
6281
6424
  if (!open) return;
6282
6425
  const onClick = (e) => {
6283
6426
  if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
@@ -6288,7 +6431,7 @@ function Combobox({
6288
6431
  document.addEventListener("mousedown", onClick);
6289
6432
  return () => document.removeEventListener("mousedown", onClick);
6290
6433
  }, [open]);
6291
- React38.useEffect(() => {
6434
+ React.useEffect(() => {
6292
6435
  if (open) {
6293
6436
  setHighlight(0);
6294
6437
  requestAnimationFrame(() => inputRef.current?.focus());
@@ -6296,7 +6439,7 @@ function Combobox({
6296
6439
  setQuery("");
6297
6440
  }
6298
6441
  }, [open]);
6299
- const selectedLabel = React38.useMemo(() => {
6442
+ const selectedLabel = React.useMemo(() => {
6300
6443
  const match = options.find((o) => o.value === value);
6301
6444
  return match?.label ?? value;
6302
6445
  }, [options, value]);
@@ -6358,7 +6501,7 @@ function Combobox({
6358
6501
  ]
6359
6502
  }
6360
6503
  ),
6361
- open && /* @__PURE__ */ jsxs("div", { className: "absolute z-50 mt-1 w-full rounded-md border border-border bg-card shadow-lg", children: [
6504
+ open && /* @__PURE__ */ jsxs("div", { className: "absolute z-[10000] mt-1 w-full rounded-md border border-border bg-card shadow-lg", children: [
6362
6505
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2", children: [
6363
6506
  /* @__PURE__ */ jsx(Search, { className: "h-3.5 w-3.5 text-muted-foreground" }),
6364
6507
  /* @__PURE__ */ jsx(
@@ -6417,12 +6560,13 @@ var VARIANT_PRESETS = {
6417
6560
  error: "text-xs"
6418
6561
  }
6419
6562
  };
6420
- var VariantContext = createContext({ variant: "default", bordered: false });
6421
- var VariantProvider = ({ variant = "default", bordered = false, children }) => /* @__PURE__ */ jsx(VariantContext.Provider, { value: { variant, bordered }, children });
6563
+ var VariantContext = createContext({ variant: "default" });
6564
+ var VariantProvider = ({ variant = "default", bordered, borderDegree, children }) => /* @__PURE__ */ jsx(VariantContext.Provider, { value: { variant, bordered, borderDegree }, children });
6422
6565
  var useVariant = () => useContext(VariantContext).variant;
6423
6566
  var useBordered = () => useContext(VariantContext).bordered;
6567
+ var useBorderDegree = () => useContext(VariantContext).borderDegree;
6424
6568
  var useVariantPreset = () => VARIANT_PRESETS[useContext(VariantContext).variant];
6425
- function NFormInner({ schema, defaultValues, onSubmit, form: externalForm, variant = "default", bordered = false, as = "form", className = "", id, devTools, children }) {
6569
+ function NFormInner({ schema, defaultValues, onSubmit, form: externalForm, variant = "default", bordered, borderDegree, as = "form", className = "", id, devTools, children }) {
6426
6570
  const resolver = useMemo(() => schema ? zodResolver(schema) : void 0, [schema]);
6427
6571
  const internalForm = useForm({
6428
6572
  resolver,
@@ -6452,9 +6596,9 @@ function NFormInner({ schema, defaultValues, onSubmit, form: externalForm, varia
6452
6596
  console.log("Form errors:", form.formState.errors);
6453
6597
  }
6454
6598
  }, [form.formState.errors]);
6455
- const wrapperClass = cn("flex flex-col h-full w-full gap-2", className);
6599
+ const wrapperClass = cn("flex flex-col h-full w-full gap-4", className);
6456
6600
  const submit = form.handleSubmit(onSubmit);
6457
- 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) => {
6601
+ 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) => {
6458
6602
  if (e.key === "Enter" && e.target.tagName !== "TEXTAREA") {
6459
6603
  e.preventDefault();
6460
6604
  void submit();
@@ -6517,6 +6661,7 @@ var FormInput = ({ name, type, formLabel, formDescription, required = false, dis
6517
6661
  const prefix = usePrefix();
6518
6662
  const preset = useVariantPreset();
6519
6663
  const contextBordered = useBordered();
6664
+ const contextBorderDegree = useBorderDegree();
6520
6665
  const fieldName = prefix ? `${prefix}.${name}` : name;
6521
6666
  if (!InputComponent) return null;
6522
6667
  const getDefaultValue = () => {
@@ -6547,7 +6692,7 @@ var FormInput = ({ name, type, formLabel, formDescription, required = false, dis
6547
6692
  formLabel,
6548
6693
  required && !disabled && !readOnly && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
6549
6694
  ] }),
6550
- /* @__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 }) }),
6695
+ /* @__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 }) }),
6551
6696
  !hasError && !disabled && !readOnly && formDescription && /* @__PURE__ */ jsx(FormDescription, { className: slot.description, children: formDescription }),
6552
6697
  !isHidden && /* @__PURE__ */ jsx(FormMessage, { className: slot.error })
6553
6698
  ] });
@@ -6877,7 +7022,8 @@ function WizardForm({
6877
7022
  previousLabel = "Previous",
6878
7023
  submitLabel = "Submit",
6879
7024
  variant = "default",
6880
- bordered = false,
7025
+ bordered,
7026
+ borderDegree,
6881
7027
  className,
6882
7028
  classNames,
6883
7029
  footerSlot
@@ -6937,7 +7083,7 @@ function WizardForm({
6937
7083
  classNames
6938
7084
  }
6939
7085
  ),
6940
- /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsx(VariantProvider, { variant, bordered, children: /* @__PURE__ */ jsxs(
7086
+ /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsx(VariantProvider, { variant, bordered, borderDegree, children: /* @__PURE__ */ jsxs(
6941
7087
  "form",
6942
7088
  {
6943
7089
  id: `step-${currentStepConfig.id}`,
@@ -6971,12 +7117,18 @@ var handler = {
6971
7117
  }
6972
7118
  };
6973
7119
  useTableStore.use = new Proxy({}, handler);
6974
- var actionButtonClass = (bordered, danger) => cn(
7120
+ var actionButtonClass = (bordered, danger, borderClass) => cn(
6975
7121
  "flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition-colors",
6976
7122
  danger ? "hover:bg-red-500/10 hover:text-red-400" : "hover:bg-muted hover:text-foreground",
6977
- bordered && "border border-muted-foreground"
7123
+ bordered && `border ${borderClass ?? "border-muted-foreground"}`
6978
7124
  );
6979
- function TableActionCell({ row, onView, onEdit, onDelete, openRowMenu, menuButton, bordered }) {
7125
+ function TableActionCell({ row, onView, onEdit, onDelete, openRowMenu, menuButton, bordered, borderDegree }) {
7126
+ const resolvedBorderDegree = useResolvedBorderDegree({
7127
+ borderDegree,
7128
+ bordered,
7129
+ fallback: "default"
7130
+ });
7131
+ const borderClass = borderColorClassForDegree(resolvedBorderDegree);
6980
7132
  if (menuButton && openRowMenu) {
6981
7133
  return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center gap-1", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(
6982
7134
  "button",
@@ -6999,7 +7151,7 @@ function TableActionCell({ row, onView, onEdit, onDelete, openRowMenu, menuButto
6999
7151
  type: "button",
7000
7152
  "aria-label": "View",
7001
7153
  onClick: () => onView(row.original),
7002
- className: actionButtonClass(bordered),
7154
+ className: actionButtonClass(bordered, false, borderClass),
7003
7155
  children: /* @__PURE__ */ jsx(Eye, { className: "h-3.5 w-3.5" })
7004
7156
  }
7005
7157
  ),
@@ -7009,7 +7161,7 @@ function TableActionCell({ row, onView, onEdit, onDelete, openRowMenu, menuButto
7009
7161
  type: "button",
7010
7162
  "aria-label": "Edit",
7011
7163
  onClick: () => onEdit(row.original),
7012
- className: actionButtonClass(bordered),
7164
+ className: actionButtonClass(bordered, false, borderClass),
7013
7165
  children: /* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" })
7014
7166
  }
7015
7167
  ),
@@ -7019,7 +7171,7 @@ function TableActionCell({ row, onView, onEdit, onDelete, openRowMenu, menuButto
7019
7171
  type: "button",
7020
7172
  "aria-label": "Delete",
7021
7173
  onClick: () => onDelete(row.original),
7022
- className: actionButtonClass(bordered, true),
7174
+ className: actionButtonClass(bordered, true, borderClass),
7023
7175
  children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" })
7024
7176
  }
7025
7177
  )
@@ -7094,7 +7246,8 @@ var createTableStore = () => {
7094
7246
  CardComponent: null,
7095
7247
  className: "",
7096
7248
  classNames: {},
7097
- bordered: false,
7249
+ bordered: void 0,
7250
+ borderDegree: void 0,
7098
7251
  headerClassName: "bg-card",
7099
7252
  headerColor: "primary",
7100
7253
  showCheckbox: true,
@@ -7348,6 +7501,7 @@ function useTable() {
7348
7501
  const openRowMenu = useTableStore.use.openRowMenu();
7349
7502
  const menuButton = useTableStore.use.menuButton();
7350
7503
  const bordered = useTableStore.use.bordered();
7504
+ const borderDegree = useTableStore.use.borderDegree();
7351
7505
  const CardComponent = useTableStore.use.CardComponent();
7352
7506
  const dynamicHeight = useTableStore.use.dynamicHeight();
7353
7507
  const viewMode = useTableStore.use.viewMode();
@@ -7377,15 +7531,15 @@ function useTable() {
7377
7531
  ...effectiveColumns,
7378
7532
  {
7379
7533
  id: "actions",
7380
- header: () => isMenuActions ? null : React38__default.createElement("div", { className: "flex w-full justify-start text-left" }, "Actions"),
7381
- cell: ({ row }) => React38__default.createElement(TableActionCell, { row, onView, onEdit, onDelete, openRowMenu, menuButton, bordered }),
7534
+ header: () => isMenuActions ? null : React__default.createElement("div", { className: "flex w-full justify-start text-left" }, "Actions"),
7535
+ cell: ({ row }) => React__default.createElement(TableActionCell, { row, onView, onEdit, onDelete, openRowMenu, menuButton, bordered, borderDegree }),
7382
7536
  enableSorting: false,
7383
7537
  enableHiding: false
7384
7538
  }
7385
7539
  ];
7386
7540
  }
7387
7541
  return effectiveColumns;
7388
- }, [columns, CardComponent, hasActions, onView, onEdit, onDelete, openRowMenu, menuButton, bordered]);
7542
+ }, [columns, CardComponent, hasActions, onView, onEdit, onDelete, openRowMenu, menuButton, bordered, borderDegree]);
7389
7543
  const notifyStateChange = useCallback((state) => {
7390
7544
  onStateChange?.(state);
7391
7545
  }, [onStateChange]);
@@ -7532,10 +7686,10 @@ function EditableCell({ cell, onCellEdit }) {
7532
7686
  const columnId = cell.column.id;
7533
7687
  const editor = meta.editor || "text";
7534
7688
  const initial = cell.getValue();
7535
- const [editing, setEditing] = React38__default.useState(false);
7536
- const [value, setValue] = React38__default.useState(initial);
7537
- const [saving, setSaving] = React38__default.useState(false);
7538
- React38__default.useEffect(() => {
7689
+ const [editing, setEditing] = React__default.useState(false);
7690
+ const [value, setValue] = React__default.useState(initial);
7691
+ const [saving, setSaving] = React__default.useState(false);
7692
+ React__default.useEffect(() => {
7539
7693
  if (!editing) setValue(initial);
7540
7694
  }, [initial, editing]);
7541
7695
  const commit = async (next) => {
@@ -7596,6 +7750,15 @@ function NTableContent({ effectiveMode }) {
7596
7750
  const showContent = useTableStore.use.showContent();
7597
7751
  const classNames = useTableStore.use.classNames();
7598
7752
  const bordered = useTableStore.use.bordered();
7753
+ const borderDegree = useTableStore.use.borderDegree();
7754
+ const resolvedBorderDegree = useResolvedBorderDegree({
7755
+ borderDegree,
7756
+ bordered,
7757
+ fallback: "default"
7758
+ });
7759
+ const tableBorderClass = borderColorClassForDegree(resolvedBorderDegree);
7760
+ const isStrong = resolvedBorderDegree === "strong";
7761
+ const useDegreeBorder = bordered || borderDegree || resolvedBorderDegree !== "default";
7599
7762
  const showCheckbox = useTableStore.use.showCheckbox();
7600
7763
  const selectedRowId = useTableStore.use.selectedRowId();
7601
7764
  const renderSubRow = useTableStore.use.renderSubRow();
@@ -7618,100 +7781,124 @@ function NTableContent({ effectiveMode }) {
7618
7781
  if (dir === "desc") return /* @__PURE__ */ jsx(ArrowDown, { className: "h-4 w-4" });
7619
7782
  return /* @__PURE__ */ jsx(ArrowUpDown, { className: "h-4 w-4 opacity-50" });
7620
7783
  };
7621
- return /* @__PURE__ */ jsx(NajmScroll, { axis: "both", className: cn("min-h-0 flex-1 overflow-hidden rounded-md bg-card", bordered ? "border border-muted-foreground" : "shadow-sm", classNames?.content), onContextMenu: handleBackgroundContextMenu, children: /* @__PURE__ */ jsxs(Table, { children: [
7622
- /* @__PURE__ */ jsx(TableHeader, { "data-ntable-table-header": true, className: cn("bg-card sticky top-0 z-10", colorStyle?.text, headerClassName, bordered && "[&_tr]:border-muted-foreground", classNames?.tableHeader), children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsxs(TableRow, { className: cn("hover:bg-transparent", bordered && "border-muted-foreground"), children: [
7623
- showCheckbox && /* @__PURE__ */ jsx(TableHead, { className: cn("w-10 text-foreground h-12", colorStyle?.bg), children: /* @__PURE__ */ jsx(
7624
- Checkbox,
7625
- {
7626
- "aria-label": "Select all rows",
7627
- checked: table.getIsAllPageRowsSelected(),
7628
- onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value)
7629
- }
7630
- ) }),
7631
- hasExpansion && /* @__PURE__ */ jsx(TableHead, { "aria-label": "Expand column", className: cn("w-10 text-foreground h-12", colorStyle?.bg) }),
7632
- hg.headers.map((header) => /* @__PURE__ */ jsx(TableHead, { className: cn("text-foreground h-12", colorStyle?.bg), children: header.isPlaceholder ? null : /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", header.column.getCanSort() && showSorting && "cursor-pointer select-none"), onClick: header.column.getToggleSortingHandler(), children: [
7633
- flexRender(header.column.columnDef.header, header.getContext()),
7634
- header.column.getCanSort() && showSorting && /* @__PURE__ */ jsx("span", { children: getSortIcon(header.column) })
7635
- ] }) }, header.id))
7636
- ] }, hg.id)) }),
7637
- /* @__PURE__ */ jsx(TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => {
7638
- const isSelectedByRowId = Boolean(selectedRowId && row.original?.id === selectedRowId);
7639
- const canExpand = hasExpansion && row.getCanExpand();
7640
- const isExpanded = canExpand && row.getIsExpanded();
7641
- const totalCols = row.getVisibleCells().length + (showCheckbox ? 1 : 0) + (hasExpansion ? 1 : 0);
7642
- return /* @__PURE__ */ jsxs(React38__default.Fragment, { children: [
7643
- /* @__PURE__ */ jsxs(
7644
- TableRow,
7645
- {
7646
- "data-row": "true",
7647
- "data-row-id": row.id,
7648
- "data-state": row.getIsSelected() && "selected",
7649
- "data-selected-row": isSelectedByRowId ? "true" : void 0,
7650
- onClick: () => onRowClick?.(row.original),
7651
- onContextMenu: onRowContextMenu ? (e) => {
7652
- e.nativeEvent[ROW_CONTEXT_HANDLED] = true;
7653
- onRowContextMenu(e, row.original);
7654
- } : void 0,
7655
- className: cn(colorStyle?.row, classNames?.row, onRowClick && "cursor-pointer", isSelectedByRowId && "bg-brand/5 hover:bg-brand/5", bordered && "border-border"),
7656
- children: [
7657
- showCheckbox && /* @__PURE__ */ jsx(TableCell, { className: "h-14 w-10", children: /* @__PURE__ */ jsx(
7658
- Checkbox,
7659
- {
7660
- "aria-label": `Select row ${row.id}`,
7661
- checked: row.getIsSelected(),
7662
- onClick: (e) => e.stopPropagation(),
7663
- onCheckedChange: (value) => row.toggleSelected(!!value)
7664
- }
7665
- ) }),
7666
- hasExpansion && /* @__PURE__ */ jsx(TableCell, { className: "h-14 w-10", children: canExpand ? /* @__PURE__ */ jsx(
7667
- "button",
7668
- {
7669
- type: "button",
7670
- "aria-label": `${isExpanded ? "Collapse" : "Expand"} row ${row.id}`,
7671
- "aria-expanded": isExpanded,
7672
- onClick: (e) => {
7673
- e.stopPropagation();
7674
- row.toggleExpanded();
7675
- },
7676
- className: cn(
7677
- "flex h-6 w-6 items-center justify-center rounded hover:bg-muted",
7678
- bordered && "border border-muted-foreground"
7679
- ),
7680
- children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
7681
- }
7682
- ) : null }),
7683
- row.getVisibleCells().map((cell) => {
7684
- const columnDef = cell.column.columnDef;
7685
- const meta = columnDef.meta || {};
7686
- const isEditable = Boolean(onCellEdit) && Boolean(meta.editable);
7687
- return /* @__PURE__ */ jsx(TableCell, { className: "h-14", children: isEditable ? /* @__PURE__ */ jsx(EditableCell, { cell, onCellEdit }) : flexRender(columnDef.cell, cell.getContext()) }, cell.id);
7688
- })
7689
- ]
7690
- }
7691
- ),
7692
- isExpanded && renderSubRow && /* @__PURE__ */ jsx(TableRow, { "data-expanded-row": "true", className: "bg-muted/40 hover:bg-muted/40", children: /* @__PURE__ */ jsx(TableCell, { colSpan: totalCols, className: "p-0", children: renderSubRow(row.original) }) })
7693
- ] }, row.id);
7694
- }) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length + (showCheckbox ? 1 : 0) + (hasExpansion ? 1 : 0), className: "h-16 text-center", children: noResultsText }) }) })
7695
- ] }) });
7784
+ return /* @__PURE__ */ jsx(
7785
+ NajmScroll,
7786
+ {
7787
+ axis: "both",
7788
+ "data-border-degree": resolvedBorderDegree,
7789
+ className: cn(
7790
+ "min-h-0 flex-1 overflow-hidden rounded-md bg-card",
7791
+ useDegreeBorder ? `border ${tableBorderClass}` : "shadow-sm",
7792
+ isStrong && "shadow-none",
7793
+ classNames?.content
7794
+ ),
7795
+ onContextMenu: handleBackgroundContextMenu,
7796
+ children: /* @__PURE__ */ jsxs(Table, { children: [
7797
+ /* @__PURE__ */ jsx(TableHeader, { "data-ntable-table-header": true, className: cn("bg-card sticky top-0 z-10", colorStyle?.text, headerClassName, bordered && "[&_tr]:border-border", classNames?.tableHeader), children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsxs(TableRow, { className: cn("hover:bg-transparent", bordered && "border-border"), children: [
7798
+ showCheckbox && /* @__PURE__ */ jsx(TableHead, { className: cn("w-10 text-foreground h-12", colorStyle?.bg), children: /* @__PURE__ */ jsx(
7799
+ Checkbox,
7800
+ {
7801
+ "aria-label": "Select all rows",
7802
+ checked: table.getIsAllPageRowsSelected(),
7803
+ onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value)
7804
+ }
7805
+ ) }),
7806
+ hasExpansion && /* @__PURE__ */ jsx(TableHead, { "aria-label": "Expand column", className: cn("w-10 text-foreground h-12", colorStyle?.bg) }),
7807
+ hg.headers.map((header) => /* @__PURE__ */ jsx(TableHead, { className: cn("text-foreground h-12", colorStyle?.bg), children: header.isPlaceholder ? null : /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", header.column.getCanSort() && showSorting && "cursor-pointer select-none"), onClick: header.column.getToggleSortingHandler(), children: [
7808
+ flexRender(header.column.columnDef.header, header.getContext()),
7809
+ header.column.getCanSort() && showSorting && /* @__PURE__ */ jsx("span", { children: getSortIcon(header.column) })
7810
+ ] }) }, header.id))
7811
+ ] }, hg.id)) }),
7812
+ /* @__PURE__ */ jsx(TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => {
7813
+ const isSelectedByRowId = Boolean(selectedRowId && row.original?.id === selectedRowId);
7814
+ const canExpand = hasExpansion && row.getCanExpand();
7815
+ const isExpanded = canExpand && row.getIsExpanded();
7816
+ const totalCols = row.getVisibleCells().length + (showCheckbox ? 1 : 0) + (hasExpansion ? 1 : 0);
7817
+ return /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
7818
+ /* @__PURE__ */ jsxs(
7819
+ TableRow,
7820
+ {
7821
+ "data-row": "true",
7822
+ "data-row-id": row.id,
7823
+ "data-state": row.getIsSelected() && "selected",
7824
+ "data-selected-row": isSelectedByRowId ? "true" : void 0,
7825
+ onClick: () => onRowClick?.(row.original),
7826
+ onContextMenu: onRowContextMenu ? (e) => {
7827
+ e.nativeEvent[ROW_CONTEXT_HANDLED] = true;
7828
+ onRowContextMenu(e, row.original);
7829
+ } : void 0,
7830
+ className: cn(colorStyle?.row, classNames?.row, onRowClick && "cursor-pointer", isSelectedByRowId && "bg-brand/5 hover:bg-brand/5", bordered && "border-border"),
7831
+ children: [
7832
+ showCheckbox && /* @__PURE__ */ jsx(TableCell, { className: "h-14 w-10", children: /* @__PURE__ */ jsx(
7833
+ Checkbox,
7834
+ {
7835
+ "aria-label": `Select row ${row.id}`,
7836
+ checked: row.getIsSelected(),
7837
+ onClick: (e) => e.stopPropagation(),
7838
+ onCheckedChange: (value) => row.toggleSelected(!!value)
7839
+ }
7840
+ ) }),
7841
+ hasExpansion && /* @__PURE__ */ jsx(TableCell, { className: "h-14 w-10", children: canExpand ? /* @__PURE__ */ jsx(
7842
+ "button",
7843
+ {
7844
+ type: "button",
7845
+ "aria-label": `${isExpanded ? "Collapse" : "Expand"} row ${row.id}`,
7846
+ "aria-expanded": isExpanded,
7847
+ onClick: (e) => {
7848
+ e.stopPropagation();
7849
+ row.toggleExpanded();
7850
+ },
7851
+ className: cn(
7852
+ "flex h-6 w-6 items-center justify-center rounded hover:bg-muted",
7853
+ bordered && `border ${tableBorderClass}`
7854
+ ),
7855
+ children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
7856
+ }
7857
+ ) : null }),
7858
+ row.getVisibleCells().map((cell) => {
7859
+ const columnDef = cell.column.columnDef;
7860
+ const meta = columnDef.meta || {};
7861
+ const isEditable = Boolean(onCellEdit) && Boolean(meta.editable);
7862
+ return /* @__PURE__ */ jsx(TableCell, { className: "h-14", children: isEditable ? /* @__PURE__ */ jsx(EditableCell, { cell, onCellEdit }) : flexRender(columnDef.cell, cell.getContext()) }, cell.id);
7863
+ })
7864
+ ]
7865
+ }
7866
+ ),
7867
+ isExpanded && renderSubRow && /* @__PURE__ */ jsx(TableRow, { "data-expanded-row": "true", className: "bg-muted/40 hover:bg-muted/40", children: /* @__PURE__ */ jsx(TableCell, { colSpan: totalCols, className: "p-0", children: renderSubRow(row.original) }) })
7868
+ ] }, row.id);
7869
+ }) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length + (showCheckbox ? 1 : 0) + (hasExpansion ? 1 : 0), className: "h-16 text-center", children: noResultsText }) }) })
7870
+ ] })
7871
+ }
7872
+ );
7696
7873
  }
7697
- function NDataCardShell({ row, onClick, onContextMenu, actions, children, className, showCheckbox = true, selectedRowId, openRowMenu, menuButton, bordered = false }) {
7874
+ function NDataCardShell({ row, onClick, onContextMenu, actions, children, className, showCheckbox = true, selectedRowId, openRowMenu, menuButton, bordered, borderDegree }) {
7698
7875
  const canExpand = row.getCanExpand();
7699
7876
  const isExpanded = canExpand && row.getIsExpanded();
7700
7877
  const isSelected = row.getIsSelected();
7701
7878
  const isHighlighted = selectedRowId != null && row.original?.id === selectedRowId;
7702
7879
  const isActive = isSelected || isHighlighted;
7703
7880
  const useMenuButton = menuButton && openRowMenu;
7881
+ const resolvedBorderDegree = useResolvedBorderDegree({
7882
+ borderDegree,
7883
+ bordered,
7884
+ fallback: "default"
7885
+ });
7886
+ const isStrong = resolvedBorderDegree === "strong";
7887
+ const isNone = resolvedBorderDegree === "none";
7888
+ const borderClass = borderColorClassForDegree(resolvedBorderDegree);
7704
7889
  return /* @__PURE__ */ jsxs(
7705
7890
  "div",
7706
7891
  {
7707
7892
  "data-row": "true",
7708
7893
  "data-row-id": row.id,
7894
+ "data-border-degree": resolvedBorderDegree,
7709
7895
  onClick,
7710
7896
  onContextMenu,
7711
7897
  className: cn(
7712
7898
  "relative group w-full rounded-lg bg-card",
7713
- bordered ? "border border-muted-foreground" : "shadow-sm",
7714
- isActive && (bordered ? "border-primary" : "ring-2 ring-primary ring-offset-1 ring-offset-background"),
7899
+ isNone ? "border-transparent" : `border ${borderClass}`,
7900
+ isStrong && "shadow-none",
7901
+ isActive && (bordered || resolvedBorderDegree !== "default" || borderDegree ? "border-primary" : "ring-2 ring-primary ring-offset-1 ring-offset-background"),
7715
7902
  onClick && "cursor-pointer",
7716
7903
  className
7717
7904
  ),
@@ -7806,7 +7993,7 @@ function NDataCardShell({ row, onClick, onContextMenu, actions, children, classN
7806
7993
  },
7807
7994
  className: cn(
7808
7995
  "absolute bottom-2 right-2 z-10 flex h-6 w-6 items-center justify-center rounded hover:bg-muted",
7809
- bordered && "border border-muted-foreground"
7996
+ bordered && `border ${borderClass}`
7810
7997
  ),
7811
7998
  children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
7812
7999
  }
@@ -7843,6 +8030,7 @@ function NTableCards({ effectiveMode }) {
7843
8030
  const showContent = useTableStore.use.showContent();
7844
8031
  const classNames = useTableStore.use.classNames();
7845
8032
  const bordered = useTableStore.use.bordered();
8033
+ const borderDegree = useTableStore.use.borderDegree();
7846
8034
  const renderSubRow = useTableStore.use.renderSubRow();
7847
8035
  const userGetRowCanExpand = useTableStore.use.getRowCanExpand();
7848
8036
  const handleContainerContextMenu = useCallback((e) => {
@@ -7945,6 +8133,7 @@ function NTableCards({ effectiveMode }) {
7945
8133
  openRowMenu,
7946
8134
  menuButton,
7947
8135
  bordered,
8136
+ borderDegree,
7948
8137
  children: /* @__PURE__ */ jsx(
7949
8138
  CardComponent,
7950
8139
  {
@@ -7975,6 +8164,13 @@ function NTablePagination() {
7975
8164
  const setPagination = useTableStore.use.setPagination();
7976
8165
  const isPaginationControlled = useTableStore.use.isPaginationControlled();
7977
8166
  const bordered = useTableStore.use.bordered();
8167
+ const borderDegree = useTableStore.use.borderDegree();
8168
+ const resolvedBorderDegree = useResolvedBorderDegree({
8169
+ borderDegree,
8170
+ bordered,
8171
+ fallback: "default"
8172
+ });
8173
+ const triggerBorderClass = borderColorClassForDegree(resolvedBorderDegree);
7978
8174
  if (!table || !showContent || !showPagination || viewMode === "json" || viewMode === "files") return null;
7979
8175
  const filteredRows = table.getFilteredRowModel().rows;
7980
8176
  const selectedRows = table.getFilteredSelectedRowModel().rows;
@@ -8009,7 +8205,7 @@ function NTablePagination() {
8009
8205
  (!isPaginationControlled || manualPagination) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8010
8206
  /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Rows/page" }),
8011
8207
  /* @__PURE__ */ jsxs(Select, { value: `${pageSize}`, onValueChange: handlePageSizeChange, children: [
8012
- /* @__PURE__ */ jsx(SelectTrigger, { className: cn("h-8 w-[80px]", bordered && "border-muted-foreground"), children: /* @__PURE__ */ jsx(SelectValue, { placeholder: pageSize }) }),
8208
+ /* @__PURE__ */ jsx(SelectTrigger, { className: cn("h-8 w-[80px]", bordered && triggerBorderClass), children: /* @__PURE__ */ jsx(SelectValue, { placeholder: pageSize }) }),
8013
8209
  /* @__PURE__ */ jsx(SelectContent, { side: "top", children: currentPageSizeOptions.map((size) => /* @__PURE__ */ jsx(SelectItem, { value: `${size}`, children: size }, size)) })
8014
8210
  ] })
8015
8211
  ] }),
@@ -8037,25 +8233,28 @@ function NTablePagination() {
8037
8233
  function SearchFilter({ placeholder }) {
8038
8234
  const table = useTableStore.use.table();
8039
8235
  const bordered = useTableStore.use.bordered();
8236
+ const borderDegree = useTableStore.use.borderDegree();
8040
8237
  if (!table) return null;
8041
8238
  const value = table.getState().globalFilter ?? "";
8042
- return /* @__PURE__ */ jsx(TextInput, { icon: Search, value, onChange: (v) => table.setGlobalFilter(v), placeholder: placeholder ?? "Search\u2026", bordered });
8239
+ return /* @__PURE__ */ jsx(TextInput, { icon: Search, value, onChange: (v) => table.setGlobalFilter(v), placeholder: placeholder ?? "Search\u2026", bordered, borderDegree });
8043
8240
  }
8044
8241
  function TextFilter({ name, placeholder }) {
8045
8242
  const table = useTableStore.use.table();
8046
8243
  const bordered = useTableStore.use.bordered();
8244
+ const borderDegree = useTableStore.use.borderDegree();
8047
8245
  const column = table?.getColumn?.(name);
8048
8246
  if (!column) return null;
8049
- return /* @__PURE__ */ jsx(TextInput, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value), placeholder, bordered });
8247
+ return /* @__PURE__ */ jsx(TextInput, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value), placeholder, bordered, borderDegree });
8050
8248
  }
8051
8249
  function SelectFilter({ name, options, placeholder, inputType }) {
8052
8250
  const table = useTableStore.use.table();
8053
8251
  const bordered = useTableStore.use.bordered();
8252
+ const borderDegree = useTableStore.use.borderDegree();
8054
8253
  const column = table?.getColumn?.(name);
8055
8254
  if (!column) return null;
8056
8255
  const allOptions = [{ value: "__clear__", label: "All" }, ...options.map((o) => typeof o === "string" ? { value: o, label: o } : o)];
8057
8256
  const InputComponent = inputType === "combobox" ? ComboboxInput : SelectInput;
8058
- return /* @__PURE__ */ jsx(InputComponent, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value === "" || value === "__clear__" ? void 0 : value), items: allOptions, placeholder: placeholder || "Filter...", bordered });
8257
+ return /* @__PURE__ */ jsx(InputComponent, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value === "" || value === "__clear__" ? void 0 : value), items: allOptions, placeholder: placeholder || "Filter...", bordered, borderDegree });
8059
8258
  }
8060
8259
  function defaultWrapperClass(filter) {
8061
8260
  return filter.type === "search" ? "flex-1 min-w-[160px] max-w-sm" : "w-full sm:w-40 shrink-0";
@@ -8063,6 +8262,7 @@ function defaultWrapperClass(filter) {
8063
8262
  function RenderFilter({ filter }) {
8064
8263
  const table = useTableStore.use.table();
8065
8264
  const bordered = useTableStore.use.bordered();
8265
+ const borderDegree = useTableStore.use.borderDegree();
8066
8266
  if (filter.type === "search") {
8067
8267
  return /* @__PURE__ */ jsx(SearchFilter, { placeholder: filter.placeholder });
8068
8268
  }
@@ -8074,6 +8274,7 @@ function RenderFilter({ filter }) {
8074
8274
  onChange: filter.onChange,
8075
8275
  placeholder: filter.placeholder,
8076
8276
  bordered,
8277
+ borderDegree,
8077
8278
  className: "w-full"
8078
8279
  }
8079
8280
  );
@@ -8087,6 +8288,7 @@ function RenderFilter({ filter }) {
8087
8288
  onChange: filter.onChange,
8088
8289
  placeholder: filter.placeholder,
8089
8290
  bordered,
8291
+ borderDegree,
8090
8292
  className: "w-full"
8091
8293
  }
8092
8294
  );
@@ -8105,6 +8307,7 @@ function RenderFilter({ filter }) {
8105
8307
  showIcon: true,
8106
8308
  disabled: filter.disabled,
8107
8309
  bordered,
8310
+ borderDegree,
8108
8311
  className: "w-full"
8109
8312
  }
8110
8313
  );
@@ -8120,6 +8323,7 @@ function RenderFilter({ filter }) {
8120
8323
  showIcon: true,
8121
8324
  disabled: filter.disabled,
8122
8325
  bordered,
8326
+ borderDegree,
8123
8327
  className: "w-full"
8124
8328
  }
8125
8329
  );
@@ -8148,6 +8352,12 @@ function TableAddButton() {
8148
8352
  const addButtonText = useTableStore.use.addButtonText();
8149
8353
  const headerColor = useTableStore.use.headerColor();
8150
8354
  const bordered = useTableStore.use.bordered();
8355
+ const borderDegree = useTableStore.use.borderDegree();
8356
+ const resolvedBorderDegree = useResolvedBorderDegree({
8357
+ borderDegree,
8358
+ bordered,
8359
+ fallback: "default"
8360
+ });
8151
8361
  if (!showAddButton) return null;
8152
8362
  const accentHex = headerColor ? HEADER_HEX[headerColor] : void 0;
8153
8363
  const btnStyle = accentHex ? { backgroundColor: accentHex } : void 0;
@@ -8161,6 +8371,7 @@ function TableAddButton() {
8161
8371
  style: btnStyle,
8162
8372
  "aria-label": addButtonText || "Create",
8163
8373
  title: addButtonText || "Create",
8374
+ "data-border-degree": bordered ? resolvedBorderDegree : void 0,
8164
8375
  className: `h-10 w-10 shrink-0 cursor-pointer flex items-center justify-center rounded-lg text-white transition-opacity ${baseCls} ${borderedCls}`,
8165
8376
  children: /* @__PURE__ */ jsx(Plus, { className: "h-5 w-5" })
8166
8377
  }
@@ -8177,6 +8388,7 @@ function TableSettingsMenu() {
8177
8388
  const cardComponent = useTableStore.use.CardComponent();
8178
8389
  const table = useTableStore.use.table();
8179
8390
  const bordered = useTableStore.use.bordered();
8391
+ const borderDegree = useTableStore.use.borderDegree();
8180
8392
  if (!showViewToggle && !showColumnVisibility) return null;
8181
8393
  const allModes = ["table", "cards", "json", "files"];
8182
8394
  const filteredModes = availableModes ?? allModes;
@@ -8195,7 +8407,7 @@ function TableSettingsMenu() {
8195
8407
  const hasModes = modeItems.length > 0;
8196
8408
  const hasColumns = columns.length > 0;
8197
8409
  return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
8198
- /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(BaseInput, { className: "w-auto cursor-pointer px-3", onClick: (e) => e.preventDefault(), bordered, children: /* @__PURE__ */ jsx(SlidersHorizontal, { className: "h-4 w-4 shrink-0 text-muted-foreground" }) }) }),
8410
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(BaseInput, { className: "w-auto cursor-pointer px-3", onClick: (e) => e.preventDefault(), bordered, borderDegree, children: /* @__PURE__ */ jsx(SlidersHorizontal, { className: "h-4 w-4 shrink-0 text-muted-foreground" }) }) }),
8199
8411
  /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-56 bg-card", children: [
8200
8412
  showViewToggle && hasModes && /* @__PURE__ */ jsxs(Fragment, { children: [
8201
8413
  /* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "flex items-center gap-2", children: [
@@ -8521,7 +8733,8 @@ function NTable(props) {
8521
8733
  CardComponent: props.renderCard ?? null,
8522
8734
  className: props.className ?? "",
8523
8735
  classNames: props.classNames ?? {},
8524
- bordered: props.bordered ?? false,
8736
+ bordered: props.bordered,
8737
+ borderDegree: props.borderDegree,
8525
8738
  headerClassName: props.headerClassName ?? "bg-card",
8526
8739
  headerColor: props.headerColor ?? "primary",
8527
8740
  showCheckbox: props.showCheckbox ?? true,
@@ -8956,7 +9169,11 @@ function NSmartPasteDialog({
8956
9169
  }
8957
9170
  function NSidebarHeader({ children, collapsed, className, classNames }) {
8958
9171
  if (!children) return null;
8959
- return /* @__PURE__ */ jsx("div", { className: cn("flex items-center h-14 min-h-14 px-4 border-b border-border/70 shrink-0 justify-between gap-2", classNames?.sidebarHeader, className), children: /* @__PURE__ */ jsx("div", { className: "min-w-0", children }) });
9172
+ return /* @__PURE__ */ jsx("div", { className: cn(
9173
+ "flex items-center h-14 min-h-14 px-4 border-b border-border/70 shrink-0 gap-2 justify-start",
9174
+ classNames?.sidebarHeader,
9175
+ className
9176
+ ), children });
8960
9177
  }
8961
9178
  function NSidebarLogo({
8962
9179
  icon,
@@ -8966,19 +9183,27 @@ function NSidebarLogo({
8966
9183
  collapsed = false
8967
9184
  }) {
8968
9185
  if (!icon && !title && !subtitle) return null;
8969
- const IconNode = typeof icon === "function" || typeof icon === "object" && icon !== null && "$$typeof" in icon ? React38__default.createElement(icon, { className: "h-5 w-5 text-primary" }) : icon;
9186
+ 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;
9187
+ const collapsedCenter = collapsed ? { marginLeft: "calc(var(--rail, 4rem) / 2 - 2.25rem)" } : void 0;
8970
9188
  return /* @__PURE__ */ jsxs(
8971
9189
  "button",
8972
9190
  {
8973
9191
  type: "button",
8974
9192
  onClick,
8975
9193
  className: cn(
8976
- "flex items-center gap-2.5 min-w-0 text-left",
9194
+ "flex items-center gap-2.5 text-left",
8977
9195
  onClick && "cursor-pointer hover:opacity-80 transition-opacity"
8978
9196
  ),
8979
9197
  children: [
8980
- IconNode && /* @__PURE__ */ jsx("div", { className: "size-9 rounded-lg bg-primary/10 flex items-center justify-center shrink-0", children: IconNode }),
8981
- !collapsed && (title || subtitle) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-0", children: [
9198
+ IconNode && /* @__PURE__ */ jsx(
9199
+ "div",
9200
+ {
9201
+ className: "size-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0",
9202
+ style: collapsedCenter,
9203
+ children: IconNode
9204
+ }
9205
+ ),
9206
+ !collapsed && (title || subtitle) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col ", children: [
8982
9207
  title && /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-foreground leading-tight truncate", children: title }),
8983
9208
  subtitle && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground leading-tight truncate", children: subtitle })
8984
9209
  ] })
@@ -9015,6 +9240,7 @@ function NSidebarItem({
9015
9240
  const baseClasses = cn(
9016
9241
  "flex items-center gap-3 w-full rounded-md text-sm px-2 font-medium transition-colors h-8 text-left",
9017
9242
  depth > 0 && "pl-7",
9243
+ collapsed && "pl-[calc(var(--rail,4rem)/2_-_1.5rem)]",
9018
9244
  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",
9019
9245
  classNames?.sidebarItem
9020
9246
  );
@@ -9226,9 +9452,18 @@ function NSidebarMobile({
9226
9452
  hamburgerClassName,
9227
9453
  showHamburgerButton = true,
9228
9454
  children,
9229
- bordered = false
9455
+ bordered,
9456
+ borderDegree
9230
9457
  }) {
9231
9458
  const mobileClass = mobileBreakpoint === "sm" ? "sm:hidden" : mobileBreakpoint === "lg" ? "lg:hidden" : "md:hidden";
9459
+ const resolvedBorderDegree = useResolvedBorderDegree({
9460
+ borderDegree,
9461
+ bordered,
9462
+ fallback: "default"
9463
+ });
9464
+ const isStrong = resolvedBorderDegree === "strong";
9465
+ const isNone = resolvedBorderDegree === "none";
9466
+ const mobileBorderClass = isNone ? "border-transparent" : borderColorClassForDegree(resolvedBorderDegree);
9232
9467
  return /* @__PURE__ */ jsxs(Fragment, { children: [
9233
9468
  showHamburgerButton && /* @__PURE__ */ jsx(
9234
9469
  "button",
@@ -9256,9 +9491,11 @@ function NSidebarMobile({
9256
9491
  /* @__PURE__ */ jsxs(
9257
9492
  "aside",
9258
9493
  {
9494
+ "data-border-degree": resolvedBorderDegree,
9259
9495
  className: cn(
9260
9496
  "fixed inset-y-0 left-0 z-50 bg-card flex flex-col transition-transform duration-200",
9261
- bordered ? "border border-muted-foreground shadow-none" : "border-r",
9497
+ // When global strong is on, we want a strong border, not a soft `border-r` edge.
9498
+ isStrong ? `border ${mobileBorderClass} shadow-none` : isNone ? "border-transparent" : `border-r ${mobileBorderClass}`,
9262
9499
  mobileClass,
9263
9500
  open ? "translate-x-0" : "-translate-x-full"
9264
9501
  ),
@@ -9305,10 +9542,12 @@ function NSidebar({
9305
9542
  defaultCollapsed = false,
9306
9543
  onCollapsedChange,
9307
9544
  showCollapseButton = true,
9545
+ collapseButtonPosition = "footer",
9308
9546
  showSectionLabels = true,
9309
9547
  showSectionIcons = true,
9310
9548
  showSectionSeparators = false,
9311
- bordered = false,
9549
+ bordered,
9550
+ borderDegree,
9312
9551
  footer,
9313
9552
  className,
9314
9553
  classNames,
@@ -9352,10 +9591,20 @@ function NSidebar({
9352
9591
  if (closeOnNavigate) setMobileOpen(false);
9353
9592
  }, [onNavigate, closeOnNavigate]);
9354
9593
  const groups = useMemo(() => buildGroups(navItems), [navItems]);
9594
+ const resolvedBorderDegree = useResolvedBorderDegree({
9595
+ borderDegree,
9596
+ bordered,
9597
+ fallback: "default"
9598
+ });
9599
+ const sidebarShellBorderClass = borderColorClassForDegree(resolvedBorderDegree);
9600
+ const isStrong = resolvedBorderDegree === "strong";
9601
+ const isNone = resolvedBorderDegree === "none";
9355
9602
  const desktopClass = mobileBreakpoint === "sm" ? "hidden sm:flex" : mobileBreakpoint === "lg" ? "hidden lg:flex" : "hidden md:flex";
9356
9603
  const expandedWidth = widths?.expanded ?? 240;
9357
9604
  const collapsedWidth = widths?.collapsed ?? 64;
9358
9605
  const mobileWidth = widths?.mobile ?? expandedWidth;
9606
+ const railVar = typeof collapsedWidth === "number" ? `${collapsedWidth}px` : collapsedWidth;
9607
+ const showEdgeCollapse = showCollapseButton && collapseButtonPosition === "edge";
9359
9608
  const defaultLogoContent = logoIcon || logoTitle || logoSubtitle ? /* @__PURE__ */ jsx(NSidebarLogo, { icon: logoIcon, title: logoTitle, subtitle: logoSubtitle, onClick: onLogoClick, collapsed }) : null;
9360
9609
  const headerContent = logo ?? defaultLogoContent;
9361
9610
  const contentProps = {
@@ -9376,7 +9625,7 @@ function NSidebar({
9376
9625
  settingsLabel,
9377
9626
  onLogout,
9378
9627
  logoutLabel,
9379
- showCollapseButton,
9628
+ showCollapseButton: showCollapseButton && collapseButtonPosition === "footer",
9380
9629
  collapsed,
9381
9630
  onToggleCollapsed: handleToggleCollapsed,
9382
9631
  collapseLabel,
@@ -9407,21 +9656,37 @@ function NSidebar({
9407
9656
  hamburgerClassName,
9408
9657
  showHamburgerButton,
9409
9658
  bordered,
9659
+ borderDegree,
9410
9660
  children: mobileInner
9411
9661
  }
9412
9662
  ),
9413
- /* @__PURE__ */ jsx(
9663
+ /* @__PURE__ */ jsxs(
9414
9664
  "aside",
9415
9665
  {
9666
+ "data-border-degree": resolvedBorderDegree,
9416
9667
  className: cn(
9417
9668
  desktopClass,
9418
- "flex flex-col h-full bg-card transition-all duration-200",
9419
- bordered && "border border-muted-foreground shadow-none",
9669
+ "relative z-10 flex flex-col h-full bg-card transition-all duration-200",
9670
+ isNone ? "border-r border-transparent" : cn("border-r", sidebarShellBorderClass),
9671
+ isStrong && "shadow-none",
9420
9672
  classNames?.sidebar,
9421
9673
  className
9422
9674
  ),
9423
- style: { width: collapsed ? collapsedWidth : expandedWidth },
9424
- children: sidebarInner
9675
+ style: { width: collapsed ? collapsedWidth : expandedWidth, ["--rail"]: railVar },
9676
+ children: [
9677
+ sidebarInner,
9678
+ showEdgeCollapse && /* @__PURE__ */ jsx(
9679
+ "button",
9680
+ {
9681
+ type: "button",
9682
+ onClick: handleToggleCollapsed,
9683
+ "aria-label": collapsed ? expandLabel : collapseLabel,
9684
+ title: collapsed ? expandLabel : collapseLabel,
9685
+ 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",
9686
+ children: collapsed ? /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(ChevronLeft, { className: "h-3.5 w-3.5" })
9687
+ }
9688
+ )
9689
+ ]
9425
9690
  }
9426
9691
  )
9427
9692
  ] });
@@ -9492,7 +9757,7 @@ function NNavbar({
9492
9757
  (userMenuActions.length > 0 || onLogout) && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
9493
9758
  userMenuActions.map((action) => {
9494
9759
  const ActionIcon = action.icon;
9495
- return /* @__PURE__ */ jsxs(React38__default.Fragment, { children: [
9760
+ return /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
9496
9761
  action.separator && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
9497
9762
  /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: action.onClick, className: "cursor-pointer", children: [
9498
9763
  ActionIcon && /* @__PURE__ */ jsx(ActionIcon, { className: "h-4 w-4 mr-2" }),
@@ -9658,13 +9923,13 @@ function NPageHeaderTop({ children, className }) {
9658
9923
  }
9659
9924
  NPageHeaderTop.displayName = "NPageHeaderTop";
9660
9925
  function isPageHeaderSlot(child, slot) {
9661
- return React38__default.isValidElement(child) && child.type === slot;
9926
+ return React__default.isValidElement(child) && child.type === slot;
9662
9927
  }
9663
9928
  function getSlotElements(children, slot) {
9664
- const matches = React38__default.Children.toArray(children).filter((child) => isPageHeaderSlot(child, slot));
9929
+ const matches = React__default.Children.toArray(children).filter((child) => isPageHeaderSlot(child, slot));
9665
9930
  return matches.length > 0 ? matches : void 0;
9666
9931
  }
9667
- function NPageHeader({ icon: Icon2, title, subtitle, actions, filters, top, search, children, className, headerClassName, bordered = false }) {
9932
+ function NPageHeader({ icon: Icon2, title, subtitle, actions, filters, top, search, children, className, headerClassName, bordered, borderDegree }) {
9668
9933
  const [internalSearch, setInternalSearch] = useState("");
9669
9934
  const searchValue = search?.value ?? internalSearch;
9670
9935
  const handleSearchChange = useCallback((e) => {
@@ -9677,13 +9942,21 @@ function NPageHeader({ icon: Icon2, title, subtitle, actions, filters, top, sear
9677
9942
  const resolvedActions = slottedActions ?? actions;
9678
9943
  const resolvedFilters = slottedFilters ?? filters;
9679
9944
  const resolvedTop = slottedTop ?? top;
9945
+ const resolvedBorderDegree = useResolvedBorderDegree({
9946
+ borderDegree,
9947
+ bordered,
9948
+ fallback: "default"
9949
+ });
9950
+ const hasBorderShell = bordered || Boolean(borderDegree) || resolvedBorderDegree !== "default";
9951
+ const isStrong = resolvedBorderDegree === "strong";
9680
9952
  return /* @__PURE__ */ jsxs(
9681
9953
  "div",
9682
9954
  {
9683
9955
  "data-slot": "page-header",
9956
+ "data-border-degree": hasBorderShell ? resolvedBorderDegree : void 0,
9684
9957
  className: cn(
9685
- "border-b border-border",
9686
- bordered && "rounded-xl border border-muted-foreground bg-card shadow-none",
9958
+ hasBorderShell ? cn("border rounded-xl bg-card shadow-none", borderColorClassForDegree(resolvedBorderDegree)) : "border-b border-border",
9959
+ isStrong && "shadow-none",
9687
9960
  className
9688
9961
  ),
9689
9962
  children: [
@@ -9746,4 +10019,4 @@ function NInspectorSheet({ open, onClose, title, children }) {
9746
10019
  ] }) });
9747
10020
  }
9748
10021
 
9749
- 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, buildDefaultFileColumns, buttonVariants, cn, composePreset, createDialogStore, createTableStore, dialogVariants, formatFileBytes, formatFileRelative, getIconColorProps, indicatorVariants, resolvePreset, resolveSlot, sliderVariants, swapVariants, toggleVariants, tooltipContentVariants, truncateByCharacters, useClickOutside, useContextMenu, useDebouncedValue, useDelayedLoading, useDialog, useDialogStore, useDynamicPageSize, useFormField, useFormSubmission, useInfiniteScroll, useKeyboard, useLocalStorageState, useNForm, useNPortalScope, usePrefix, useSelection, useStepNavigation, useStorageContextMenu, useStoreSync, useTable, useTableKeyboard, useTableStore, useVariant, useVariantPreset };
10022
+ 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 };