najm-kit 0.0.7 → 0.0.8

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,14 +1,15 @@
1
- import * as React32 from 'react';
2
- import React32__default, { createContext, useContext, useCallback, useEffect, useState, useRef, useMemo, useLayoutEffect } from 'react';
1
+ import * as React38 from 'react';
2
+ import React38__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, ChevronsLeft, ChevronLeft, ChevronsRight, MoreVertical, Edit, Merge, PanelLeftOpen, PanelLeftClose, Menu, LogOut, Image, ArrowUp, ArrowDown, LoaderPinwheelIcon, LoaderIcon, ArrowUpRight, ArrowDownRight, List, Settings, 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, 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';
7
7
  import { cva } from 'class-variance-authority';
8
8
  import { clsx } from 'clsx';
9
9
  import { twMerge } from 'tailwind-merge';
10
10
  import * as LabelPrimitive from '@radix-ui/react-label';
11
11
  import * as SheetPrimitive from '@radix-ui/react-dialog';
12
+ import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
12
13
  import { create } from 'zustand';
13
14
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
14
15
  import * as PopoverPrimitive from '@radix-ui/react-popover';
@@ -30,6 +31,7 @@ import { FormProvider, Controller, useFormContext, useForm, useFieldArray } from
30
31
  import { defaultStyles, FileIcon } from 'react-file-icon';
31
32
  import { format } from 'date-fns';
32
33
  import { PhoneInput as PhoneInput$1, defaultCountries } from 'react-international-phone';
34
+ import * as SliderPrimitive from '@radix-ui/react-slider';
33
35
  import { zodResolver } from '@hookform/resolvers/zod';
34
36
  import { getExpandedRowModel, getSortedRowModel, getPaginationRowModel, getFilteredRowModel, getCoreRowModel, useReactTable, flexRender } from '@tanstack/react-table';
35
37
 
@@ -122,9 +124,20 @@ var accents = {
122
124
  };
123
125
 
124
126
  // src/theme/presets/compose.ts
127
+ function lightAccentFromPrimary(primary = "") {
128
+ const parts = primary.trim().split(/\s+/);
129
+ if (parts.length < 2) return { accent: "0 0% 94%", "accent-foreground": "0 0% 30%" };
130
+ const [h, s] = parts;
131
+ return { accent: `${h} ${s} 93%`, "accent-foreground": `${h} ${s} 35%` };
132
+ }
125
133
  function composePreset(mode, accent) {
126
134
  const base = mode === "dark" ? darkMode : lightMode;
127
- return { ...base, ...accents[accent] };
135
+ const accentTokens = accents[accent];
136
+ if (mode === "light") {
137
+ const { accent: _a, "accent-foreground": _af, ...brandTokens } = accentTokens;
138
+ return { ...base, ...brandTokens, ...lightAccentFromPrimary(brandTokens.primary) };
139
+ }
140
+ return { ...base, ...accentTokens };
128
141
  }
129
142
  var PRESET_MAP = {
130
143
  light: { mode: "light", accent: "neutral" },
@@ -149,7 +162,8 @@ function tokensToStyle(tokens, accentOnly) {
149
162
  }
150
163
  return style;
151
164
  }
152
- var NajmThemeDepthContext = React32.createContext(0);
165
+ var NajmThemeDepthContext = React38.createContext(0);
166
+ var NajmThemeContainerCtx = React38.createContext(null);
153
167
  function NajmThemeProvider({
154
168
  preset,
155
169
  mode,
@@ -160,24 +174,56 @@ function NajmThemeProvider({
160
174
  asChild,
161
175
  children
162
176
  }) {
163
- const depth = React32.useContext(NajmThemeDepthContext);
177
+ const depth = React38.useContext(NajmThemeDepthContext);
164
178
  const isRoot = depth === 0;
165
- const resolved = React32.useMemo(() => {
179
+ const resolved = React38.useMemo(() => {
166
180
  if (tokens) return tokens;
167
181
  if (preset) return resolvePreset(preset);
168
182
  if (mode) return composePreset(mode, accent ?? "neutral");
169
183
  return resolvePreset("light");
170
184
  }, [preset, mode, accent, tokens]);
171
- const style = React32.useMemo(() => tokensToStyle(resolved, accentOnly), [resolved, accentOnly]);
185
+ const style = React38.useMemo(() => tokensToStyle(resolved, accentOnly), [resolved, accentOnly]);
172
186
  const Comp = asChild ? Slot : "div";
173
- React32.useEffect(() => {
187
+ const [container, setContainer] = React38.useState(null);
188
+ React38.useEffect(() => {
174
189
  if (!isRoot) return;
175
190
  const root = document.documentElement;
176
191
  const entries = Object.entries(style);
177
192
  entries.forEach(([k, v]) => root.style.setProperty(k, v));
178
193
  return () => entries.forEach(([k]) => root.style.removeProperty(k));
179
194
  }, [style, isRoot]);
180
- return /* @__PURE__ */ jsx(NajmThemeDepthContext.Provider, { value: depth + 1, children: /* @__PURE__ */ jsx(Comp, { "data-najm-theme": preset ?? `${mode ?? "light"}-${accent ?? "neutral"}`, className, style, children }) });
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 }) }) });
196
+ }
197
+ var EDITABLE_INPUT_TYPES = /* @__PURE__ */ new Set([
198
+ "text",
199
+ "search",
200
+ "email",
201
+ "password",
202
+ "tel",
203
+ "url",
204
+ "number",
205
+ "date",
206
+ "time",
207
+ "datetime-local",
208
+ "month",
209
+ "week",
210
+ "color"
211
+ ]);
212
+ function isEditableTextField(target) {
213
+ if (!(target instanceof HTMLElement)) return false;
214
+ if (target.isContentEditable) return true;
215
+ if (target.closest('[contenteditable="true"]')) return true;
216
+ if (target.getAttribute("role") === "combobox") return true;
217
+ if (target.closest('[role="combobox"]')) return true;
218
+ const tag = target.tagName;
219
+ if (tag === "TEXTAREA") return true;
220
+ if (tag === "SELECT") return true;
221
+ if (tag === "INPUT") {
222
+ const rawType = target.type;
223
+ const type = (rawType || "text").toLowerCase();
224
+ return EDITABLE_INPUT_TYPES.has(type);
225
+ }
226
+ return false;
181
227
  }
182
228
  function parseShortcut(shortcut) {
183
229
  const parts = shortcut.toLowerCase().split("+").map((s) => s.trim());
@@ -190,16 +236,14 @@ function parseShortcut(shortcut) {
190
236
  };
191
237
  }
192
238
  function useKeyboard(shortcut, handler2, options = {}) {
193
- const { enabled = true, preventDefault = false, ignoreInputs = true } = options;
239
+ const { enabled = true, preventDefault = false, ignoreInputs = true, scopeRef } = options;
194
240
  const callback = useCallback(
195
241
  (e) => {
196
242
  if (!enabled) return;
197
- if (ignoreInputs) {
198
- const target = e.target;
199
- if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT" || target.isContentEditable) {
200
- return;
201
- }
202
- }
243
+ const scope = scopeRef?.current;
244
+ if (scope && !(e.target instanceof Node)) return;
245
+ if (scope && e.target instanceof Node && !scope.contains(e.target)) return;
246
+ if (ignoreInputs && isEditableTextField(e.target)) return;
203
247
  const parsed = parseShortcut(shortcut);
204
248
  const ctrlMatch = parsed.ctrl ? e.ctrlKey || e.metaKey : true;
205
249
  const shiftMatch = parsed.shift ? e.shiftKey : true;
@@ -211,7 +255,7 @@ function useKeyboard(shortcut, handler2, options = {}) {
211
255
  handler2(e);
212
256
  }
213
257
  },
214
- [shortcut, handler2, enabled, preventDefault, ignoreInputs]
258
+ [shortcut, handler2, enabled, preventDefault, ignoreInputs, scopeRef]
215
259
  );
216
260
  useEffect(() => {
217
261
  document.addEventListener("keydown", callback);
@@ -347,9 +391,9 @@ var NIcon = ({
347
391
  height: size,
348
392
  ...style
349
393
  };
350
- if (React32__default.isValidElement(icon)) {
351
- return React32__default.cloneElement(icon, {
352
- className: cn(icon.props.className, className),
394
+ if (React38__default.isValidElement(icon)) {
395
+ return React38__default.cloneElement(icon, {
396
+ className: cn(className, icon.props.className),
353
397
  onClick,
354
398
  ...rest
355
399
  });
@@ -466,7 +510,7 @@ function renderIcon(icon) {
466
510
  if (!icon) return null;
467
511
  return /* @__PURE__ */ jsx(NIcon, { "aria-hidden": "true", icon, className: "shrink-0" });
468
512
  }
469
- var Button = React32.forwardRef(
513
+ var Button = React38.forwardRef(
470
514
  ({
471
515
  className,
472
516
  variant,
@@ -482,16 +526,17 @@ var Button = React32.forwardRef(
482
526
  loaderPosition = "left",
483
527
  leftIcon,
484
528
  rightIcon,
529
+ bordered = false,
485
530
  disabled,
486
531
  children,
487
532
  onClick,
488
533
  ...props
489
534
  }, ref) => {
490
- const [pending, setPending] = React32.useState(false);
535
+ const [pending, setPending] = React38.useState(false);
491
536
  const isLoading = loading || pending;
492
537
  const isDisabled = disabled || disabledWhileLoading && isLoading;
493
538
  const Comp = asChild ? Slot : "button";
494
- const handleClick = React32.useCallback(
539
+ const handleClick = React38.useCallback(
495
540
  (event) => {
496
541
  if (isDisabled) {
497
542
  event.preventDefault();
@@ -523,7 +568,11 @@ var Button = React32.forwardRef(
523
568
  "aria-busy": isLoading || void 0,
524
569
  "aria-disabled": asChild && isDisabled ? true : void 0,
525
570
  disabled: !asChild ? isDisabled : void 0,
526
- className: cn(buttonVariants({ variant, size, rounded, fullWidth, className })),
571
+ className: cn(
572
+ buttonVariants({ variant, size, rounded, fullWidth }),
573
+ bordered && "border border-muted-foreground",
574
+ className
575
+ ),
527
576
  onClick: handleClick,
528
577
  ...props,
529
578
  children: showCenteredLoader ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -693,6 +742,210 @@ function Badge({
693
742
  ] });
694
743
  }
695
744
  var NBadge = Badge;
745
+ var POSITION = {
746
+ "top-start": "top-0 start-0 -translate-x-1/2 -translate-y-1/2 rtl:translate-x-1/2",
747
+ "top-center": "top-0 start-1/2 -translate-x-1/2 -translate-y-1/2",
748
+ "top-end": "top-0 end-0 translate-x-1/2 -translate-y-1/2 rtl:-translate-x-1/2",
749
+ "middle-start": "top-1/2 start-0 -translate-x-1/2 -translate-y-1/2 rtl:translate-x-1/2",
750
+ "middle-center": "top-1/2 start-1/2 -translate-x-1/2 -translate-y-1/2",
751
+ "middle-end": "top-1/2 end-0 translate-x-1/2 -translate-y-1/2 rtl:-translate-x-1/2",
752
+ "bottom-start": "bottom-0 start-0 -translate-x-1/2 translate-y-1/2 rtl:translate-x-1/2",
753
+ "bottom-center": "bottom-0 start-1/2 -translate-x-1/2 translate-y-1/2",
754
+ "bottom-end": "bottom-0 end-0 translate-x-1/2 translate-y-1/2 rtl:-translate-x-1/2"
755
+ };
756
+ var POSITION_SM = {
757
+ "top-start": "sm:top-0 sm:start-0 sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rtl:translate-x-1/2",
758
+ "top-center": "sm:top-0 sm:start-1/2 sm:-translate-x-1/2 sm:-translate-y-1/2",
759
+ "top-end": "sm:top-0 sm:end-0 sm:translate-x-1/2 sm:-translate-y-1/2 sm:rtl:-translate-x-1/2",
760
+ "middle-start": "sm:top-1/2 sm:start-0 sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rtl:translate-x-1/2",
761
+ "middle-center": "sm:top-1/2 sm:start-1/2 sm:-translate-x-1/2 sm:-translate-y-1/2",
762
+ "middle-end": "sm:top-1/2 sm:end-0 sm:translate-x-1/2 sm:-translate-y-1/2 sm:rtl:-translate-x-1/2",
763
+ "bottom-start": "sm:bottom-0 sm:start-0 sm:-translate-x-1/2 sm:translate-y-1/2 sm:rtl:translate-x-1/2",
764
+ "bottom-center": "sm:bottom-0 sm:start-1/2 sm:-translate-x-1/2 sm:translate-y-1/2",
765
+ "bottom-end": "sm:bottom-0 sm:end-0 sm:translate-x-1/2 sm:translate-y-1/2 sm:rtl:-translate-x-1/2"
766
+ };
767
+ var POSITION_MD = {
768
+ "top-start": "md:top-0 md:start-0 md:-translate-x-1/2 md:-translate-y-1/2 md:rtl:translate-x-1/2",
769
+ "top-center": "md:top-0 md:start-1/2 md:-translate-x-1/2 md:-translate-y-1/2",
770
+ "top-end": "md:top-0 md:end-0 md:translate-x-1/2 md:-translate-y-1/2 md:rtl:-translate-x-1/2",
771
+ "middle-start": "md:top-1/2 md:start-0 md:-translate-x-1/2 md:-translate-y-1/2 md:rtl:translate-x-1/2",
772
+ "middle-center": "md:top-1/2 md:start-1/2 md:-translate-x-1/2 md:-translate-y-1/2",
773
+ "middle-end": "md:top-1/2 md:end-0 md:translate-x-1/2 md:-translate-y-1/2 md:rtl:-translate-x-1/2",
774
+ "bottom-start": "md:bottom-0 md:start-0 md:-translate-x-1/2 md:translate-y-1/2 md:rtl:translate-x-1/2",
775
+ "bottom-center": "md:bottom-0 md:start-1/2 md:-translate-x-1/2 md:translate-y-1/2",
776
+ "bottom-end": "md:bottom-0 md:end-0 md:translate-x-1/2 md:translate-y-1/2 md:rtl:-translate-x-1/2"
777
+ };
778
+ var POSITION_LG = {
779
+ "top-start": "lg:top-0 lg:start-0 lg:-translate-x-1/2 lg:-translate-y-1/2 lg:rtl:translate-x-1/2",
780
+ "top-center": "lg:top-0 lg:start-1/2 lg:-translate-x-1/2 lg:-translate-y-1/2",
781
+ "top-end": "lg:top-0 lg:end-0 lg:translate-x-1/2 lg:-translate-y-1/2 lg:rtl:-translate-x-1/2",
782
+ "middle-start": "lg:top-1/2 lg:start-0 lg:-translate-x-1/2 lg:-translate-y-1/2 lg:rtl:translate-x-1/2",
783
+ "middle-center": "lg:top-1/2 lg:start-1/2 lg:-translate-x-1/2 lg:-translate-y-1/2",
784
+ "middle-end": "lg:top-1/2 lg:end-0 lg:translate-x-1/2 lg:-translate-y-1/2 lg:rtl:-translate-x-1/2",
785
+ "bottom-start": "lg:bottom-0 lg:start-0 lg:-translate-x-1/2 lg:translate-y-1/2 lg:rtl:translate-x-1/2",
786
+ "bottom-center": "lg:bottom-0 lg:start-1/2 lg:-translate-x-1/2 lg:translate-y-1/2",
787
+ "bottom-end": "lg:bottom-0 lg:end-0 lg:translate-x-1/2 lg:translate-y-1/2 lg:rtl:-translate-x-1/2"
788
+ };
789
+ var POSITION_XL = {
790
+ "top-start": "xl:top-0 xl:start-0 xl:-translate-x-1/2 xl:-translate-y-1/2 xl:rtl:translate-x-1/2",
791
+ "top-center": "xl:top-0 xl:start-1/2 xl:-translate-x-1/2 xl:-translate-y-1/2",
792
+ "top-end": "xl:top-0 xl:end-0 xl:translate-x-1/2 xl:-translate-y-1/2 xl:rtl:-translate-x-1/2",
793
+ "middle-start": "xl:top-1/2 xl:start-0 xl:-translate-x-1/2 xl:-translate-y-1/2 xl:rtl:translate-x-1/2",
794
+ "middle-center": "xl:top-1/2 xl:start-1/2 xl:-translate-x-1/2 xl:-translate-y-1/2",
795
+ "middle-end": "xl:top-1/2 xl:end-0 xl:translate-x-1/2 xl:-translate-y-1/2 xl:rtl:-translate-x-1/2",
796
+ "bottom-start": "xl:bottom-0 xl:start-0 xl:-translate-x-1/2 xl:translate-y-1/2 xl:rtl:translate-x-1/2",
797
+ "bottom-center": "xl:bottom-0 xl:start-1/2 xl:-translate-x-1/2 xl:translate-y-1/2",
798
+ "bottom-end": "xl:bottom-0 xl:end-0 xl:translate-x-1/2 xl:translate-y-1/2 xl:rtl:-translate-x-1/2"
799
+ };
800
+ var POSITION_2XL = {
801
+ "top-start": "2xl:top-0 2xl:start-0 2xl:-translate-x-1/2 2xl:-translate-y-1/2 2xl:rtl:translate-x-1/2",
802
+ "top-center": "2xl:top-0 2xl:start-1/2 2xl:-translate-x-1/2 2xl:-translate-y-1/2",
803
+ "top-end": "2xl:top-0 2xl:end-0 2xl:translate-x-1/2 2xl:-translate-y-1/2 2xl:rtl:-translate-x-1/2",
804
+ "middle-start": "2xl:top-1/2 2xl:start-0 2xl:-translate-x-1/2 2xl:-translate-y-1/2 2xl:rtl:translate-x-1/2",
805
+ "middle-center": "2xl:top-1/2 2xl:start-1/2 2xl:-translate-x-1/2 2xl:-translate-y-1/2",
806
+ "middle-end": "2xl:top-1/2 2xl:end-0 2xl:translate-x-1/2 2xl:-translate-y-1/2 2xl:rtl:-translate-x-1/2",
807
+ "bottom-start": "2xl:bottom-0 2xl:start-0 2xl:-translate-x-1/2 2xl:translate-y-1/2 2xl:rtl:translate-x-1/2",
808
+ "bottom-center": "2xl:bottom-0 2xl:start-1/2 2xl:-translate-x-1/2 2xl:translate-y-1/2",
809
+ "bottom-end": "2xl:bottom-0 2xl:end-0 2xl:translate-x-1/2 2xl:translate-y-1/2 2xl:rtl:-translate-x-1/2"
810
+ };
811
+ var BP_MAPS = {
812
+ sm: POSITION_SM,
813
+ md: POSITION_MD,
814
+ lg: POSITION_LG,
815
+ xl: POSITION_XL,
816
+ "2xl": POSITION_2XL
817
+ };
818
+ var RESPONSIVE_KEYS = ["sm", "md", "lg", "xl", "2xl"];
819
+ function resolvePosition(pos) {
820
+ if (!pos) {
821
+ return { base: "top-end", classes: POSITION["top-end"] };
822
+ }
823
+ if (typeof pos === "string") {
824
+ return { base: pos, classes: POSITION[pos] };
825
+ }
826
+ const base = pos.base ?? "top-end";
827
+ const extras = RESPONSIVE_KEYS.filter((bp) => pos[bp]).map((bp) => BP_MAPS[bp][pos[bp]]);
828
+ return { base, classes: cn(POSITION[base], ...extras) };
829
+ }
830
+ var colorBg = {
831
+ primary: "bg-pink-500",
832
+ secondary: "bg-indigo-500",
833
+ accent: "bg-orange-500",
834
+ neutral: "bg-slate-500",
835
+ info: "bg-sky-500",
836
+ success: "bg-emerald-500",
837
+ warning: "bg-amber-400",
838
+ destructive: "bg-red-500"
839
+ };
840
+ var sizeDot = {
841
+ sm: "size-2",
842
+ md: "size-3",
843
+ lg: "size-4"
844
+ };
845
+ var sizeStatus = {
846
+ sm: "size-2.5",
847
+ md: "size-3",
848
+ lg: "size-4"
849
+ };
850
+ var indicatorVariants = cva("relative inline-flex w-fit", {
851
+ variants: {},
852
+ defaultVariants: {}
853
+ });
854
+ function DefaultCloseButton() {
855
+ return /* @__PURE__ */ jsx(
856
+ "button",
857
+ {
858
+ type: "button",
859
+ "aria-label": "Dismiss",
860
+ className: "flex items-center justify-center size-6 rounded-full bg-destructive text-white text-xs font-semibold hover:bg-destructive/90 transition-colors",
861
+ children: "\xD7"
862
+ }
863
+ );
864
+ }
865
+ function NIndicator({
866
+ children,
867
+ position = "top-end",
868
+ overlay = "dot",
869
+ color = "primary",
870
+ size = "md",
871
+ shape = "default",
872
+ content,
873
+ ping,
874
+ pulse,
875
+ className,
876
+ overlayClassName,
877
+ ...rest
878
+ }) {
879
+ const { base, classes } = resolvePosition(position);
880
+ return /* @__PURE__ */ jsxs(
881
+ "div",
882
+ {
883
+ "data-slot": "indicator",
884
+ "data-position": base,
885
+ className: cn(indicatorVariants(), className),
886
+ ...rest,
887
+ children: [
888
+ /* @__PURE__ */ jsxs(
889
+ "span",
890
+ {
891
+ "data-slot": "indicator-overlay",
892
+ "data-position": base,
893
+ className: cn("absolute z-10", classes, overlayClassName),
894
+ children: [
895
+ (overlay === "dot" || overlay === "status") && /* @__PURE__ */ jsxs(
896
+ "span",
897
+ {
898
+ className: cn(
899
+ "relative inline-flex rounded-full",
900
+ overlay === "dot" ? sizeDot[size] : sizeStatus[size]
901
+ ),
902
+ children: [
903
+ ping && /* @__PURE__ */ jsx(
904
+ "span",
905
+ {
906
+ "data-slot": "indicator-ping",
907
+ "aria-hidden": "true",
908
+ className: cn(
909
+ "absolute inset-0 rounded-full animate-ping opacity-60",
910
+ colorBg[color]
911
+ )
912
+ }
913
+ ),
914
+ /* @__PURE__ */ jsx(
915
+ "span",
916
+ {
917
+ className: cn(
918
+ "relative rounded-full size-full",
919
+ colorBg[color],
920
+ overlay === "status" && "ring-2 ring-background"
921
+ )
922
+ }
923
+ )
924
+ ]
925
+ }
926
+ ),
927
+ overlay === "badge" && /* @__PURE__ */ jsx(
928
+ NBadge,
929
+ {
930
+ color,
931
+ look: "solid",
932
+ shape,
933
+ className: cn(pulse && "animate-pulse"),
934
+ children: content
935
+ }
936
+ ),
937
+ overlay === "button" && (content ?? /* @__PURE__ */ jsx(DefaultCloseButton, {})),
938
+ overlay === "custom" && content
939
+ ]
940
+ }
941
+ ),
942
+ children
943
+ ]
944
+ }
945
+ );
946
+ }
947
+ NIndicator.displayName = "NIndicator";
948
+ var Indicator = NIndicator;
696
949
  function Input({ className, type, ...props }) {
697
950
  return /* @__PURE__ */ jsx(
698
951
  "input",
@@ -700,7 +953,7 @@ function Input({ className, type, ...props }) {
700
953
  type,
701
954
  "data-slot": "input",
702
955
  className: cn(
703
- "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
956
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground border-input flex h-9 w-full min-w-0 rounded-md border bg-card px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
704
957
  "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
705
958
  "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
706
959
  className
@@ -824,6 +1077,66 @@ function SheetTitle({ className, ...props }) {
824
1077
  function SheetDescription({ className, ...props }) {
825
1078
  return /* @__PURE__ */ jsx(SheetPrimitive.Description, { "data-slot": "sheet-description", className: cn("text-muted-foreground text-sm", className), ...props });
826
1079
  }
1080
+ function assignRef(ref, node) {
1081
+ if (!ref) return;
1082
+ if (typeof ref === "function") ref(node);
1083
+ else ref.current = node;
1084
+ }
1085
+ function applyViewportLayout(node, axis) {
1086
+ node.style.width = "100%";
1087
+ node.style.height = "100%";
1088
+ node.style.minWidth = "0";
1089
+ node.style.minHeight = "0";
1090
+ node.style.overflowX = axis === "x" || axis === "both" ? "auto" : "hidden";
1091
+ node.style.overflowY = axis === "y" || axis === "both" ? "auto" : "hidden";
1092
+ }
1093
+ function NajmScroll({ className, axis = "y", autoHide = "never", viewportRef, events, options, element, children, style, ...props }) {
1094
+ return /* @__PURE__ */ jsx(
1095
+ OverlayScrollbarsComponent,
1096
+ {
1097
+ className: cn(className),
1098
+ style: {
1099
+ ...style,
1100
+ display: "flex",
1101
+ alignItems: "stretch",
1102
+ flexDirection: "row",
1103
+ flexWrap: "nowrap",
1104
+ overflow: "hidden",
1105
+ minHeight: 0,
1106
+ minWidth: 0
1107
+ },
1108
+ element,
1109
+ defer: true,
1110
+ options: {
1111
+ scrollbars: { theme: "os-theme-najm", autoHide, autoHideDelay: 500, clickScroll: true },
1112
+ overflow: {
1113
+ x: axis === "x" || axis === "both" ? "scroll" : "hidden",
1114
+ y: axis === "y" || axis === "both" ? "scroll" : "hidden"
1115
+ },
1116
+ ...options
1117
+ },
1118
+ events: {
1119
+ ...events,
1120
+ initialized: (instance, ...rest) => {
1121
+ const viewport = instance.elements().viewport;
1122
+ applyViewportLayout(viewport, axis);
1123
+ assignRef(viewportRef, viewport);
1124
+ events?.initialized?.(instance, ...rest);
1125
+ },
1126
+ updated: (instance, ...rest) => {
1127
+ applyViewportLayout(instance.elements().viewport, axis);
1128
+ events?.updated?.(instance, ...rest);
1129
+ },
1130
+ destroyed: (instance, ...rest) => {
1131
+ assignRef(viewportRef, null);
1132
+ events?.destroyed?.(instance, ...rest);
1133
+ }
1134
+ },
1135
+ ...props,
1136
+ children
1137
+ }
1138
+ );
1139
+ }
827
1140
  var PortalScopeContext = createContext(void 0);
828
1141
  function NPortalScopeProvider({ className, children }) {
829
1142
  return /* @__PURE__ */ jsx(PortalScopeContext.Provider, { value: className, children });
@@ -863,7 +1176,7 @@ function NSheet({
863
1176
  /* @__PURE__ */ jsx(SheetTitle, { className: "text-sm font-semibold text-txt-primary", children: title }),
864
1177
  description && /* @__PURE__ */ jsx(SheetDescription, { className: "text-xs text-txt-muted", children: description })
865
1178
  ] }),
866
- /* @__PURE__ */ jsx("div", { className: cn("min-h-0 flex-1 overflow-y-auto px-6 py-5", bodyClassName), children }),
1179
+ /* @__PURE__ */ jsx(NajmScroll, { axis: "y", className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx("div", { className: cn("px-6 py-5", bodyClassName), children }) }),
867
1180
  footer && /* @__PURE__ */ jsx("div", { className: "shrink-0 border-t border-border px-6 py-3", children: footer })
868
1181
  ]
869
1182
  }
@@ -966,16 +1279,33 @@ function createDialogStore() {
966
1279
  width: config.width,
967
1280
  height: config.height,
968
1281
  className: config.className,
1282
+ actionMode: config.actionMode ?? "auto",
1283
+ render: config.render,
969
1284
  resolve,
970
1285
  reject
971
1286
  };
972
1287
  set((state) => ({ dialogs: [...state.dialogs, dialogConfig] }));
973
1288
  });
974
1289
  },
975
- popDialog: (result) => {
1290
+ popDialog: async (result) => {
976
1291
  const { dialogs } = get();
977
1292
  if (dialogs.length === 0) return;
978
1293
  const dialog = dialogs[dialogs.length - 1];
1294
+ const closeCurrentDialog = () => {
1295
+ dialog.resolve?.(result);
1296
+ set((state) => ({ dialogs: state.dialogs.slice(0, -1) }));
1297
+ };
1298
+ const handler2 = dialog.primaryButton?.onClick ?? dialog.primaryButton?.onConfirm;
1299
+ if (handler2 && result != null) {
1300
+ get().setPrimaryLoading(true);
1301
+ try {
1302
+ await handler2(result);
1303
+ closeCurrentDialog();
1304
+ } finally {
1305
+ get().setPrimaryLoading(false);
1306
+ }
1307
+ return;
1308
+ }
979
1309
  dialog.resolve?.(result);
980
1310
  set((state) => ({ dialogs: state.dialogs.slice(0, -1) }));
981
1311
  },
@@ -1143,7 +1473,47 @@ var dialogVariants = cva(
1143
1473
  }
1144
1474
  }
1145
1475
  );
1476
+ var CONTENT_ACTIONS_SELECTOR = '[data-najm-dialog-actions="content"], [data-najm-wizard-form="true"]';
1477
+ function useContentOwnsActions() {
1478
+ const [contentElement, setContentElement] = React38__default.useState(null);
1479
+ const [contentOwnsActions, setContentOwnsActions] = React38__default.useState(false);
1480
+ React38__default.useLayoutEffect(() => {
1481
+ if (!contentElement) {
1482
+ setContentOwnsActions(false);
1483
+ return;
1484
+ }
1485
+ const update = () => {
1486
+ setContentOwnsActions(!!contentElement.querySelector(CONTENT_ACTIONS_SELECTOR));
1487
+ };
1488
+ update();
1489
+ const observer = new MutationObserver(update);
1490
+ observer.observe(contentElement, {
1491
+ childList: true,
1492
+ subtree: true,
1493
+ attributes: true,
1494
+ attributeFilter: ["data-najm-dialog-actions", "data-najm-wizard-form"]
1495
+ });
1496
+ return () => observer.disconnect();
1497
+ }, [contentElement]);
1498
+ return { contentOwnsActions, setContentElement };
1499
+ }
1500
+ function shouldRenderDialogButtons(showButtons, actionMode = "auto", contentOwnsActions) {
1501
+ if (!showButtons || actionMode === "content") return false;
1502
+ if (actionMode === "auto" && contentOwnsActions) return false;
1503
+ return true;
1504
+ }
1146
1505
  function DialogItem({ dialog, index, store }) {
1506
+ if (dialog.render) {
1507
+ return /* @__PURE__ */ jsx(Fragment, { children: dialog.render({
1508
+ dialog,
1509
+ index,
1510
+ zIndex: 9990 + index,
1511
+ close: (result) => store.getState().closeDialog(dialog.id, result),
1512
+ confirm: (data) => store.getState().handlePrimaryClick(dialog.id, data),
1513
+ cancel: (data) => store.getState().handleSecondaryClick(dialog.id, data),
1514
+ onOpenChange: (open) => store.getState().handleOpenChange(dialog.id, open)
1515
+ }) });
1516
+ }
1147
1517
  const {
1148
1518
  id,
1149
1519
  title,
@@ -1155,8 +1525,11 @@ function DialogItem({ dialog, index, store }) {
1155
1525
  size,
1156
1526
  width,
1157
1527
  height,
1158
- className
1528
+ className,
1529
+ actionMode = "auto"
1159
1530
  } = dialog;
1531
+ const { contentOwnsActions, setContentElement } = useContentOwnsActions();
1532
+ const renderDialogButtons = shouldRenderDialogButtons(showButtons, actionMode, contentOwnsActions);
1160
1533
  const noTitle = !title || title.trim() === "";
1161
1534
  const noDescription = !description || description.trim() === "";
1162
1535
  const noHeader = noTitle && noDescription;
@@ -1181,9 +1554,9 @@ function DialogItem({ dialog, index, store }) {
1181
1554
  /* @__PURE__ */ jsx(DialogTitle, { className: cn(noTitle && "sr-only"), children: title }),
1182
1555
  /* @__PURE__ */ jsx(DialogDescription, { className: cn(noDescription && "sr-only"), children: description })
1183
1556
  ] }),
1184
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto overflow-x-hidden px-1 -mx-1", children }),
1185
- /* @__PURE__ */ jsxs(DialogFooter, { className: cn(!showButtons && "sr-only"), children: [
1186
- secondaryButton && /* @__PURE__ */ jsx(
1557
+ /* @__PURE__ */ jsx(NajmScroll, { axis: "y", className: "flex-1 px-1 -mx-1", children: /* @__PURE__ */ jsx("div", { ref: setContentElement, style: { display: "contents" }, children }) }),
1558
+ /* @__PURE__ */ jsxs(DialogFooter, { className: cn(!renderDialogButtons && "sr-only"), children: [
1559
+ renderDialogButtons && secondaryButton && /* @__PURE__ */ jsx(
1187
1560
  Button,
1188
1561
  {
1189
1562
  type: secondaryButton.form ? "submit" : "button",
@@ -1199,7 +1572,7 @@ function DialogItem({ dialog, index, store }) {
1199
1572
  children: secondaryButton.text
1200
1573
  }
1201
1574
  ),
1202
- primaryButton && /* @__PURE__ */ jsx(
1575
+ renderDialogButtons && primaryButton && /* @__PURE__ */ jsx(
1203
1576
  Button,
1204
1577
  {
1205
1578
  type: primaryButton.form ? "submit" : "button",
@@ -1247,11 +1620,12 @@ function NDirectDialog({
1247
1620
  width,
1248
1621
  height,
1249
1622
  className,
1623
+ actionMode = "auto",
1250
1624
  closeOnPrimary = true,
1251
1625
  closeOnSecondary = true
1252
1626
  }) {
1253
- const [internalOpen, setInternalOpen] = React32__default.useState(defaultOpen);
1254
- const [primaryLoading, setPrimaryLoading] = React32__default.useState(false);
1627
+ const [internalOpen, setInternalOpen] = React38__default.useState(defaultOpen);
1628
+ const [primaryLoading, setPrimaryLoading] = React38__default.useState(false);
1255
1629
  const isControlled = open !== void 0;
1256
1630
  const currentOpen = isControlled ? open : internalOpen;
1257
1631
  const setOpen = (nextOpen) => {
@@ -1278,6 +1652,8 @@ function NDirectDialog({
1278
1652
  const noDescription = !description || description.trim() === "";
1279
1653
  const noHeader = noTitle && noDescription;
1280
1654
  const isPrimaryLoading = primaryLoading || !!resolvedPrimaryButton.loading;
1655
+ const { contentOwnsActions, setContentElement } = useContentOwnsActions();
1656
+ const renderDialogButtons = shouldRenderDialogButtons(showButtons, actionMode, contentOwnsActions);
1281
1657
  const handlePrimary = async (e) => {
1282
1658
  const hasForm = !!resolvedPrimaryButton.form;
1283
1659
  if (!hasForm && e) e.preventDefault();
@@ -1310,8 +1686,8 @@ function NDirectDialog({
1310
1686
  /* @__PURE__ */ jsx(DialogTitle, { className: cn(noTitle && "sr-only"), children: title }),
1311
1687
  /* @__PURE__ */ jsx(DialogDescription, { className: cn(noDescription && "sr-only"), children: description })
1312
1688
  ] }),
1313
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto overflow-x-hidden px-1 -mx-1", children }),
1314
- /* @__PURE__ */ jsx(DialogFooter, { className: cn(!showButtons && "sr-only"), children: showButtons && /* @__PURE__ */ jsxs(Fragment, { children: [
1689
+ /* @__PURE__ */ jsx(NajmScroll, { axis: "y", className: "flex-1 px-1 -mx-1", children: /* @__PURE__ */ jsx("div", { ref: setContentElement, style: { display: "contents" }, children }) }),
1690
+ /* @__PURE__ */ jsx(DialogFooter, { className: cn(!renderDialogButtons && "sr-only"), children: renderDialogButtons && /* @__PURE__ */ jsxs(Fragment, { children: [
1315
1691
  /* @__PURE__ */ jsx(
1316
1692
  Button,
1317
1693
  {
@@ -1399,27 +1775,104 @@ function NConfirmDialog({
1399
1775
  function NDeleteDialogContent({
1400
1776
  itemName,
1401
1777
  itemType,
1402
- icon: Icon2,
1403
- warningText = "This action cannot be undone.",
1778
+ icon: Icon2 = "trash-2",
1779
+ warningText = "Are you sure you want to delete?",
1404
1780
  className
1405
1781
  }) {
1406
- return /* @__PURE__ */ jsx("form", { id: "najm-delete-form", onSubmit: (e) => e.preventDefault(), children: /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-center gap-4 py-4", className), children: [
1407
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center w-20 h-20 rounded-full bg-red-100 dark:bg-red-900/30", children: /* @__PURE__ */ jsx(NIcon, { icon: Icon2 ?? "alert-triangle", className: "h-10 w-10 text-red-500" }) }),
1408
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center text-center", children: [
1409
- /* @__PURE__ */ jsxs("p", { className: "text-md text-muted-foreground mb-2", children: [
1410
- "Are you sure you want to delete ",
1411
- /* @__PURE__ */ jsx("strong", { children: itemName }),
1412
- itemType ? /* @__PURE__ */ jsxs(Fragment, { children: [
1413
- " (",
1414
- itemType,
1415
- ")"
1416
- ] }) : null,
1417
- "?"
1418
- ] }),
1419
- /* @__PURE__ */ jsx("p", { className: "text-md text-muted-foreground", children: warningText })
1782
+ return /* @__PURE__ */ jsx("form", { id: "najm-delete-form", onSubmit: (e) => e.preventDefault(), children: /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-center text-center", className), children: [
1783
+ /* @__PURE__ */ jsx("div", { className: "mb-6 flex size-16 items-center justify-center rounded-[20px] bg-destructive/10 text-destructive dark:bg-[#5a1822] dark:text-white", children: /* @__PURE__ */ jsx(NIcon, { icon: Icon2, className: "size-7" }) }),
1784
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
1785
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold leading-none text-card-foreground dark:text-white", children: "Delete" }),
1786
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
1787
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium leading-5 text-muted-foreground dark:text-[#aab4c2]", children: warningText }),
1788
+ /* @__PURE__ */ jsxs("p", { className: "max-w-[280px] truncate text-sm font-bold leading-5 text-card-foreground dark:text-white", children: [
1789
+ '"',
1790
+ itemName,
1791
+ '"',
1792
+ itemType ? /* @__PURE__ */ jsxs(Fragment, { children: [
1793
+ " (",
1794
+ itemType,
1795
+ ")"
1796
+ ] }) : null
1797
+ ] })
1798
+ ] })
1420
1799
  ] })
1421
1800
  ] }) });
1422
1801
  }
1802
+ function NDeleteDialog({
1803
+ open = true,
1804
+ title = "Delete",
1805
+ description,
1806
+ itemName,
1807
+ itemType,
1808
+ icon,
1809
+ warningText,
1810
+ confirmText = "Confirm",
1811
+ cancelText = "Cancel",
1812
+ loading,
1813
+ zIndex,
1814
+ className,
1815
+ contentClassName,
1816
+ onOpenChange,
1817
+ onConfirm,
1818
+ onCancel
1819
+ }) {
1820
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
1821
+ DialogContent,
1822
+ {
1823
+ className: cn(
1824
+ "h-auto max-w-[380px] gap-0 rounded-[18px] border border-border bg-card p-6 pt-8 shadow-2xl dark:border-0 dark:bg-[#222b38]",
1825
+ "[&>button]:right-4 [&>button]:top-4 [&>button]:flex [&>button]:size-6 [&>button]:items-center [&>button]:justify-center",
1826
+ "[&>button]:rounded-full [&>button]:bg-muted [&>button]:text-muted-foreground [&>button]:opacity-100 [&>button]:ring-offset-0",
1827
+ "[&>button]:hover:bg-secondary [&>button]:hover:text-foreground dark:[&>button]:bg-[#4d5a6d] dark:[&>button]:text-white dark:[&>button]:hover:bg-[#647186] dark:[&>button]:hover:text-white",
1828
+ className
1829
+ ),
1830
+ style: { zIndex },
1831
+ children: [
1832
+ /* @__PURE__ */ jsxs(DialogHeader, { className: "sr-only", children: [
1833
+ /* @__PURE__ */ jsx(DialogTitle, { children: title }),
1834
+ /* @__PURE__ */ jsx(DialogDescription, { children: description })
1835
+ ] }),
1836
+ /* @__PURE__ */ jsx(
1837
+ NDeleteDialogContent,
1838
+ {
1839
+ itemName,
1840
+ itemType,
1841
+ icon,
1842
+ warningText,
1843
+ className: contentClassName
1844
+ }
1845
+ ),
1846
+ /* @__PURE__ */ jsxs(DialogFooter, { className: "mt-6 grid grid-cols-2 gap-3 sm:grid-cols-2", children: [
1847
+ /* @__PURE__ */ jsx(
1848
+ Button,
1849
+ {
1850
+ type: "button",
1851
+ "data-button-type": "secondary",
1852
+ variant: "outline",
1853
+ onClick: onCancel,
1854
+ disabled: loading,
1855
+ className: "h-10 w-full rounded-[10px] border border-border bg-secondary text-sm font-bold text-secondary-foreground shadow-none hover:bg-secondary/80 hover:text-secondary-foreground dark:border-0 dark:bg-[#3e4a5d] dark:text-white dark:hover:bg-[#4b586c] dark:hover:text-white",
1856
+ children: cancelText
1857
+ }
1858
+ ),
1859
+ /* @__PURE__ */ jsx(
1860
+ Button,
1861
+ {
1862
+ type: "button",
1863
+ "data-button-type": "primary",
1864
+ variant: "destructive",
1865
+ onClick: onConfirm,
1866
+ loading,
1867
+ className: "h-10 w-full rounded-[10px] bg-destructive text-sm font-bold text-destructive-foreground shadow-none hover:bg-destructive/90 focus-visible:ring-destructive/40 dark:bg-[#dc4d61] dark:text-white dark:hover:bg-[#e15f70] dark:focus-visible:ring-[#dc4d61]/40",
1868
+ children: confirmText
1869
+ }
1870
+ )
1871
+ ] })
1872
+ ]
1873
+ }
1874
+ ) });
1875
+ }
1423
1876
  function useDialog(store) {
1424
1877
  const resolvedStore = store ?? useDialogStore();
1425
1878
  const custom = async (options) => {
@@ -1433,17 +1886,27 @@ function useDialog(store) {
1433
1886
  const confirmDelete = async (options) => {
1434
1887
  try {
1435
1888
  return await resolvedStore.getState().pushDialog({
1436
- title: options.title || "Confirm Deletion",
1889
+ title: options.title || "Delete",
1437
1890
  description: options.description,
1438
- children: React32__default.createElement(NDeleteDialogContent, {
1891
+ size: options.size || "sm",
1892
+ className: options.className,
1893
+ render: ({ dialog, zIndex, confirm, cancel, onOpenChange }) => React38__default.createElement(NDeleteDialog, {
1439
1894
  itemName: options.itemName,
1440
1895
  itemType: options.itemType,
1441
- icon: options.icon
1896
+ icon: options.icon,
1897
+ title: dialog.title,
1898
+ description: dialog.description,
1899
+ confirmText: dialog.primaryButton?.text,
1900
+ cancelText: dialog.secondaryButton?.text,
1901
+ loading: dialog.primaryButton?.loading,
1902
+ className: dialog.className,
1903
+ zIndex,
1904
+ onOpenChange,
1905
+ onConfirm: () => confirm(),
1906
+ onCancel: () => cancel()
1442
1907
  }),
1443
- size: options.size || "sm",
1444
- className: options.className,
1445
1908
  primaryButton: {
1446
- text: options.confirmText || "Delete",
1909
+ text: options.confirmText || "Confirm",
1447
1910
  variant: "destructive",
1448
1911
  loading: options.loading,
1449
1912
  onClick: options.onConfirm
@@ -1633,7 +2096,8 @@ function DropdownMenuSubContent({ className, ...props }) {
1633
2096
  );
1634
2097
  }
1635
2098
  function DropdownMenuContent({ className, sideOffset = 4, ...props }) {
1636
- return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
2099
+ const container = React38.useContext(NajmThemeContainerCtx);
2100
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { container: container ?? void 0, children: /* @__PURE__ */ jsx(
1637
2101
  DropdownMenuPrimitive.Content,
1638
2102
  {
1639
2103
  "data-slot": "dropdown-menu-content",
@@ -1709,7 +2173,8 @@ function PopoverAnchor({ ...props }) {
1709
2173
  return /* @__PURE__ */ jsx(PopoverPrimitive.Anchor, { "data-slot": "popover-anchor", ...props });
1710
2174
  }
1711
2175
  function PopoverContent({ className, align = "center", sideOffset = 4, ...props }) {
1712
- return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
2176
+ const container = React38.useContext(NajmThemeContainerCtx);
2177
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { container: container ?? void 0, children: /* @__PURE__ */ jsx(
1713
2178
  PopoverPrimitive.Content,
1714
2179
  {
1715
2180
  "data-slot": "popover-content",
@@ -1738,7 +2203,7 @@ function SelectTrigger({ className, children, ...props }) {
1738
2203
  {
1739
2204
  "data-slot": "select-trigger",
1740
2205
  className: cn(
1741
- "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex h-9 w-full items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
2206
+ "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex h-9 w-full cursor-pointer items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1742
2207
  className
1743
2208
  ),
1744
2209
  ...props,
@@ -1756,7 +2221,8 @@ function SelectScrollDownButton({ className, ...props }) {
1756
2221
  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" }) });
1757
2222
  }
1758
2223
  function SelectContent({ className, children, position = "popper", ...props }) {
1759
- return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
2224
+ const container = React38.useContext(NajmThemeContainerCtx);
2225
+ return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { container: container ?? void 0, children: /* @__PURE__ */ jsxs(
1760
2226
  SelectPrimitive.Content,
1761
2227
  {
1762
2228
  "data-slot": "select-content",
@@ -1795,7 +2261,7 @@ function SelectItem({ className, children, ...props }) {
1795
2261
  function SelectSeparator({ className, ...props }) {
1796
2262
  return /* @__PURE__ */ jsx(SelectPrimitive.Separator, { "data-slot": "select-separator", className: cn("bg-muted pointer-events-none -mx-1 my-1 h-px", className), ...props });
1797
2263
  }
1798
- var NativeSelect = React32.forwardRef(
2264
+ var NativeSelect = React38.forwardRef(
1799
2265
  ({ className, options, placeholder, value, ...props }, ref) => {
1800
2266
  const hasValue = value !== void 0 && value !== "";
1801
2267
  return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
@@ -1975,8 +2441,9 @@ var triggerVariantMap = {
1975
2441
  ].join(" "),
1976
2442
  ghost: [
1977
2443
  "data-[state=active]:text-foreground",
1978
- "data-[state=active]:bg-secondary",
1979
- "rounded-md px-2 py-1"
2444
+ "data-[state=active]:bg-secondary dark:data-[state=active]:bg-card",
2445
+ "rounded-md px-2 py-1",
2446
+ "h-full"
1980
2447
  ].join(" ")
1981
2448
  };
1982
2449
  function TabsTrigger({
@@ -2000,6 +2467,121 @@ function TabsTrigger({
2000
2467
  function TabsContent({ className, ...props }) {
2001
2468
  return /* @__PURE__ */ jsx(TabsPrimitive.Content, { "data-slot": "tabs-content", className: cn("flex-1 outline-none", className), ...props });
2002
2469
  }
2470
+
2471
+ // src/components/tabs/tabColors.ts
2472
+ var TAB_COLORS = {
2473
+ default: { list: "bg-muted", active: "bg-background" },
2474
+ primary: { list: "bg-primary/20", active: "bg-primary/50" },
2475
+ card: { list: "bg-card", active: "bg-muted" },
2476
+ ghost: { list: "bg-transparent", active: "bg-accent" }
2477
+ };
2478
+ function hexToRgb(hex) {
2479
+ const m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
2480
+ return m ? { r: parseInt(m[1], 16), g: parseInt(m[2], 16), b: parseInt(m[3], 16) } : { r: 0, g: 0, b: 0 };
2481
+ }
2482
+ function accentStyles(hex) {
2483
+ const { r, g, b } = hexToRgb(hex);
2484
+ const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
2485
+ return {
2486
+ list: { backgroundColor: `rgba(${r},${g},${b},0.12)` },
2487
+ trigger: { color: `rgba(${r},${g},${b},0.7)` },
2488
+ activeTrigger: { backgroundColor: hex, color: luminance > 0.55 ? "#1e293b" : "#ffffff" }
2489
+ };
2490
+ }
2491
+ function NTabs({
2492
+ items,
2493
+ defaultValue,
2494
+ value,
2495
+ onValueChange,
2496
+ variant = "pills",
2497
+ orientation = "horizontal",
2498
+ color = "default",
2499
+ accentColor,
2500
+ fullWidth = false,
2501
+ className,
2502
+ classNames,
2503
+ styles
2504
+ }) {
2505
+ const preset = TAB_COLORS[color];
2506
+ const activeClass = `data-[state=active]:${preset.active}`;
2507
+ const isHorizontal = orientation === "horizontal";
2508
+ const [currentValue, setCurrentValue] = useState(
2509
+ value ?? defaultValue ?? items[0]?.value ?? ""
2510
+ );
2511
+ useEffect(() => {
2512
+ if (value !== void 0) setCurrentValue(value);
2513
+ }, [value]);
2514
+ const handleChange = (v) => {
2515
+ setCurrentValue(v);
2516
+ onValueChange?.(v);
2517
+ };
2518
+ const derived = accentColor ? accentStyles(accentColor) : null;
2519
+ const listStyle = variant === "ghost" || variant === "bordered" ? styles?.list : derived?.list ?? styles?.list;
2520
+ const triggerStyle = derived?.trigger ?? styles?.trigger;
2521
+ const activeStyle = derived ? variant === "bordered" ? { borderColor: accentColor, color: accentColor } : derived.activeTrigger : styles?.activeTrigger;
2522
+ return /* @__PURE__ */ jsxs(
2523
+ Tabs,
2524
+ {
2525
+ value,
2526
+ defaultValue,
2527
+ onValueChange: handleChange,
2528
+ variant,
2529
+ orientation,
2530
+ className: classNames?.root,
2531
+ style: styles?.root,
2532
+ children: [
2533
+ /* @__PURE__ */ jsx(
2534
+ TabsList,
2535
+ {
2536
+ variant,
2537
+ orientation,
2538
+ className: cn(
2539
+ !accentColor && variant === "pills" && preset.list,
2540
+ fullWidth && isHorizontal && "w-full",
2541
+ classNames?.list,
2542
+ className
2543
+ ),
2544
+ style: listStyle,
2545
+ children: items.map((item) => /* @__PURE__ */ jsxs(
2546
+ TabsTrigger,
2547
+ {
2548
+ value: item.value,
2549
+ variant,
2550
+ disabled: item.disabled,
2551
+ className: cn(
2552
+ !accentColor && activeClass,
2553
+ fullWidth && isHorizontal && "flex-1",
2554
+ classNames?.trigger
2555
+ ),
2556
+ style: {
2557
+ ...triggerStyle,
2558
+ ...currentValue === item.value ? activeStyle : {}
2559
+ },
2560
+ children: [
2561
+ item.icon && /* @__PURE__ */ jsx(NIcon, { icon: item.icon, size: 14 }),
2562
+ item.label
2563
+ ]
2564
+ },
2565
+ item.value
2566
+ ))
2567
+ }
2568
+ ),
2569
+ items.map(
2570
+ (item) => item.content != null ? /* @__PURE__ */ jsx(
2571
+ TabsContent,
2572
+ {
2573
+ value: item.value,
2574
+ className: classNames?.content,
2575
+ style: styles?.content,
2576
+ children: item.content
2577
+ },
2578
+ item.value
2579
+ ) : null
2580
+ )
2581
+ ]
2582
+ }
2583
+ );
2584
+ }
2003
2585
  function TooltipProvider({ delayDuration = 0, ...props }) {
2004
2586
  return /* @__PURE__ */ jsx(TooltipPrimitive.Provider, { "data-slot": "tooltip-provider", delayDuration, ...props });
2005
2587
  }
@@ -2022,7 +2604,8 @@ var tooltipContentVariants = cva(
2022
2604
  }
2023
2605
  );
2024
2606
  function TooltipContent({ className, sideOffset = 4, variant, children, ...props }) {
2025
- return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(
2607
+ const container = React38.useContext(NajmThemeContainerCtx);
2608
+ return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { container: container ?? void 0, children: /* @__PURE__ */ jsx(
2026
2609
  TooltipPrimitive.Content,
2027
2610
  {
2028
2611
  "data-slot": "tooltip-content",
@@ -2183,7 +2766,7 @@ function ScrollArea({ className, children, ...props }) {
2183
2766
  return /* @__PURE__ */ jsx("div", { className: cn("relative overflow-hidden", className), ...props, children: /* @__PURE__ */ jsx(
2184
2767
  "div",
2185
2768
  {
2186
- className: "h-full w-full overflow-y-auto overflow-x-hidden",
2769
+ className: "h-full w-full najm-overlay-scroll-y overflow-x-hidden",
2187
2770
  style: {
2188
2771
  scrollbarWidth: "thin",
2189
2772
  scrollbarColor: "#3a3a4e transparent"
@@ -2282,7 +2865,7 @@ function Avatar({
2282
2865
  ...props
2283
2866
  }) {
2284
2867
  const hasShortcut = src !== void 0 || fallback !== void 0;
2285
- const hasChildren = React32.Children.count(children) > 0;
2868
+ const hasChildren = React38.Children.count(children) > 0;
2286
2869
  return /* @__PURE__ */ jsxs(
2287
2870
  AvatarPrimitive.Root,
2288
2871
  {
@@ -2376,9 +2959,9 @@ function AvatarGroup({ ring = true, className, children, ...props }) {
2376
2959
  "data-slot": "avatar-group",
2377
2960
  className: cn("flex -space-x-2", className),
2378
2961
  ...props,
2379
- children: ring ? React32.Children.map(children, (child) => {
2380
- if (React32.isValidElement(child) && child.type === Avatar) {
2381
- return React32.cloneElement(child, { ring: true, ...child.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 });
2382
2965
  }
2383
2966
  return child;
2384
2967
  }) : children
@@ -2445,7 +3028,7 @@ function Swap({
2445
3028
  className,
2446
3029
  ...props
2447
3030
  }) {
2448
- const [internalChecked, setInternalChecked] = React32.useState(defaultChecked);
3031
+ const [internalChecked, setInternalChecked] = React38.useState(defaultChecked);
2449
3032
  const isControlled = controlledChecked !== void 0 || controlledState !== void 0;
2450
3033
  const currentState = getDerivedState(
2451
3034
  isControlled ? controlledChecked ?? false : internalChecked,
@@ -2453,7 +3036,7 @@ function Swap({
2453
3036
  );
2454
3037
  const dataState = currentState === "indeterminate" ? "indeterminate" : currentState ? "on" : "off";
2455
3038
  const ariaPressed = currentState === "indeterminate" ? "mixed" : currentState;
2456
- const handleClick = React32.useCallback((event) => {
3039
+ const handleClick = React38.useCallback((event) => {
2457
3040
  onClick?.(event);
2458
3041
  if (event.defaultPrevented) return;
2459
3042
  if (disabled) return;
@@ -2590,7 +3173,7 @@ function CommandInput({ className, ...props }) {
2590
3173
  ] });
2591
3174
  }
2592
3175
  function CommandList({ className, ...props }) {
2593
- return /* @__PURE__ */ jsx(Command$1.List, { "data-slot": "command-list", className: cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className), ...props });
3176
+ return /* @__PURE__ */ jsx(Command$1.List, { "data-slot": "command-list", className: cn("max-h-[300px] najm-overlay-scroll-y overflow-x-hidden", className), ...props });
2594
3177
  }
2595
3178
  function CommandEmpty({ ...props }) {
2596
3179
  return /* @__PURE__ */ jsx(Command$1.Empty, { "data-slot": "command-empty", className: "py-6 text-center text-sm", ...props });
@@ -2624,7 +3207,7 @@ function CollapsibleContent2({ ...props }) {
2624
3207
  return /* @__PURE__ */ jsx(CollapsiblePrimitive.CollapsibleContent, { "data-slot": "collapsible-content", ...props });
2625
3208
  }
2626
3209
  var toggleVariants = cva(
2627
- "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-[color,box-shadow] hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
3210
+ "inline-flex cursor-pointer items-center justify-center gap-2 rounded-md text-sm font-medium transition-[color,box-shadow] hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
2628
3211
  {
2629
3212
  variants: {
2630
3213
  variant: {
@@ -2657,7 +3240,7 @@ var sizeClasses = {
2657
3240
  md: "h-8 w-8",
2658
3241
  lg: "h-10 w-10"
2659
3242
  };
2660
- var IconButton = React32.forwardRef(
3243
+ var IconButton = React38.forwardRef(
2661
3244
  ({
2662
3245
  className,
2663
3246
  variant = "ghost",
@@ -2674,7 +3257,7 @@ var IconButton = React32.forwardRef(
2674
3257
  type,
2675
3258
  "aria-pressed": active || void 0,
2676
3259
  className: cn(
2677
- "inline-flex shrink-0 items-center justify-center rounded-md transition-colors",
3260
+ "inline-flex shrink-0 cursor-pointer items-center justify-center rounded-md transition-colors",
2678
3261
  "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
2679
3262
  "disabled:cursor-not-allowed disabled:opacity-50",
2680
3263
  variantClasses[variant],
@@ -2769,7 +3352,7 @@ var toneClasses = {
2769
3352
  ring: "border-primary/30"
2770
3353
  }
2771
3354
  };
2772
- var StatusPill = React32.forwardRef(
3355
+ var StatusPill = React38.forwardRef(
2773
3356
  ({ className, tone = "neutral", pulse = false, label, ...props }, ref) => {
2774
3357
  const c = toneClasses[tone];
2775
3358
  return /* @__PURE__ */ jsxs(
@@ -2827,20 +3410,20 @@ function Toaster({ ...props }) {
2827
3410
  );
2828
3411
  }
2829
3412
  var Form = FormProvider;
2830
- var FormFieldContext = React32.createContext({});
3413
+ var FormFieldContext = React38.createContext({});
2831
3414
  var FormField = ({ ...props }) => /* @__PURE__ */ jsx(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx(Controller, { ...props }) });
2832
3415
  var useFormField = () => {
2833
- const fieldContext = React32.useContext(FormFieldContext);
2834
- const itemContext = React32.useContext(FormItemContext);
3416
+ const fieldContext = React38.useContext(FormFieldContext);
3417
+ const itemContext = React38.useContext(FormItemContext);
2835
3418
  const { getFieldState, formState } = useFormContext();
2836
3419
  const fieldState = getFieldState(fieldContext.name, formState);
2837
3420
  if (!fieldContext) throw new Error("useFormField should be used within <FormField>");
2838
3421
  const { id } = itemContext;
2839
3422
  return { id, name: fieldContext.name, formItemId: `${id}-form-item`, formDescriptionId: `${id}-form-item-description`, formMessageId: `${id}-form-item-message`, ...fieldState };
2840
3423
  };
2841
- var FormItemContext = React32.createContext({});
3424
+ var FormItemContext = React38.createContext({});
2842
3425
  function FormItem({ className, ...props }) {
2843
- const id = React32.useId();
3426
+ const id = React38.useId();
2844
3427
  return /* @__PURE__ */ jsx(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx("div", { "data-slot": "form-item", className: cn("grid gap-2", className), ...props }) });
2845
3428
  }
2846
3429
  function FormLabel({ className, ...props }) {
@@ -2862,10 +3445,10 @@ function FormMessage({ className, children, ...props }) {
2862
3445
  return /* @__PURE__ */ jsx("p", { "data-slot": "form-message", id: formMessageId, className: cn("text-destructive text-[0.8rem] font-medium", className), ...props, children: body });
2863
3446
  }
2864
3447
  function Table({ className, ...props }) {
2865
- return /* @__PURE__ */ jsx("div", { "data-slot": "table-container", className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx("table", { "data-slot": "table", className: cn("w-full caption-bottom text-sm", className), ...props }) });
3448
+ return /* @__PURE__ */ jsx("div", { "data-slot": "table-container", className: "relative w-full", children: /* @__PURE__ */ jsx("table", { "data-slot": "table", className: cn("w-full caption-bottom text-sm", className), ...props }) });
2866
3449
  }
2867
3450
  function TableHeader({ className, ...props }) {
2868
- return /* @__PURE__ */ jsx("thead", { "data-slot": "table-header", className: cn("bg-muted/80 [&_tr]:border-b [&_tr]:border-border/40 [&_tr]:hover:bg-transparent", className), ...props });
3451
+ return /* @__PURE__ */ jsx("thead", { "data-slot": "table-header", className: cn("[&_tr]:border-b [&_tr]:border-border/40", className), ...props });
2869
3452
  }
2870
3453
  function TableBody({ className, ...props }) {
2871
3454
  return /* @__PURE__ */ jsx("tbody", { "data-slot": "table-body", className: cn("[&_tr:last-child]:border-0", className), ...props });
@@ -2984,7 +3567,7 @@ function NErrorState({ title = "Something went wrong", message, onRetry, retryLa
2984
3567
  ] });
2985
3568
  }
2986
3569
  function NEmptyState({ title = "No data", description, icon, action, className }) {
2987
- const iconContent = icon ? React32__default.isValidElement(icon) ? icon : React32__default.createElement(icon, { className: "h-8 w-8" }) : null;
3570
+ const iconContent = icon ? React38__default.isValidElement(icon) ? icon : React38__default.createElement(icon, { className: "h-8 w-8" }) : null;
2988
3571
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-center justify-center gap-3 py-12", className), children: [
2989
3572
  iconContent && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground/50", children: iconContent }),
2990
3573
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
@@ -2994,7 +3577,7 @@ function NEmptyState({ title = "No data", description, icon, action, className }
2994
3577
  action && /* @__PURE__ */ jsx("div", { className: "mt-2", children: action })
2995
3578
  ] });
2996
3579
  }
2997
- var NErrorBoundary = class extends React32__default.Component {
3580
+ var NErrorBoundary = class extends React38__default.Component {
2998
3581
  constructor(props) {
2999
3582
  super(props);
3000
3583
  this.state = { hasError: false, error: null };
@@ -3240,16 +3823,18 @@ function NCard({
3240
3823
  onRetry,
3241
3824
  noPadding = false,
3242
3825
  separator = false,
3826
+ bordered = false,
3243
3827
  className,
3244
- classNames
3828
+ classNames,
3829
+ onClick
3245
3830
  }) {
3246
3831
  const isEmpty = empty ?? noData ?? false;
3247
3832
  const resolvedEmptyText = emptyText ?? noDataText ?? "No data available";
3248
3833
  let actionSlot = null;
3249
3834
  let footerSlot = null;
3250
3835
  const mainChildren = [];
3251
- React32__default.Children.forEach(children, (child) => {
3252
- if (React32__default.isValidElement(child)) {
3836
+ React38__default.Children.forEach(children, (child) => {
3837
+ if (React38__default.isValidElement(child)) {
3253
3838
  if (child.type === NCardAction) {
3254
3839
  actionSlot = child;
3255
3840
  } else if (child.type === NCardFooter) {
@@ -3263,27 +3848,41 @@ function NCard({
3263
3848
  });
3264
3849
  const hasHeader = !!(title || description || actionSlot);
3265
3850
  const iconSize = description ? "h-8 w-8" : "h-5 w-5";
3266
- return /* @__PURE__ */ jsxs(Card, { className: cn("flex flex-col", !noPadding && "p-4 gap-3", classNames?.root, className), children: [
3267
- hasHeader && /* @__PURE__ */ jsxs(CardHeader, { className: cn("flex flex-row items-center justify-between space-y-0 p-0", classNames?.header), children: [
3268
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
3269
- icon && /* @__PURE__ */ jsx(NIcon, { icon, className: cn(iconSize, "shrink-0 text-muted-foreground", iconColor, classNames?.icon) }),
3270
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
3271
- title && /* @__PURE__ */ jsx(CardTitle, { className: cn("text-base leading-snug", classNames?.title), children: title }),
3272
- description && /* @__PURE__ */ jsx(CardDescription, { className: cn("text-xs mt-0.5", classNames?.description), children: description })
3273
- ] })
3274
- ] }),
3275
- actionSlot && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 shrink-0 ml-2", children: actionSlot })
3276
- ] }),
3277
- hasHeader && separator && /* @__PURE__ */ jsx("div", { className: "border-t" }),
3278
- /* @__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(
3279
- NErrorState,
3280
- {
3281
- message: typeof error === "string" ? error : errorText ?? "Something went wrong",
3282
- onRetry
3283
- }
3284
- ) : isEmpty ? /* @__PURE__ */ jsx(NEmptyState, { title: resolvedEmptyText }) : mainChildren }),
3285
- footerSlot && /* @__PURE__ */ jsx(CardFooter, { className: cn("p-0 pt-3 border-t mt-auto", classNames?.footer), children: footerSlot })
3286
- ] });
3851
+ return /* @__PURE__ */ jsxs(
3852
+ Card,
3853
+ {
3854
+ "data-bordered": bordered ? "true" : void 0,
3855
+ onClick,
3856
+ className: cn(
3857
+ "flex flex-col",
3858
+ !noPadding && "p-4 gap-3",
3859
+ bordered && "border border-muted-foreground shadow-none",
3860
+ classNames?.root,
3861
+ className
3862
+ ),
3863
+ children: [
3864
+ hasHeader && /* @__PURE__ */ jsxs(CardHeader, { className: cn("flex flex-row items-center justify-between space-y-0 p-0", classNames?.header), children: [
3865
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
3866
+ icon && /* @__PURE__ */ jsx(NIcon, { icon, className: cn(iconSize, "shrink-0 text-muted-foreground", iconColor, classNames?.icon) }),
3867
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
3868
+ title && /* @__PURE__ */ jsx(CardTitle, { className: cn("text-base leading-snug", classNames?.title), children: title }),
3869
+ description && /* @__PURE__ */ jsx(CardDescription, { className: cn("text-xs mt-0.5", classNames?.description), children: description })
3870
+ ] })
3871
+ ] }),
3872
+ actionSlot && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 shrink-0 ml-2", children: actionSlot })
3873
+ ] }),
3874
+ hasHeader && separator && /* @__PURE__ */ jsx("div", { className: "border-t" }),
3875
+ /* @__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
+ NErrorState,
3877
+ {
3878
+ message: typeof error === "string" ? error : errorText ?? "Something went wrong",
3879
+ onRetry
3880
+ }
3881
+ ) : 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 })
3883
+ ]
3884
+ }
3885
+ );
3287
3886
  }
3288
3887
  function truncateByCharacters(text, maxCharacters, suffix = "...") {
3289
3888
  if (!text) return "";
@@ -3445,25 +4044,31 @@ function DefaultCard({
3445
4044
  subtext,
3446
4045
  change,
3447
4046
  onClick,
4047
+ bordered,
3448
4048
  className,
3449
4049
  classNames
3450
4050
  }) {
3451
4051
  return /* @__PURE__ */ jsxs(
3452
- "div",
4052
+ NCard,
3453
4053
  {
4054
+ noPadding: true,
3454
4055
  onClick,
4056
+ bordered,
3455
4057
  className: cn(
3456
- "group flex items-center gap-4 rounded-xl border border-border bg-card p-4 transition-colors",
4058
+ "group p-4 transition-colors",
3457
4059
  onClick && "cursor-pointer hover:border-border/60 hover:bg-accent/40",
3458
- classNames?.root,
3459
4060
  className
3460
4061
  ),
4062
+ classNames: {
4063
+ root: classNames?.root,
4064
+ content: "flex-row items-center gap-4"
4065
+ },
3461
4066
  children: [
3462
4067
  /* @__PURE__ */ jsx(
3463
4068
  "div",
3464
4069
  {
3465
4070
  className: cn(
3466
- "flex h-14 w-14 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary transition-colors group-hover:bg-primary/20",
4071
+ "flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary transition-colors group-hover:bg-primary/20",
3467
4072
  classNames?.icon
3468
4073
  ),
3469
4074
  children: /* @__PURE__ */ jsx(NIcon, { icon, className: "w-7 h-7" })
@@ -3486,7 +4091,7 @@ function DefaultCard({
3486
4091
  }
3487
4092
  )
3488
4093
  ] }),
3489
- /* @__PURE__ */ jsx("p", { className: cn("text-2xl font-semibold leading-none text-foreground", classNames?.value), children: value }),
4094
+ /* @__PURE__ */ jsx("p", { className: cn("text-xl font-semibold leading-none text-foreground", classNames?.value), children: value }),
3490
4095
  subtext && /* @__PURE__ */ jsx("p", { className: cn("text-[10px] text-muted-foreground", classNames?.description), children: subtext })
3491
4096
  ] })
3492
4097
  ]
@@ -3504,21 +4109,24 @@ function UsageCard({
3504
4109
  accentColor,
3505
4110
  countLabel,
3506
4111
  onClick,
4112
+ bordered,
3507
4113
  className,
3508
4114
  classNames
3509
4115
  }) {
3510
4116
  const pct = total > 0 ? Math.min(Math.max(used / total * 100, 0), 100) : 0;
3511
4117
  const itemLabel = countLabel ?? (count === 1 ? "Item" : "Items");
3512
4118
  return /* @__PURE__ */ jsxs(
3513
- "div",
4119
+ NCard,
3514
4120
  {
4121
+ noPadding: true,
3515
4122
  onClick,
4123
+ bordered,
3516
4124
  className: cn(
3517
- "group min-h-[116px] rounded-[10px] border border-border bg-card px-4 py-4 transition-colors",
4125
+ "group min-h-[116px] px-4 py-4 transition-colors",
3518
4126
  onClick && "cursor-pointer hover:bg-accent/30",
3519
- classNames?.root,
3520
4127
  className
3521
4128
  ),
4129
+ classNames: { root: classNames?.root },
3522
4130
  children: [
3523
4131
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
3524
4132
  /* @__PURE__ */ jsx(
@@ -3557,17 +4165,23 @@ function UsageCard({
3557
4165
  }
3558
4166
  );
3559
4167
  }
3560
- function CompactCard({ icon, label, value, unit, iconColor, onClick, className, classNames }) {
4168
+ function CompactCard({ icon, label, value, unit, iconColor, onClick, bordered, className, classNames }) {
3561
4169
  return /* @__PURE__ */ jsxs(
3562
- "div",
4170
+ NCard,
3563
4171
  {
4172
+ noPadding: true,
3564
4173
  onClick,
4174
+ bordered,
3565
4175
  className: cn(
3566
- "rounded-lg bg-foreground/10 p-3 flex flex-col items-center justify-center",
4176
+ !bordered && "border-0",
4177
+ "bg-foreground/10 p-3 shadow-none",
3567
4178
  onClick && "cursor-pointer",
3568
- classNames?.root,
3569
4179
  className
3570
4180
  ),
4181
+ classNames: {
4182
+ root: classNames?.root,
4183
+ content: "items-center justify-center"
4184
+ },
3571
4185
  children: [
3572
4186
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
3573
4187
  /* @__PURE__ */ jsx(NIcon, { icon, className: cn("w-4 h-4", iconColor ?? "text-primary", classNames?.icon) }),
@@ -3700,6 +4314,22 @@ function NViewBody({ children, className, variant = "table" }) {
3700
4314
  function NContextMenu({ x, y, items, onAction, onClose, className }) {
3701
4315
  const [openSub, setOpenSub] = useState(null);
3702
4316
  const menuRef = useRef(null);
4317
+ const [pos, setPos] = useState({ left: x, top: y });
4318
+ useLayoutEffect(() => {
4319
+ if (!menuRef.current) return;
4320
+ const rect = menuRef.current.getBoundingClientRect();
4321
+ const pad = 8;
4322
+ const vw = window.innerWidth;
4323
+ const vh = window.innerHeight;
4324
+ let left = x;
4325
+ let top = y;
4326
+ if (left + rect.width > vw - pad) left = Math.max(pad, vw - pad - rect.width);
4327
+ if (top + rect.height > vh - pad) top = Math.max(pad, vh - pad - rect.height);
4328
+ const next = { left, top };
4329
+ setPos(
4330
+ (prev) => prev.left === next.left && prev.top === next.top ? prev : next
4331
+ );
4332
+ }, [x, y]);
3703
4333
  useEffect(() => {
3704
4334
  const onKey = (e) => {
3705
4335
  if (e.key === "Escape") onClose();
@@ -3733,12 +4363,12 @@ function NContextMenu({ x, y, items, onAction, onClose, className }) {
3733
4363
  "fixed z-50 w-48 rounded-lg border border-border bg-popover py-1 shadow-xl text-popover-foreground",
3734
4364
  className
3735
4365
  ),
3736
- style: { left: x, top: y },
4366
+ style: { left: pos.left, top: pos.top },
3737
4367
  onContextMenu: (e) => e.preventDefault(),
3738
4368
  children: items.map((item) => {
3739
4369
  const Icon2 = item.icon;
3740
4370
  const hasSub = !!item.submenu?.length;
3741
- return /* @__PURE__ */ jsxs(React32__default.Fragment, { children: [
4371
+ return /* @__PURE__ */ jsxs(React38__default.Fragment, { children: [
3742
4372
  item.separatorBefore && /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-border/60" }),
3743
4373
  /* @__PURE__ */ jsxs(
3744
4374
  "div",
@@ -4129,7 +4759,7 @@ function FloatingSelectSegment({
4129
4759
  ]
4130
4760
  }
4131
4761
  ),
4132
- /* @__PURE__ */ jsx(DropdownMenuContent, { side: "top", align: "center", className: "max-h-72 overflow-y-auto", children: action.options.map((o) => /* @__PURE__ */ jsx(
4762
+ /* @__PURE__ */ jsx(DropdownMenuContent, { side: "top", align: "center", className: "max-h-72 najm-overlay-scroll-y", children: action.options.map((o) => /* @__PURE__ */ jsx(
4133
4763
  DropdownMenuItem,
4134
4764
  {
4135
4765
  onSelect: () => void onAction(action.id, o.value),
@@ -4541,29 +5171,62 @@ function UploaderRow({ item, onCancel, onRemove }) {
4541
5171
  }
4542
5172
  );
4543
5173
  }
5174
+ var NO_SHADE = /* @__PURE__ */ new Set(["black", "white"]);
5175
+ var PRESETS = {
5176
+ muted: "border-muted-foreground",
5177
+ primary: "border-primary",
5178
+ accent: "border-accent",
5179
+ success: "border-green-600",
5180
+ warning: "border-amber-600",
5181
+ destructive: "border-red-600"
5182
+ };
4544
5183
  var inputVariants = cva(
4545
- "relative w-full flex items-center border dark:bg-input/30 overflow-hidden bg-none",
5184
+ "relative w-full flex items-center h-10 bg-card overflow-hidden transition-colors",
4546
5185
  {
4547
5186
  variants: {
4548
5187
  variant: {
4549
5188
  default: "p-2 rounded-md",
4550
5189
  rounded: "p-2 rounded-full",
4551
- ghost: "border-none p-0! !bg-transparent !bg-none"
5190
+ ghost: "p-0! !bg-transparent !bg-none"
4552
5191
  },
4553
5192
  status: {
4554
- default: "border-muted-foreground/20",
4555
- error: "border-2 border-red-500"
5193
+ default: "",
5194
+ error: ""
4556
5195
  },
4557
5196
  hasIcon: { true: "pl-8", false: "pl-3" },
4558
5197
  disabled: { true: "cursor-not-allowed", false: "" }
4559
5198
  },
4560
- defaultVariants: { variant: "default", status: "default", hasIcon: false, disabled: false },
4561
- compoundVariants: [
4562
- { variant: ["default", "rounded"], disabled: false, class: "hover:border-primary dark:hover:bg-input/50" }
4563
- ]
5199
+ defaultVariants: { variant: "default", status: "default", hasIcon: false, disabled: false }
5200
+ }
5201
+ );
5202
+ var BORDER_INTERACTIVE = "border hover:border-primary focus-within:border-primary";
5203
+ 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) => {
5206
+ const isGhost = variant === "ghost";
5207
+ 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`) : "";
5211
+ return /* @__PURE__ */ jsx(
5212
+ "div",
5213
+ {
5214
+ ref,
5215
+ className: cn(
5216
+ inputVariants({ variant, status, hasIcon, disabled }),
5217
+ showBorder && (isError ? ERROR_BORDER : BORDER_INTERACTIVE),
5218
+ showBorder && colorClass,
5219
+ className
5220
+ ),
5221
+ onMouseEnter: disabled ? void 0 : onHover,
5222
+ onClick: disabled ? void 0 : onClick,
5223
+ ...rest,
5224
+ children
5225
+ }
5226
+ );
4564
5227
  }
4565
5228
  );
4566
- var BaseInput = ({ children, variant = "default", status = "default", hasIcon = false, className = "", disabled = false, onHover, onClick }) => /* @__PURE__ */ jsx("div", { className: cn(inputVariants({ variant, status, hasIcon, disabled }), className), onMouseEnter: disabled ? void 0 : onHover, onClick: disabled ? void 0 : onClick, children });
5229
+ BaseInput.displayName = "BaseInput";
4567
5230
  function getIconColorProps(iconColor, baseClassName = "") {
4568
5231
  if (!iconColor) return { className: cn(baseClassName, "text-muted-foreground"), style: {} };
4569
5232
  if (iconColor.startsWith("text-")) return { className: cn(baseClassName, iconColor), style: {} };
@@ -4571,40 +5234,35 @@ function getIconColorProps(iconColor, baseClassName = "") {
4571
5234
  }
4572
5235
  function resolveIcon(icon) {
4573
5236
  if (!icon) return null;
4574
- if (typeof icon === "string") {
4575
- return React32__default.createElement("span", { className: "text-xs font-medium" }, icon.charAt(0).toUpperCase());
4576
- }
4577
- if (React32__default.isValidElement(icon)) return icon;
4578
- if (typeof icon === "function") return React32__default.createElement(icon, { className: "h-4 w-4" });
4579
- return icon;
5237
+ return /* @__PURE__ */ jsx(NIcon, { icon, size: 16 });
4580
5238
  }
4581
- var TextInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", disabled = false, ...props }) => {
5239
+ var TextInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered = false, borderColor, disabled = false, ...props }) => {
4582
5240
  const shouldDisplayIcon = Boolean(icon) && showIcon;
4583
5241
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
4584
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, className: cn("h-9 gap-2", className), disabled, children: [
5242
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), disabled, children: [
4585
5243
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
4586
5244
  /* @__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 })
4587
5245
  ] });
4588
5246
  };
4589
- var NumberInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default" }) => {
5247
+ var NumberInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered = false, borderColor }) => {
4590
5248
  const shouldDisplayIcon = Boolean(icon) && showIcon;
4591
5249
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
4592
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, className: cn("h-9 gap-2", className), children: [
5250
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), children: [
4593
5251
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
4594
5252
  /* @__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" })
4595
5253
  ] });
4596
5254
  };
4597
- var PasswordInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default" }) => {
5255
+ var PasswordInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered = false, borderColor }) => {
4598
5256
  const [showPassword, setShowPassword] = useState(false);
4599
5257
  const shouldDisplayIcon = Boolean(icon) && showIcon;
4600
5258
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
4601
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, className: cn("h-9 gap-2", className), children: [
5259
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), children: [
4602
5260
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
4603
5261
  /* @__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" }),
4604
5262
  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) })
4605
5263
  ] });
4606
5264
  };
4607
- var TextAreaInput = ({ value, onChange, placeholder = "", className = "", variant = "default", status = "default", rows }) => /* @__PURE__ */ jsx(BaseInput, { variant, status, className: cn("items-start", className), children: /* @__PURE__ */ jsx(
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(
4608
5266
  Textarea,
4609
5267
  {
4610
5268
  rows,
@@ -4621,18 +5279,33 @@ function renderItems(items) {
4621
5279
  return /* @__PURE__ */ jsx(SelectItem, { value, children: label }, value);
4622
5280
  });
4623
5281
  }
4624
- var SelectInput = ({ placeholder = "", value, onChange, icon, showIcon = true, iconColor, items, className = "", variant = "default", status = "default", disabled = false }) => {
5282
+ var SelectInput = ({ placeholder = "", value, onChange, icon, showIcon = true, iconColor, items, className = "", variant = "default", status = "default", bordered = false, borderColor, disabled = false }) => {
4625
5283
  const shouldDisplayIcon = Boolean(icon) && showIcon && !value;
4626
5284
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
4627
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, className: cn("h-9 gap-2", className), children: [
4628
- shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5285
+ const displayLabel = value ? (() => {
5286
+ const found = items.find((i) => typeof i === "string" ? i === value : i.value === value);
5287
+ return typeof found === "string" ? found : found?.label ?? value;
5288
+ })() : "";
5289
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
5290
+ /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: "pointer-events-none", children: [
5291
+ shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5292
+ /* @__PURE__ */ jsx("span", { className: cn("flex-1 truncate text-sm", !displayLabel && "text-muted-foreground"), children: displayLabel || placeholder }),
5293
+ /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 shrink-0 opacity-50" })
5294
+ ] }),
4629
5295
  /* @__PURE__ */ jsxs(Select, { onValueChange: onChange, value: String(value || ""), disabled, children: [
4630
- /* @__PURE__ */ jsx(SelectTrigger, { className: "w-full cursor-pointer border-0 shadow-none focus-visible:ring-0 dark:bg-transparent text-muted-foreground gap-2 p-0 bg-transparent dark:hover:bg-transparent", style: { border: "none", boxShadow: "none" }, disabled, children: /* @__PURE__ */ jsx(SelectValue, { placeholder }) }),
4631
- /* @__PURE__ */ jsx(SelectContent, { className: "max-h-[300px] w-full overflow-y-auto", children: renderItems(items) })
5296
+ /* @__PURE__ */ jsx(
5297
+ SelectTrigger,
5298
+ {
5299
+ className: "absolute inset-0 w-full h-full opacity-0",
5300
+ disabled,
5301
+ "aria-label": placeholder || "Select"
5302
+ }
5303
+ ),
5304
+ /* @__PURE__ */ jsx(SelectContent, { children: renderItems(items) })
4632
5305
  ] }, String(value))
4633
5306
  ] });
4634
5307
  };
4635
- var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...", emptyMessage = "No results found.", value, onChange, icon, showIcon = true, iconColor, items = [], className = "", variant = "default", status = "default", disabled = false, allowFreeText = false }) => {
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 }) => {
4636
5309
  const [open, setOpen] = useState(false);
4637
5310
  const [query, setQuery] = useState("");
4638
5311
  const normalizedItems = items.map((item) => typeof item === "string" ? { value: item, label: item } : item);
@@ -4648,52 +5321,50 @@ var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...
4648
5321
  setOpen(false);
4649
5322
  setQuery("");
4650
5323
  };
4651
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, className: cn("h-9", className), children: [
4652
- shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
4653
- /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: (o) => {
4654
- setOpen(o);
4655
- if (!o) setQuery("");
4656
- }, children: [
4657
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(Button, { variant: "ghost", role: "combobox", "aria-expanded": open, className: cn("w-full justify-between h-auto font-normal hover:bg-transparent border-0 shadow-none focus-visible:ring-0", !displayLabel && "text-muted-foreground"), disabled, children: [
4658
- /* @__PURE__ */ jsx("span", { className: "truncate", children: displayLabel || placeholder }),
4659
- /* @__PURE__ */ jsx(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-50" })
4660
- ] }) }),
4661
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-[var(--radix-popover-trigger-width)] p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { children: [
4662
- /* @__PURE__ */ jsx(
4663
- CommandInput,
4664
- {
4665
- placeholder: searchPlaceholder,
4666
- className: "h-9",
4667
- value: query,
4668
- onValueChange: setQuery,
4669
- onKeyDown: (e) => {
4670
- if (e.key === "Enter" && showFreeTextOption) {
4671
- e.preventDefault();
4672
- commit(trimmedQuery);
4673
- }
5324
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: (o) => {
5325
+ setOpen(o);
5326
+ if (!o) setQuery("");
5327
+ }, children: [
5328
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("cursor-pointer", className), children: [
5329
+ shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5330
+ /* @__PURE__ */ jsx("span", { className: cn("flex-1 truncate text-sm", !displayLabel && "text-muted-foreground"), children: displayLabel || placeholder }),
5331
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-50" })
5332
+ ] }) }),
5333
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-[var(--radix-popover-trigger-width)] p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { children: [
5334
+ /* @__PURE__ */ jsx(
5335
+ CommandInput,
5336
+ {
5337
+ placeholder: searchPlaceholder,
5338
+ className: "h-9",
5339
+ value: query,
5340
+ onValueChange: setQuery,
5341
+ onKeyDown: (e) => {
5342
+ if (e.key === "Enter" && showFreeTextOption) {
5343
+ e.preventDefault();
5344
+ commit(trimmedQuery);
4674
5345
  }
4675
5346
  }
4676
- ),
4677
- /* @__PURE__ */ jsxs(CommandList, { children: [
4678
- /* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
4679
- /* @__PURE__ */ jsxs(CommandGroup, { children: [
4680
- showFreeTextOption && /* @__PURE__ */ jsxs(CommandItem, { value: trimmedQuery, onSelect: () => commit(trimmedQuery), className: "cursor-pointer", children: [
4681
- /* @__PURE__ */ jsx(Check, { className: "mr-2 h-4 w-4 opacity-0" }),
4682
- 'Use "',
4683
- trimmedQuery,
4684
- '"'
4685
- ] }, "__free_text__"),
4686
- normalizedItems.map((item) => /* @__PURE__ */ jsxs(CommandItem, { value: item.label, keywords: [item.value, item.label], onSelect: () => commit(value === item.value ? "" : item.value), className: "cursor-pointer", children: [
4687
- /* @__PURE__ */ jsx(Check, { className: cn("mr-2 h-4 w-4", value === item.value ? "opacity-100" : "opacity-0") }),
4688
- item.label
4689
- ] }, item.value))
4690
- ] })
5347
+ }
5348
+ ),
5349
+ /* @__PURE__ */ jsxs(CommandList, { children: [
5350
+ /* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
5351
+ /* @__PURE__ */ jsxs(CommandGroup, { children: [
5352
+ showFreeTextOption && /* @__PURE__ */ jsxs(CommandItem, { value: trimmedQuery, onSelect: () => commit(trimmedQuery), className: "cursor-pointer", children: [
5353
+ /* @__PURE__ */ jsx(Check, { className: "mr-2 h-4 w-4 opacity-0" }),
5354
+ 'Use "',
5355
+ trimmedQuery,
5356
+ '"'
5357
+ ] }, "__free_text__"),
5358
+ normalizedItems.map((item) => /* @__PURE__ */ jsxs(CommandItem, { value: item.label, keywords: [item.value, item.label], onSelect: () => commit(value === item.value ? "" : item.value), className: "cursor-pointer", children: [
5359
+ /* @__PURE__ */ jsx(Check, { className: cn("mr-2 h-4 w-4", value === item.value ? "opacity-100" : "opacity-0") }),
5360
+ item.label
5361
+ ] }, item.value))
4691
5362
  ] })
4692
- ] }) })
4693
- ] })
5363
+ ] })
5364
+ ] }) })
4694
5365
  ] });
4695
5366
  };
4696
- var MultiSelectInput = ({ placeholder = "Select items...", value = [], onChange, icon, showIcon = true, iconColor, items, className = "", variant = "default", status = "default", disabled = false, searchPlaceholder = "Search...", emptyMessage = "No items found.", maxDisplay = 3, showSearch = true }) => {
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 }) => {
4697
5368
  const [open, setOpen] = useState(false);
4698
5369
  const shouldDisplayIcon = Boolean(icon) && showIcon && value.length === 0;
4699
5370
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
@@ -4706,44 +5377,42 @@ var MultiSelectInput = ({ placeholder = "Select items...", value = [], onChange,
4706
5377
  };
4707
5378
  const displayedItems = value.slice(0, maxDisplay);
4708
5379
  const remainingCount = value.length - maxDisplay;
4709
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, className: cn("h-9 gap-2", className), children: [
4710
- shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
4711
- /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
4712
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs("div", { className: cn("w-full flex items-center justify-between cursor-pointer h-full", disabled && "cursor-not-allowed opacity-50"), children: [
4713
- /* @__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: [
4714
- displayedItems.map((itemValue) => /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "text-xs px-2 py-0.5 gap-1", children: [
4715
- getItemLabel(itemValue),
4716
- !disabled && /* @__PURE__ */ jsx("button", { type: "button", onClick: (e) => {
4717
- e.stopPropagation();
4718
- onChange(value.filter((v) => v !== itemValue));
4719
- }, className: "ml-1 hover:text-destructive", children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" }) })
4720
- ] }, itemValue)),
4721
- remainingCount > 0 && /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "text-xs px-2 py-0.5", children: [
4722
- "+",
4723
- remainingCount,
4724
- " more"
4725
- ] })
4726
- ] }) }),
4727
- open ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4 text-muted-foreground ml-2 shrink-0" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 text-muted-foreground ml-2 shrink-0" })
5380
+ 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: [
5382
+ shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5383
+ /* @__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
+ displayedItems.map((itemValue) => /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "text-xs px-2 py-0.5 gap-1", children: [
5385
+ getItemLabel(itemValue),
5386
+ !disabled && /* @__PURE__ */ jsx("button", { type: "button", onClick: (e) => {
5387
+ e.stopPropagation();
5388
+ onChange(value.filter((v) => v !== itemValue));
5389
+ }, className: "ml-1 hover:text-destructive", children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" }) })
5390
+ ] }, itemValue)),
5391
+ remainingCount > 0 && /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "text-xs px-2 py-0.5", children: [
5392
+ "+",
5393
+ remainingCount,
5394
+ " more"
5395
+ ] })
4728
5396
  ] }) }),
4729
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-[var(--radix-popover-trigger-width)] p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { children: [
4730
- showSearch && /* @__PURE__ */ jsx(CommandInput, { placeholder: searchPlaceholder, className: "h-9" }),
4731
- /* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
4732
- /* @__PURE__ */ jsx(CommandGroup, { className: "max-h-[300px] overflow-y-auto", children: items.map((item) => {
4733
- const itemValue = typeof item === "string" ? item : item.value;
4734
- const itemLabel = typeof item === "string" ? item : item.label;
4735
- const isSelected = value.includes(itemValue);
4736
- return /* @__PURE__ */ jsxs(CommandItem, { onSelect: () => handleSelect(itemValue), className: "flex items-center gap-2 cursor-pointer", children: [
4737
- /* @__PURE__ */ jsx(Checkbox, { checked: isSelected, onCheckedChange: () => handleSelect(itemValue), className: "pointer-events-none" }),
4738
- /* @__PURE__ */ jsx("span", { className: "flex-1", children: itemLabel })
4739
- ] }, itemValue);
4740
- }) })
4741
- ] }) })
4742
- ] })
5397
+ open ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4 text-muted-foreground ml-2 shrink-0" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 text-muted-foreground ml-2 shrink-0" })
5398
+ ] }) }),
5399
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-[var(--radix-popover-trigger-width)] p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { children: [
5400
+ showSearch && /* @__PURE__ */ jsx(CommandInput, { placeholder: searchPlaceholder, className: "h-9" }),
5401
+ /* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
5402
+ /* @__PURE__ */ jsx(CommandGroup, { className: "max-h-[300px] najm-overlay-scroll-y", children: items.map((item) => {
5403
+ const itemValue = typeof item === "string" ? item : item.value;
5404
+ const itemLabel = typeof item === "string" ? item : item.label;
5405
+ const isSelected = value.includes(itemValue);
5406
+ return /* @__PURE__ */ jsxs(CommandItem, { onSelect: () => handleSelect(itemValue), className: "flex items-center gap-2 cursor-pointer", children: [
5407
+ /* @__PURE__ */ jsx(Checkbox, { checked: isSelected, onCheckedChange: () => handleSelect(itemValue), className: "pointer-events-none" }),
5408
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children: itemLabel })
5409
+ ] }, itemValue);
5410
+ }) })
5411
+ ] }) })
4743
5412
  ] });
4744
5413
  };
4745
5414
  var layoutVariants = cva("flex items-start", { variants: { layout: { column: "flex-col gap-4", row: "flex-row gap-7" } }, defaultVariants: { layout: "row" } });
4746
- var RadioGroupInput = ({ value, onChange, className = "", variant = "default", status = "default", layout = "row", items }) => /* @__PURE__ */ jsx(BaseInput, { variant, status, className, children: /* @__PURE__ */ jsx(RadioGroup2, { onValueChange: onChange, value, className: layoutVariants({ layout }), children: items.map((item) => {
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) => {
4747
5416
  const itemValue = typeof item === "string" ? item : item.value;
4748
5417
  const itemLabel = typeof item === "string" ? item : item.label;
4749
5418
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center space-y-0", children: [
@@ -4751,7 +5420,7 @@ var RadioGroupInput = ({ value, onChange, className = "", variant = "default", s
4751
5420
  /* @__PURE__ */ jsx(Label, { className: "text-sm font-normal peer-disabled:opacity-70 ml-1", children: itemLabel })
4752
5421
  ] }, itemValue);
4753
5422
  }) }) });
4754
- var CheckboxInput = ({ value, onChange, helper, label, checkboxClassName, className, variant = "default", status = "default" }) => /* @__PURE__ */ jsxs(BaseInput, { variant, status, className: cn("flex gap-2 items-center h-9", className), children: [
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: [
4755
5424
  /* @__PURE__ */ jsx(Checkbox, { checked: value, onCheckedChange: onChange, className: cn("cursor-pointer transition-colors duration-200 border-primary", checkboxClassName) }),
4756
5425
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
4757
5426
  /* @__PURE__ */ jsx(Label, { className: "cursor-pointer text-muted-foreground", onClick: () => onChange(!value), children: label }),
@@ -4775,13 +5444,15 @@ function CheckboxGroupInput({
4775
5444
  className,
4776
5445
  variant = "default",
4777
5446
  status = "default",
5447
+ bordered = false,
5448
+ borderColor,
4778
5449
  disabled = false
4779
5450
  }) {
4780
5451
  const handleChange = (itemValue, checked) => {
4781
5452
  const next = checked ? [...value, itemValue] : value.filter((v) => v !== itemValue);
4782
5453
  onChange(next);
4783
5454
  };
4784
- return /* @__PURE__ */ jsx(BaseInput, { variant, status, className: cn("flex-wrap", className), disabled, children: /* @__PURE__ */ jsx("div", { className: cn(layoutVariants2({ layout })), children: items.map((item) => {
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) => {
4785
5456
  const itemValue = typeof item === "string" ? item : item.value;
4786
5457
  const itemLabel = typeof item === "string" ? item : item.label;
4787
5458
  const checked = value.includes(itemValue);
@@ -4798,7 +5469,7 @@ function CheckboxGroupInput({
4798
5469
  ] }, itemValue);
4799
5470
  }) }) });
4800
5471
  }
4801
- var SwitchInput = ({ value, onChange, label = "", helper, className = "", variant = "default", status = "default", icon, showIcon = true, iconPosition = "label", iconColor }) => /* @__PURE__ */ jsxs(BaseInput, { variant, status, className: cn("gap-2 justify-between items-center", className), children: [
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: [
4802
5473
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
4803
5474
  /* @__PURE__ */ jsxs(Label, { className: "flex items-center gap-2", children: [
4804
5475
  iconPosition === "label" && icon && showIcon && /* @__PURE__ */ jsx("span", { className: "w-4 h-4", children: resolveIcon(icon) }),
@@ -4811,10 +5482,10 @@ var SwitchInput = ({ value, onChange, label = "", helper, className = "", varian
4811
5482
  /* @__PURE__ */ jsx(Switch, { checked: value, onCheckedChange: onChange })
4812
5483
  ] })
4813
5484
  ] });
4814
- var DateInput = ({ value, onChange, placeholder = "Pick a date", className = "", icon, showIcon = true, iconColor, variant = "default", status = "default" }) => {
5485
+ var DateInput = ({ value, onChange, placeholder = "Pick a date", className = "", icon, showIcon = true, iconColor, variant = "default", status = "default", bordered = false, borderColor }) => {
4815
5486
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
4816
5487
  const toDateString = (date) => date?.toISOString().split("T")[0];
4817
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, className: cn("h-9", className), children: [
5488
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className, children: [
4818
5489
  /* @__PURE__ */ jsxs(Popover, { children: [
4819
5490
  /* @__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 }) }) }),
4820
5491
  /* @__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" }) })
@@ -4829,7 +5500,7 @@ function truncateFilename(filename, maxLength = 25) {
4829
5500
  const name = extIndex !== -1 ? filename.slice(0, extIndex) : filename;
4830
5501
  return `${name.slice(0, maxLength - ext.length - 3)}...${ext}`;
4831
5502
  }
4832
- var FileInput = ({ value, onChange, placeholder = "No file chosen", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default" }) => {
5503
+ var FileInput = ({ value, onChange, placeholder = "No file chosen", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered = false, borderColor }) => {
4833
5504
  const fileInputRef = useRef(null);
4834
5505
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
4835
5506
  const displayFilename = () => {
@@ -4837,7 +5508,7 @@ var FileInput = ({ value, onChange, placeholder = "No file chosen", icon, showIc
4837
5508
  const filename = typeof value === "string" ? value.split(/[\\/]/).pop() || "" : value.name;
4838
5509
  return truncateFilename(filename);
4839
5510
  };
4840
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, className: cn("flex h-9 px-0 p-0 text-muted-foreground", className), onClick: () => fileInputRef.current?.click(), children: [
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: [
4841
5512
  /* @__PURE__ */ jsx("input", { type: "file", ref: fileInputRef, onChange: (e) => onChange(e.target.files?.[0] || null), className: "hidden" }),
4842
5513
  /* @__PURE__ */ jsxs("div", { className: "bg-muted flex h-full items-center px-3", children: [
4843
5514
  showIcon && (icon ? /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }) : /* @__PURE__ */ jsx(FileUp, { className: cn(iconProps.className) })),
@@ -4966,14 +5637,14 @@ function ImageInput({
4966
5637
  renderFileInput()
4967
5638
  ] });
4968
5639
  }
4969
- var StarRatingInput = ({ value, onChange, maxStars = 5, className = "", variant = "default", status = "default" }) => {
5640
+ var StarRatingInput = ({ value, onChange, maxStars = 5, className = "", variant = "default", status = "default", bordered = false, borderColor }) => {
4970
5641
  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));
4971
- return /* @__PURE__ */ jsx(BaseInput, { variant, status, className: cn("gap-2", className), children: stars });
5642
+ return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), children: stars });
4972
5643
  };
4973
5644
  var DEFAULT_COLORS = ["#222222", "#e11d48", "#ea580c", "#16a34a", "#db2777", "#2563eb", "#9333ea", "#eab308"];
4974
- var ColorArrayInput = ({ value, onChange, className = "", variant = "default", status = "default", colors = DEFAULT_COLORS }) => {
5645
+ var ColorArrayInput = ({ value, onChange, className = "", variant = "default", status = "default", bordered = false, borderColor, colors = DEFAULT_COLORS }) => {
4975
5646
  const [selectedColor, setSelectedColor] = useState(value || "");
4976
- return /* @__PURE__ */ jsx(BaseInput, { variant, status, 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: () => {
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: () => {
4977
5648
  setSelectedColor(color);
4978
5649
  onChange(color);
4979
5650
  }, 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)) });
@@ -5007,6 +5678,8 @@ function ColorPickerInput({
5007
5678
  className,
5008
5679
  variant = "default",
5009
5680
  status = "default",
5681
+ bordered = false,
5682
+ borderColor,
5010
5683
  disabled = false
5011
5684
  }) {
5012
5685
  const inputRef = useRef(null);
@@ -5015,6 +5688,8 @@ function ColorPickerInput({
5015
5688
  {
5016
5689
  variant,
5017
5690
  status,
5691
+ bordered,
5692
+ borderColor,
5018
5693
  className: cn("flex-col gap-3 items-start p-3", className),
5019
5694
  disabled,
5020
5695
  onClick: () => inputRef.current?.click(),
@@ -5101,6 +5776,8 @@ function EmojiInput({
5101
5776
  className,
5102
5777
  variant = "default",
5103
5778
  status = "default",
5779
+ bordered = false,
5780
+ borderColor,
5104
5781
  disabled = false
5105
5782
  }) {
5106
5783
  return /* @__PURE__ */ jsx(
@@ -5108,6 +5785,8 @@ function EmojiInput({
5108
5785
  {
5109
5786
  variant,
5110
5787
  status,
5788
+ bordered,
5789
+ borderColor,
5111
5790
  className: cn("gap-3 flex-wrap", className),
5112
5791
  disabled,
5113
5792
  children: options.map((opt) => /* @__PURE__ */ jsxs(
@@ -5176,7 +5855,9 @@ function PhoneInput({
5176
5855
  disabled = false,
5177
5856
  className,
5178
5857
  variant = "default",
5179
- status = "default"
5858
+ status = "default",
5859
+ bordered = false,
5860
+ borderColor
5180
5861
  }) {
5181
5862
  const phoneThemeVars = {
5182
5863
  "--react-international-phone-height": "40px",
@@ -5200,7 +5881,7 @@ function PhoneInput({
5200
5881
  "--react-international-phone-dropdown-preferred-list-divider-color": "hsl(var(--najm-border))",
5201
5882
  "--react-international-phone-dropdown-shadow": "0 16px 40px hsl(var(--najm-background) / 0.45)"
5202
5883
  };
5203
- return /* @__PURE__ */ jsx(BaseInput, { variant, status, className: cn("h-10 gap-0 overflow-visible p-0!", className), disabled, children: /* @__PURE__ */ jsx(
5884
+ return /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-0 overflow-visible p-0!", className), disabled, children: /* @__PURE__ */ jsx(
5204
5885
  PhoneInput$1,
5205
5886
  {
5206
5887
  className: "w-full",
@@ -5260,7 +5941,7 @@ function PhoneInput({
5260
5941
  }
5261
5942
  ) });
5262
5943
  }
5263
- var TimeInput = ({ value = "", onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", format24 = true, showSeconds = false, disabled = false }) => {
5944
+ var TimeInput = ({ value = "", onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered = false, borderColor, format24 = true, showSeconds = false, disabled = false }) => {
5264
5945
  const [inputValue, setInputValue] = useState(value);
5265
5946
  const [isValid, setIsValid] = useState(true);
5266
5947
  useEffect(() => {
@@ -5308,44 +5989,210 @@ var TimeInput = ({ value = "", onChange, placeholder = "", icon, showIcon = true
5308
5989
  };
5309
5990
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5310
5991
  const currentStatus = !isValid ? "error" : status;
5311
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status: currentStatus, className: cn("h-9 gap-2", className), children: [
5992
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status: currentStatus, bordered, borderColor, className: cn("gap-2", className), children: [
5312
5993
  showIcon && (icon ? /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }) : /* @__PURE__ */ jsx(Clock, { className: iconProps.className, style: iconProps.style })),
5313
5994
  /* @__PURE__ */ jsx(Input, { type: "text", placeholder: placeholder || (showSeconds ? "HH:MM:SS" : "HH:MM"), value: inputValue, onChange: (e) => handleInputChange(e.target.value), onKeyDown: (e) => {
5314
5995
  if (!/\d/.test(e.key) && !["Backspace", "Delete", "ArrowLeft", "ArrowRight", "Tab"].includes(e.key)) e.preventDefault();
5315
5996
  }, onBlur: handleBlur, disabled, className: cn("p-0 border-0 shadow-none bg-transparent dark:bg-transparent focus-visible:ring-0", !isValid ? "text-red-500" : "text-muted-foreground") })
5316
5997
  ] });
5317
5998
  };
5318
- function Slider({ value, onValueChange, min = 0, max = 100, step = 1, className, disabled }) {
5319
- const percentage = (value[0] - min) / (max - min) * 100;
5320
- return /* @__PURE__ */ jsxs("div", { className: cn("relative flex w-full touch-none select-none items-center h-5", className), children: [
5321
- /* @__PURE__ */ jsx("div", { className: "relative h-2 w-full grow overflow-hidden rounded-full bg-border", children: /* @__PURE__ */ jsx(
5322
- "div",
5323
- {
5324
- className: "absolute h-full bg-brand rounded-full",
5325
- style: { width: `${percentage}%` }
5326
- }
5327
- ) }),
5328
- /* @__PURE__ */ jsx(
5329
- "div",
5330
- {
5331
- className: "absolute h-5 w-5 rounded-full bg-brand border-2 border-bg shadow-md pointer-events-none transition-transform",
5332
- style: { left: `calc(${percentage}% - 10px)` }
5333
- }
5334
- ),
5335
- /* @__PURE__ */ jsx(
5336
- "input",
5337
- {
5338
- type: "range",
5339
- min,
5340
- max,
5341
- step,
5342
- value: value[0],
5343
- onChange: (e) => onValueChange([Number(e.target.value)]),
5344
- disabled,
5345
- className: "absolute inset-0 w-full h-full opacity-0 cursor-pointer"
5999
+ var RANGE_COLOR = {
6000
+ default: "bg-primary",
6001
+ secondary: "bg-secondary",
6002
+ destructive: "bg-destructive",
6003
+ accent: "bg-accent",
6004
+ success: "bg-emerald-500",
6005
+ warning: "bg-amber-500",
6006
+ info: "bg-sky-500"
6007
+ };
6008
+ var THUMB_COLOR = {
6009
+ default: "border-primary",
6010
+ secondary: "border-secondary",
6011
+ destructive: "border-destructive",
6012
+ accent: "border-accent",
6013
+ success: "border-emerald-500",
6014
+ warning: "border-amber-500",
6015
+ info: "border-sky-500"
6016
+ };
6017
+ var TRACK_SIZE = {
6018
+ sm: { horizontal: "h-1", vertical: "w-1" },
6019
+ md: { horizontal: "h-1.5", vertical: "w-1.5" },
6020
+ lg: { horizontal: "h-2", vertical: "w-2" }
6021
+ };
6022
+ var THUMB_SIZE = {
6023
+ sm: "size-3",
6024
+ md: "size-4",
6025
+ lg: "size-5"
6026
+ };
6027
+ var sliderVariants = cva(
6028
+ "relative flex touch-none select-none",
6029
+ {
6030
+ variants: {
6031
+ size: {
6032
+ sm: "",
6033
+ md: "",
6034
+ lg: ""
6035
+ },
6036
+ orientation: {
6037
+ horizontal: "w-full items-center",
6038
+ vertical: "h-full flex-col"
5346
6039
  }
5347
- )
5348
- ] });
6040
+ },
6041
+ defaultVariants: {
6042
+ size: "md",
6043
+ orientation: "horizontal"
6044
+ }
6045
+ }
6046
+ );
6047
+ function NSlider({
6048
+ value: controlledValue,
6049
+ defaultValue,
6050
+ onValueChange,
6051
+ min = 0,
6052
+ max = 100,
6053
+ step = 1,
6054
+ variant = "default",
6055
+ size = "md",
6056
+ orientation = "horizontal",
6057
+ disabled = false,
6058
+ showTooltip = false,
6059
+ formatTooltip,
6060
+ dir,
6061
+ name,
6062
+ className,
6063
+ "aria-label": ariaLabel,
6064
+ "aria-labelledby": ariaLabelledBy,
6065
+ ...rest
6066
+ }) {
6067
+ const isRangeMode = (v) => {
6068
+ if (v === void 0) return false;
6069
+ return Array.isArray(v) && v.length === 2;
6070
+ };
6071
+ const rangeMode = isRangeMode(controlledValue ?? defaultValue);
6072
+ const toRadix = (v) => {
6073
+ if (v === void 0) return rangeMode ? [min, max] : [min];
6074
+ return Array.isArray(v) ? [...v] : [v];
6075
+ };
6076
+ const initialRadix = toRadix(controlledValue ?? defaultValue);
6077
+ const [internalValues, setInternalValues] = React38.useState(initialRadix);
6078
+ const [active, setActive] = React38.useState(null);
6079
+ const currentValues = controlledValue !== void 0 ? toRadix(controlledValue) : internalValues;
6080
+ const handleRadix = (arr) => {
6081
+ setInternalValues(arr);
6082
+ if (onValueChange) {
6083
+ onValueChange(rangeMode ? [arr[0], arr[1]] : arr[0]);
6084
+ }
6085
+ };
6086
+ const radixValue = controlledValue !== void 0 ? toRadix(controlledValue) : void 0;
6087
+ const radixDefault = controlledValue === void 0 ? toRadix(defaultValue) : void 0;
6088
+ const fmt = formatTooltip ?? ((n) => String(Math.round(n)));
6089
+ return /* @__PURE__ */ jsxs(
6090
+ SliderPrimitive.Root,
6091
+ {
6092
+ "data-slot": "slider",
6093
+ "data-disabled": disabled ? "" : void 0,
6094
+ value: radixValue,
6095
+ defaultValue: radixDefault,
6096
+ onValueChange: handleRadix,
6097
+ min,
6098
+ max,
6099
+ step,
6100
+ orientation,
6101
+ dir,
6102
+ disabled,
6103
+ className: cn(sliderVariants({ size, orientation }), className),
6104
+ ...rest,
6105
+ children: [
6106
+ /* @__PURE__ */ jsx(
6107
+ SliderPrimitive.Track,
6108
+ {
6109
+ "data-slot": "slider-track",
6110
+ className: cn(
6111
+ "relative grow rounded-full bg-muted",
6112
+ TRACK_SIZE[size][orientation]
6113
+ ),
6114
+ children: /* @__PURE__ */ jsx(
6115
+ SliderPrimitive.Range,
6116
+ {
6117
+ "data-slot": "slider-range",
6118
+ className: cn("absolute rounded-full", RANGE_COLOR[variant])
6119
+ }
6120
+ )
6121
+ }
6122
+ ),
6123
+ currentValues.map((v, i) => /* @__PURE__ */ jsx(
6124
+ SliderPrimitive.Thumb,
6125
+ {
6126
+ "data-slot": "slider-thumb",
6127
+ "aria-label": ariaLabel,
6128
+ "aria-labelledby": ariaLabelledBy,
6129
+ onFocus: () => setActive(i),
6130
+ onBlur: () => setActive(null),
6131
+ onPointerDown: () => setActive(i),
6132
+ onPointerUp: () => setActive(null),
6133
+ className: cn(
6134
+ "block rounded-full bg-background border-2 shadow outline-none",
6135
+ "focus-visible:ring-2 focus-visible:ring-ring/50",
6136
+ "disabled:pointer-events-none",
6137
+ THUMB_SIZE[size],
6138
+ THUMB_COLOR[variant]
6139
+ ),
6140
+ children: showTooltip && active === i && /* @__PURE__ */ jsx(
6141
+ "span",
6142
+ {
6143
+ "data-slot": "slider-tooltip",
6144
+ className: cn(
6145
+ "absolute left-1/2 -translate-x-1/2 -top-7",
6146
+ "rounded bg-popover px-1.5 py-0.5 text-xs text-popover-foreground shadow-md",
6147
+ "pointer-events-none select-none whitespace-nowrap"
6148
+ ),
6149
+ children: fmt(v)
6150
+ }
6151
+ )
6152
+ },
6153
+ i
6154
+ )),
6155
+ name && currentValues.map((v, i) => /* @__PURE__ */ jsx(
6156
+ "input",
6157
+ {
6158
+ type: "hidden",
6159
+ name: i === 0 ? name : `${name}-${i}`,
6160
+ value: v
6161
+ },
6162
+ `hidden-${i}`
6163
+ ))
6164
+ ]
6165
+ }
6166
+ );
6167
+ }
6168
+ NSlider.displayName = "NSlider";
6169
+ function Slider({ value, onValueChange, ...rest }) {
6170
+ return /* @__PURE__ */ jsx(
6171
+ NSlider,
6172
+ {
6173
+ ...rest,
6174
+ value: value.length === 2 ? [value[0], value[1]] : value[0],
6175
+ onValueChange: (v) => onValueChange(Array.isArray(v) ? [...v] : [v])
6176
+ }
6177
+ );
6178
+ }
6179
+ function SliderInput({
6180
+ value,
6181
+ onChange,
6182
+ status: _status,
6183
+ icon: _icon,
6184
+ iconColor: _iconColor,
6185
+ readOnly: _readOnly,
6186
+ ...rest
6187
+ }) {
6188
+ return /* @__PURE__ */ jsx(
6189
+ NSlider,
6190
+ {
6191
+ ...rest,
6192
+ value: typeof value === "number" ? value : 0,
6193
+ onValueChange: (v) => onChange?.(Array.isArray(v) ? v[0] : v)
6194
+ }
6195
+ );
5349
6196
  }
5350
6197
  function SearchField({ value, onChange, placeholder = "Search...", className }) {
5351
6198
  return /* @__PURE__ */ jsxs("div", { className: `relative ${className ?? ""}`, children: [
@@ -5356,7 +6203,7 @@ function SearchField({ value, onChange, placeholder = "Search...", className })
5356
6203
  placeholder,
5357
6204
  value,
5358
6205
  onChange: (e) => onChange(e.target.value),
5359
- className: "pl-9 text-sm bg-card"
6206
+ className: "pl-9 text-sm"
5360
6207
  }
5361
6208
  )
5362
6209
  ] });
@@ -5418,19 +6265,19 @@ function Combobox({
5418
6265
  allowFreeText = false,
5419
6266
  disabled = false
5420
6267
  }) {
5421
- const [open, setOpen] = React32.useState(false);
5422
- const [query, setQuery] = React32.useState("");
5423
- const [highlight, setHighlight] = React32.useState(0);
5424
- const wrapperRef = React32.useRef(null);
5425
- const inputRef = React32.useRef(null);
5426
- const filtered = React32.useMemo(() => {
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(() => {
5427
6274
  const q = query.trim().toLowerCase();
5428
6275
  if (!q) return options;
5429
6276
  return options.filter(
5430
6277
  (opt) => opt.label.toLowerCase().includes(q) || opt.value.toLowerCase().includes(q)
5431
6278
  );
5432
6279
  }, [options, query]);
5433
- React32.useEffect(() => {
6280
+ React38.useEffect(() => {
5434
6281
  if (!open) return;
5435
6282
  const onClick = (e) => {
5436
6283
  if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
@@ -5441,7 +6288,7 @@ function Combobox({
5441
6288
  document.addEventListener("mousedown", onClick);
5442
6289
  return () => document.removeEventListener("mousedown", onClick);
5443
6290
  }, [open]);
5444
- React32.useEffect(() => {
6291
+ React38.useEffect(() => {
5445
6292
  if (open) {
5446
6293
  setHighlight(0);
5447
6294
  requestAnimationFrame(() => inputRef.current?.focus());
@@ -5449,7 +6296,7 @@ function Combobox({
5449
6296
  setQuery("");
5450
6297
  }
5451
6298
  }, [open]);
5452
- const selectedLabel = React32.useMemo(() => {
6299
+ const selectedLabel = React38.useMemo(() => {
5453
6300
  const match = options.find((o) => o.value === value);
5454
6301
  return match?.label ?? value;
5455
6302
  }, [options, value]);
@@ -5526,7 +6373,7 @@ function Combobox({
5526
6373
  }
5527
6374
  )
5528
6375
  ] }),
5529
- /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-y-auto py-1", children: filtered.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: allowFreeText && query.trim() ? `Press Enter to use "${query.trim()}"` : emptyText }) : filtered.map((opt, i) => /* @__PURE__ */ jsxs(
6376
+ /* @__PURE__ */ jsx("div", { className: "max-h-64 najm-overlay-scroll-y py-1", children: filtered.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: allowFreeText && query.trim() ? `Press Enter to use "${query.trim()}"` : emptyText }) : filtered.map((opt, i) => /* @__PURE__ */ jsxs(
5530
6377
  "button",
5531
6378
  {
5532
6379
  type: "button",
@@ -5570,11 +6417,12 @@ var VARIANT_PRESETS = {
5570
6417
  error: "text-xs"
5571
6418
  }
5572
6419
  };
5573
- var VariantContext = createContext("default");
5574
- var VariantProvider = ({ variant = "default", children }) => /* @__PURE__ */ jsx(VariantContext.Provider, { value: variant, children });
5575
- var useVariant = () => useContext(VariantContext);
5576
- var useVariantPreset = () => VARIANT_PRESETS[useContext(VariantContext)];
5577
- function NFormInner({ schema, defaultValues, onSubmit, form: externalForm, variant = "default", as = "form", className = "", id, devTools, children }) {
6420
+ var VariantContext = createContext({ variant: "default", bordered: false });
6421
+ var VariantProvider = ({ variant = "default", bordered = false, children }) => /* @__PURE__ */ jsx(VariantContext.Provider, { value: { variant, bordered }, children });
6422
+ var useVariant = () => useContext(VariantContext).variant;
6423
+ var useBordered = () => useContext(VariantContext).bordered;
6424
+ 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 }) {
5578
6426
  const resolver = useMemo(() => schema ? zodResolver(schema) : void 0, [schema]);
5579
6427
  const internalForm = useForm({
5580
6428
  resolver,
@@ -5606,7 +6454,7 @@ function NFormInner({ schema, defaultValues, onSubmit, form: externalForm, varia
5606
6454
  }, [form.formState.errors]);
5607
6455
  const wrapperClass = cn("flex flex-col h-full w-full gap-2", className);
5608
6456
  const submit = form.handleSubmit(onSubmit);
5609
- const inner = /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsx(VariantProvider, { variant, children: as === "form" ? /* @__PURE__ */ jsx("form", { id, onSubmit: submit, className: wrapperClass, autoComplete: "off", children }) : /* @__PURE__ */ jsx("div", { id, className: wrapperClass, onKeyDown: (e) => {
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) => {
5610
6458
  if (e.key === "Enter" && e.target.tagName !== "TEXTAREA") {
5611
6459
  e.preventDefault();
5612
6460
  void submit();
@@ -5659,7 +6507,8 @@ var Inputs = {
5659
6507
  emoji: EmojiInput,
5660
6508
  lang: LangInput,
5661
6509
  phone: PhoneInput,
5662
- time: TimeInput
6510
+ time: TimeInput,
6511
+ slider: SliderInput
5663
6512
  };
5664
6513
  var FormInput = ({ name, type, formLabel, formDescription, required = false, disabled = false, readOnly = false, hidden = false, icon, iconColor, classNames, ...rest }) => {
5665
6514
  const InputComponent = Inputs[type];
@@ -5667,12 +6516,13 @@ var FormInput = ({ name, type, formLabel, formDescription, required = false, dis
5667
6516
  const { className, onChange: consumerOnChange, ...inputRest } = rest;
5668
6517
  const prefix = usePrefix();
5669
6518
  const preset = useVariantPreset();
6519
+ const contextBordered = useBordered();
5670
6520
  const fieldName = prefix ? `${prefix}.${name}` : name;
5671
6521
  if (!InputComponent) return null;
5672
6522
  const getDefaultValue = () => {
5673
6523
  if (type === "multiselect" || type === "checkboxGroup") return [];
5674
6524
  if (type === "switch" || type === "checkbox") return false;
5675
- if (type === "starRating" || type === "emoji") return 0;
6525
+ if (type === "starRating" || type === "emoji" || type === "slider") return 0;
5676
6526
  if (type === "image" || type === "file") return null;
5677
6527
  return "";
5678
6528
  };
@@ -5693,11 +6543,11 @@ var FormInput = ({ name, type, formLabel, formDescription, required = false, dis
5693
6543
  };
5694
6544
  return /* @__PURE__ */ jsxs(FormItem, { className: slot.item, children: [
5695
6545
  formLabel && /* @__PURE__ */ jsxs(FormLabel, { className: slot.label, children: [
5696
- icon && /* @__PURE__ */ jsx("span", { className: "w-4 h-4", children: icon }),
6546
+ icon && /* @__PURE__ */ jsx(NIcon, { icon, size: 16, className: "shrink-0 text-muted-foreground" }),
5697
6547
  formLabel,
5698
6548
  required && !disabled && !readOnly && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
5699
6549
  ] }),
5700
- /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(InputComponent, { value: field.value ?? getDefaultValue(), onChange: handleChange, status: hasError && !isHidden ? "error" : "default", icon: formLabel ? void 0 : icon, iconColor: formLabel ? void 0 : iconColor, disabled, readOnly, ...inputRest, className: slot.input }) }),
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 }) }),
5701
6551
  !hasError && !disabled && !readOnly && formDescription && /* @__PURE__ */ jsx(FormDescription, { className: slot.description, children: formDescription }),
5702
6552
  !isHidden && /* @__PURE__ */ jsx(FormMessage, { className: slot.error })
5703
6553
  ] });
@@ -5843,7 +6693,7 @@ function StepsProgress({ steps, currentStep, className }) {
5843
6693
  className: cn("absolute h-0.5 mb-3 top-4", className),
5844
6694
  style: { left: `${firstStepCenter}%`, width: `${lineWidth}%` },
5845
6695
  children: [
5846
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-muted rounded-full" }),
6696
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-muted-foreground/30 rounded-full" }),
5847
6697
  /* @__PURE__ */ jsx(
5848
6698
  "div",
5849
6699
  {
@@ -6026,6 +6876,8 @@ function WizardForm({
6026
6876
  nextLabel = "Next",
6027
6877
  previousLabel = "Previous",
6028
6878
  submitLabel = "Submit",
6879
+ variant = "default",
6880
+ bordered = false,
6029
6881
  className,
6030
6882
  classNames,
6031
6883
  footerSlot
@@ -6068,38 +6920,46 @@ function WizardForm({
6068
6920
  onStepComplete?.(nav.currentStep - 1, data);
6069
6921
  await handleStepSubmit(data);
6070
6922
  };
6071
- return /* @__PURE__ */ jsxs("div", { className: cn("flex w-full flex-col gap-4", classNames?.root, className), children: [
6072
- showHeader && /* @__PURE__ */ jsx(
6073
- StepsHeader,
6074
- {
6075
- steps: nav.steps,
6076
- currentStep: nav.currentStep,
6077
- completedSteps: nav.completedSteps,
6078
- onStepClick: nav.goToStep,
6079
- classNames
6080
- }
6081
- ),
6082
- /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs(
6083
- "form",
6084
- {
6085
- id: `step-${currentStepConfig.id}`,
6086
- onSubmit: form.handleSubmit(handleSubmit),
6087
- className: cn("flex flex-col gap-4", classNames?.step),
6088
- autoComplete: "off",
6089
- children: [
6090
- currentStepConfig.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: currentStepConfig.description }),
6091
- currentStepConfig.render({ form, stepIndex: nav.currentStep - 1 })
6092
- ]
6093
- }
6094
- ) }),
6095
- showFooter && /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between", classNames?.footer), children: [
6096
- /* @__PURE__ */ jsx("div", { children: !nav.isFirstStep && /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: nav.handlePrevious, children: previousLabel }) }),
6097
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6098
- footerSlot,
6099
- nav.isLastStep ? /* @__PURE__ */ jsx(Button, { type: "submit", form: `step-${currentStepConfig.id}`, children: submitLabel }) : /* @__PURE__ */ jsx(Button, { type: "submit", form: `step-${currentStepConfig.id}`, children: nextLabel })
6100
- ] })
6101
- ] })
6102
- ] });
6923
+ return /* @__PURE__ */ jsxs(
6924
+ "div",
6925
+ {
6926
+ "data-najm-wizard-form": "true",
6927
+ "data-najm-dialog-actions": "content",
6928
+ className: cn("flex w-full flex-col gap-4", classNames?.root, className),
6929
+ children: [
6930
+ showHeader && /* @__PURE__ */ jsx(
6931
+ StepsHeader,
6932
+ {
6933
+ steps: nav.steps,
6934
+ currentStep: nav.currentStep,
6935
+ completedSteps: nav.completedSteps,
6936
+ onStepClick: nav.goToStep,
6937
+ classNames
6938
+ }
6939
+ ),
6940
+ /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsx(VariantProvider, { variant, bordered, children: /* @__PURE__ */ jsxs(
6941
+ "form",
6942
+ {
6943
+ id: `step-${currentStepConfig.id}`,
6944
+ onSubmit: form.handleSubmit(handleSubmit),
6945
+ className: cn("flex flex-col gap-4", classNames?.step),
6946
+ autoComplete: "off",
6947
+ children: [
6948
+ currentStepConfig.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: currentStepConfig.description }),
6949
+ currentStepConfig.render({ form, stepIndex: nav.currentStep - 1 })
6950
+ ]
6951
+ }
6952
+ ) }) }),
6953
+ showFooter && /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between", classNames?.footer), children: [
6954
+ /* @__PURE__ */ jsx("div", { children: !nav.isFirstStep && /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: nav.handlePrevious, children: previousLabel }) }),
6955
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6956
+ footerSlot,
6957
+ nav.isLastStep ? /* @__PURE__ */ jsx(Button, { type: "submit", form: `step-${currentStepConfig.id}`, children: submitLabel }) : /* @__PURE__ */ jsx(Button, { type: "submit", form: `step-${currentStepConfig.id}`, children: nextLabel })
6958
+ ] })
6959
+ ] })
6960
+ ]
6961
+ }
6962
+ );
6103
6963
  }
6104
6964
  var TableStoreContext = createContext(null);
6105
6965
  var useTableStore = { use: {} };
@@ -6111,15 +6971,35 @@ var handler = {
6111
6971
  }
6112
6972
  };
6113
6973
  useTableStore.use = new Proxy({}, handler);
6114
- function TableActionCell({ row, onView, onEdit, onDelete }) {
6115
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-1", onClick: (e) => e.stopPropagation(), children: [
6974
+ var actionButtonClass = (bordered, danger) => cn(
6975
+ "flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition-colors",
6976
+ danger ? "hover:bg-red-500/10 hover:text-red-400" : "hover:bg-muted hover:text-foreground",
6977
+ bordered && "border border-muted-foreground"
6978
+ );
6979
+ function TableActionCell({ row, onView, onEdit, onDelete, openRowMenu, menuButton, bordered }) {
6980
+ if (menuButton && openRowMenu) {
6981
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center gap-1", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(
6982
+ "button",
6983
+ {
6984
+ type: "button",
6985
+ "aria-label": "Row actions",
6986
+ onClick: (e) => {
6987
+ e.stopPropagation();
6988
+ openRowMenu(e, row.original);
6989
+ },
6990
+ className: actionButtonClass(false),
6991
+ children: /* @__PURE__ */ jsx(MoreVertical, { className: "h-3.5 w-3.5" })
6992
+ }
6993
+ ) });
6994
+ }
6995
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-start gap-1", onClick: (e) => e.stopPropagation(), children: [
6116
6996
  onView && /* @__PURE__ */ jsx(
6117
6997
  "button",
6118
6998
  {
6119
6999
  type: "button",
6120
7000
  "aria-label": "View",
6121
7001
  onClick: () => onView(row.original),
6122
- className: "flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
7002
+ className: actionButtonClass(bordered),
6123
7003
  children: /* @__PURE__ */ jsx(Eye, { className: "h-3.5 w-3.5" })
6124
7004
  }
6125
7005
  ),
@@ -6129,7 +7009,7 @@ function TableActionCell({ row, onView, onEdit, onDelete }) {
6129
7009
  type: "button",
6130
7010
  "aria-label": "Edit",
6131
7011
  onClick: () => onEdit(row.original),
6132
- className: "flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
7012
+ className: actionButtonClass(bordered),
6133
7013
  children: /* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" })
6134
7014
  }
6135
7015
  ),
@@ -6139,7 +7019,7 @@ function TableActionCell({ row, onView, onEdit, onDelete }) {
6139
7019
  type: "button",
6140
7020
  "aria-label": "Delete",
6141
7021
  onClick: () => onDelete(row.original),
6142
- className: "flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-red-500/10 hover:text-red-400",
7022
+ className: actionButtonClass(bordered, true),
6143
7023
  children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" })
6144
7024
  }
6145
7025
  )
@@ -6154,10 +7034,12 @@ var computeFlags = (state) => {
6154
7034
  const isJsonView = state.viewMode === "json";
6155
7035
  const isFilesView = state.viewMode === "files";
6156
7036
  const isCustomMode = !["table", "cards", "json"].includes(state.viewMode ?? "");
6157
- const hasActions = Boolean(state.onView || state.onEdit || state.onDelete);
7037
+ const hasActions = Boolean(
7038
+ state.menuButton && state.openRowMenu || state.onView || state.onEdit || state.onDelete
7039
+ );
6158
7040
  const hasControls = Boolean(state.showColumnVisibility || state.showAddButton || state.showViewToggle);
6159
7041
  const showContent = !state.isLoading && !state.error && !hasNoData && !isFilteredEmpty;
6160
- return { hasData, hasNoData, isTableView, isCardView, isJsonView, isFilesView, isCustomMode, hasActions, hasControls, showContent, showPagination: state.showPagination && isTableView && showContent };
7042
+ return { hasData, hasNoData, isTableView, isCardView, isJsonView, isFilesView, isCustomMode, hasActions, hasControls, showContent, showPagination: state.showPagination && showContent };
6161
7043
  };
6162
7044
  var createSelectors = (_store) => {
6163
7045
  const store = _store;
@@ -6199,6 +7081,9 @@ var createTableStore = () => {
6199
7081
  onAddClick: null,
6200
7082
  onRowClick: null,
6201
7083
  onRowContextMenu: null,
7084
+ onBackgroundContextMenu: null,
7085
+ openRowMenu: null,
7086
+ menuButton: false,
6202
7087
  onCellClick: null,
6203
7088
  onBulkDelete: null,
6204
7089
  onRetry: null,
@@ -6209,7 +7094,9 @@ var createTableStore = () => {
6209
7094
  CardComponent: null,
6210
7095
  className: "",
6211
7096
  classNames: {},
7097
+ bordered: false,
6212
7098
  headerClassName: "bg-card",
7099
+ headerColor: "primary",
6213
7100
  showCheckbox: true,
6214
7101
  selectedRowId: null,
6215
7102
  headerSlot: null,
@@ -6325,7 +7212,8 @@ var createTableStore = () => {
6325
7212
 
6326
7213
  // src/components/table/hooks.ts
6327
7214
  var ROW_HEIGHT = 56;
6328
- var MIN_ROWS = 5;
7215
+ var DEFAULT_TABLE_HEADER_HEIGHT = 48;
7216
+ var ROOT_SECTION_GAP_COUNT = 2;
6329
7217
  function useStoreSync(props) {
6330
7218
  const storeRef = useRef(null);
6331
7219
  const isControlled = props.mode !== void 0;
@@ -6399,33 +7287,52 @@ function useStoreSync(props) {
6399
7287
  }, [props, isControlled, isPaginationControlled, isRowSelectionControlled, isExpandedControlled, isSortingControlled]);
6400
7288
  return storeRef.current;
6401
7289
  }
7290
+ function calculateDynamicPageSize(input) {
7291
+ const rowHeight = input.rowHeight ?? ROW_HEIGHT;
7292
+ const availableRowsHeight = input.bodyHeight - input.tableHeaderHeight;
7293
+ if (availableRowsHeight <= 0) return 1;
7294
+ return Math.max(1, Math.floor(availableRowsHeight / rowHeight));
7295
+ }
6402
7296
  function useDynamicPageSize(containerRef) {
6403
7297
  const dynamicHeight = useTableStore.use.dynamicHeight();
6404
7298
  const viewMode = useTableStore.use.viewMode();
6405
7299
  const manualPagination = useTableStore.use.manualPagination();
7300
+ const isLoading = useTableStore.use.isLoading();
7301
+ const error = useTableStore.use.error();
7302
+ const hasNoData = useTableStore.use.hasNoData();
7303
+ const isFilteredEmpty = useTableStore.use.isFilteredEmpty();
6406
7304
  const syncWithProps = useTableStore.use.syncWithProps();
6407
7305
  useLayoutEffect(() => {
6408
7306
  if (!dynamicHeight || !containerRef.current || viewMode !== "table" || manualPagination) return;
6409
7307
  const calculatePageSize = () => {
6410
- const container = containerRef.current;
6411
- if (!container) return;
6412
- const tableHeaderHeight = 40;
6413
- const tableContentHeaderHeight = 48;
6414
- const paginationHeight = 36;
6415
- const gap = 8;
6416
- const parentHeight = container.parentElement?.clientHeight || container.clientHeight;
6417
- const availableHeight = parentHeight - tableHeaderHeight - tableContentHeaderHeight - paginationHeight - gap;
6418
- const calculatedRows = Math.floor(availableHeight / ROW_HEIGHT);
6419
- const newPageSize = Math.max(calculatedRows, MIN_ROWS);
6420
- const calculatedMaxHeight = tableContentHeaderHeight + newPageSize * ROW_HEIGHT;
7308
+ const container2 = containerRef.current;
7309
+ if (!container2) return;
7310
+ const bodyEl = container2.querySelector("[data-ntable-body]");
7311
+ const tableHeaderEl = container2.querySelector("[data-ntable-table-header]");
7312
+ let bodyHeight = bodyEl?.clientHeight ?? 0;
7313
+ if (!bodyHeight) {
7314
+ const rootHeight = container2.clientHeight;
7315
+ const headerHeight = container2.querySelector("[data-ntable-header]")?.offsetHeight ?? 0;
7316
+ const paginationHeight = container2.querySelector("[data-ntable-pagination]")?.offsetHeight ?? 0;
7317
+ const rootStyles = window.getComputedStyle(container2);
7318
+ const gap = Number.parseFloat(rootStyles.rowGap || rootStyles.gap || "0") || 0;
7319
+ bodyHeight = rootHeight - headerHeight - paginationHeight - gap * ROOT_SECTION_GAP_COUNT;
7320
+ }
7321
+ const tableHeaderHeight = tableHeaderEl?.offsetHeight ?? DEFAULT_TABLE_HEADER_HEIGHT;
7322
+ const newPageSize = calculateDynamicPageSize({ bodyHeight, tableHeaderHeight });
7323
+ const calculatedMaxHeight = tableHeaderHeight + newPageSize * ROW_HEIGHT;
6421
7324
  syncWithProps({ calculatedPageSize: newPageSize, maxHeight: calculatedMaxHeight });
6422
7325
  };
6423
7326
  calculatePageSize();
6424
7327
  const resizeObserver = new ResizeObserver(calculatePageSize);
6425
- resizeObserver.observe(containerRef.current);
6426
- if (containerRef.current.parentElement) resizeObserver.observe(containerRef.current.parentElement);
7328
+ const container = containerRef.current;
7329
+ resizeObserver.observe(container);
7330
+ container.querySelectorAll(
7331
+ "[data-ntable-header], [data-ntable-body], [data-ntable-pagination], [data-ntable-table-header]"
7332
+ ).forEach((el) => resizeObserver.observe(el));
7333
+ if (container.parentElement) resizeObserver.observe(container.parentElement);
6427
7334
  return () => resizeObserver.disconnect();
6428
- }, [dynamicHeight, viewMode, containerRef, syncWithProps, manualPagination]);
7335
+ }, [dynamicHeight, viewMode, containerRef, syncWithProps, manualPagination, isLoading, error, hasNoData, isFilteredEmpty]);
6429
7336
  }
6430
7337
  function useTable() {
6431
7338
  const [sorting, setSorting] = useState([]);
@@ -6438,6 +7345,9 @@ function useTable() {
6438
7345
  const onView = useTableStore.use.onView();
6439
7346
  const onEdit = useTableStore.use.onEdit();
6440
7347
  const onDelete = useTableStore.use.onDelete();
7348
+ const openRowMenu = useTableStore.use.openRowMenu();
7349
+ const menuButton = useTableStore.use.menuButton();
7350
+ const bordered = useTableStore.use.bordered();
6441
7351
  const CardComponent = useTableStore.use.CardComponent();
6442
7352
  const dynamicHeight = useTableStore.use.dynamicHeight();
6443
7353
  const viewMode = useTableStore.use.viewMode();
@@ -6462,19 +7372,20 @@ function useTable() {
6462
7372
  const finalColumns = useMemo(() => {
6463
7373
  const effectiveColumns = columns.length === 0 && CardComponent ? [{ id: "id", accessorKey: "id", header: "ID" }] : columns;
6464
7374
  if (hasActions) {
7375
+ const isMenuActions = Boolean(menuButton && openRowMenu);
6465
7376
  return [
6466
7377
  ...effectiveColumns,
6467
7378
  {
6468
7379
  id: "actions",
6469
- header: "",
6470
- cell: ({ row }) => React32__default.createElement(TableActionCell, { row, onView, onEdit, onDelete }),
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 }),
6471
7382
  enableSorting: false,
6472
7383
  enableHiding: false
6473
7384
  }
6474
7385
  ];
6475
7386
  }
6476
7387
  return effectiveColumns;
6477
- }, [columns, CardComponent, hasActions, onView, onEdit, onDelete]);
7388
+ }, [columns, CardComponent, hasActions, onView, onEdit, onDelete, openRowMenu, menuButton, bordered]);
6478
7389
  const notifyStateChange = useCallback((state) => {
6479
7390
  onStateChange?.(state);
6480
7391
  }, [onStateChange]);
@@ -6563,21 +7474,57 @@ function useTable() {
6563
7474
  }, [calculatedPageSize, dynamicHeight, viewMode, table, data.length, manualPagination]);
6564
7475
  return { table, finalColumns, sorting, setSorting, columnFilters, setColumnFilters, columnVisibility, setColumnVisibility, globalFilter, setGlobalFilter };
6565
7476
  }
6566
- function useTableKeyboard() {
7477
+ function useTableKeyboard(options = {}) {
7478
+ const { scopeRef, contextMenuClose, contextMenuOpen } = options;
6567
7479
  const table = useTableStore.use.table();
6568
7480
  const onBulkDelete = useTableStore.use.onBulkDelete();
6569
- useKeyboard("ctrl+a", () => {
6570
- if (table?.getRowModel) table.getRowModel().rows.forEach((row) => row.toggleSelected(true));
6571
- }, { preventDefault: true });
6572
- useKeyboard("escape", () => {
6573
- if (table?.toggleAllRowsSelected) table.toggleAllRowsSelected(false);
6574
- });
6575
- useKeyboard("delete", () => {
7481
+ useKeyboard(
7482
+ "ctrl+a",
7483
+ () => {
7484
+ table?.toggleAllPageRowsSelected?.(true);
7485
+ },
7486
+ { preventDefault: true, scopeRef }
7487
+ );
7488
+ useKeyboard(
7489
+ "escape",
7490
+ () => {
7491
+ if (contextMenuOpen && contextMenuClose) contextMenuClose();
7492
+ const hasSelection = table?.getIsSomeRowsSelected?.() || table?.getIsAllRowsSelected?.();
7493
+ if (hasSelection) table?.toggleAllRowsSelected?.(false);
7494
+ },
7495
+ { scopeRef }
7496
+ );
7497
+ const fireBulkDelete = () => {
6576
7498
  if (!table?.getSelectedRowModel) return;
6577
7499
  const selectedRows = table.getSelectedRowModel().rows;
6578
- if (selectedRows.length > 0 && onBulkDelete) onBulkDelete(selectedRows.map((row) => row.original?.id));
6579
- });
7500
+ if (selectedRows.length > 0 && onBulkDelete) {
7501
+ onBulkDelete(selectedRows.map((row) => row.original?.id));
7502
+ }
7503
+ };
7504
+ useKeyboard("delete", fireBulkDelete, { scopeRef, preventDefault: true });
7505
+ useKeyboard("backspace", fireBulkDelete, { scopeRef, preventDefault: true });
6580
7506
  }
7507
+
7508
+ // src/components/table/tableColors.ts
7509
+ var HEADER_COLORS = {
7510
+ primary: { bg: "bg-primary/15", text: "[&_th]:text-primary", row: "hover:bg-primary/5" },
7511
+ violet: { bg: "bg-violet-600/20", text: "[&_th]:text-violet-700 dark:[&_th]:text-violet-300", row: "hover:bg-violet-500/5" },
7512
+ blue: { bg: "bg-blue-600/20", text: "[&_th]:text-blue-700 dark:[&_th]:text-blue-300", row: "hover:bg-blue-500/5" },
7513
+ emerald: { bg: "bg-emerald-600/20", text: "[&_th]:text-emerald-700 dark:[&_th]:text-emerald-300", row: "hover:bg-emerald-500/5" },
7514
+ amber: { bg: "bg-amber-500/20", text: "[&_th]:text-amber-700 dark:[&_th]:text-amber-300", row: "hover:bg-amber-500/5" },
7515
+ rose: { bg: "bg-rose-600/20", text: "[&_th]:text-rose-700 dark:[&_th]:text-rose-300", row: "hover:bg-rose-500/5" },
7516
+ slate: { bg: "bg-slate-700/60", text: "[&_th]:text-slate-100 dark:[&_th]:text-slate-300", row: "hover:bg-slate-500/5" }
7517
+ };
7518
+ var HEADER_HEX = {
7519
+ primary: "",
7520
+ violet: "#7c3aed",
7521
+ blue: "#2563eb",
7522
+ emerald: "#059669",
7523
+ amber: "#f59e0b",
7524
+ rose: "#e11d48",
7525
+ slate: "#475569"
7526
+ };
7527
+ var ROW_CONTEXT_HANDLED = "__ntableRowContextHandled";
6581
7528
  function EditableCell({ cell, onCellEdit }) {
6582
7529
  const columnDef = cell.column.columnDef;
6583
7530
  const meta = columnDef.meta || {};
@@ -6585,10 +7532,10 @@ function EditableCell({ cell, onCellEdit }) {
6585
7532
  const columnId = cell.column.id;
6586
7533
  const editor = meta.editor || "text";
6587
7534
  const initial = cell.getValue();
6588
- const [editing, setEditing] = React32__default.useState(false);
6589
- const [value, setValue] = React32__default.useState(initial);
6590
- const [saving, setSaving] = React32__default.useState(false);
6591
- React32__default.useEffect(() => {
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(() => {
6592
7539
  if (!editing) setValue(initial);
6593
7540
  }, [initial, editing]);
6594
7541
  const commit = async (next) => {
@@ -6637,20 +7584,31 @@ function NTableContent({ effectiveMode }) {
6637
7584
  const showSorting = useTableStore.use.showSorting();
6638
7585
  const noResultsText = useTableStore.use.noResultsText();
6639
7586
  const headerClassName = useTableStore.use.headerClassName();
7587
+ const headerColor = useTableStore.use.headerColor();
7588
+ const colorStyle = headerColor ? HEADER_COLORS[headerColor] : null;
6640
7589
  const onRowClick = useTableStore.use.onRowClick();
6641
7590
  const onRowContextMenu = useTableStore.use.onRowContextMenu();
7591
+ const onBackgroundContextMenu = useTableStore.use.onBackgroundContextMenu();
6642
7592
  const onCellEdit = useTableStore.use.onCellEdit();
6643
- const dynamicHeight = useTableStore.use.dynamicHeight();
6644
7593
  const isLoading = useTableStore.use.isLoading();
6645
7594
  const error = useTableStore.use.error();
6646
7595
  const hasNoData = useTableStore.use.hasNoData();
6647
7596
  const showContent = useTableStore.use.showContent();
6648
7597
  const classNames = useTableStore.use.classNames();
7598
+ const bordered = useTableStore.use.bordered();
6649
7599
  const showCheckbox = useTableStore.use.showCheckbox();
6650
7600
  const selectedRowId = useTableStore.use.selectedRowId();
6651
7601
  const renderSubRow = useTableStore.use.renderSubRow();
6652
7602
  const userGetRowCanExpand = useTableStore.use.getRowCanExpand();
6653
7603
  const hasExpansion = Boolean(renderSubRow || userGetRowCanExpand);
7604
+ const handleBackgroundContextMenu = useCallback((e) => {
7605
+ if (e.nativeEvent[ROW_CONTEXT_HANDLED]) return;
7606
+ const target = e.target;
7607
+ if (target.closest("tr[data-row]")) return;
7608
+ if (onBackgroundContextMenu) {
7609
+ onBackgroundContextMenu(e);
7610
+ }
7611
+ }, [onBackgroundContextMenu]);
6654
7612
  if (isLoading || error || hasNoData || !showContent || !table) return null;
6655
7613
  const isTableView = effectiveMode ? effectiveMode === "table" : storeIsTableView;
6656
7614
  if (!isTableView) return null;
@@ -6660,76 +7618,9 @@ function NTableContent({ effectiveMode }) {
6660
7618
  if (dir === "desc") return /* @__PURE__ */ jsx(ArrowDown, { className: "h-4 w-4" });
6661
7619
  return /* @__PURE__ */ jsx(ArrowUpDown, { className: "h-4 w-4 opacity-50" });
6662
7620
  };
6663
- return /* @__PURE__ */ jsx(Card, { className: cn("rounded-md p-0 border border-border/50 bg-transparent shadow-none", dynamicHeight ? "overflow-hidden" : "overflow-auto", classNames?.content), children: dynamicHeight ? /* @__PURE__ */ jsx("div", { className: "overflow-auto", children: /* @__PURE__ */ jsxs(Table, { children: [
6664
- /* @__PURE__ */ jsx(TableHeader, { className: cn(headerClassName, dynamicHeight && "sticky top-0 z-10", classNames?.tableHeader), children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsxs(TableRow, { className: "hover:bg-muted/30", children: [
6665
- showCheckbox && /* @__PURE__ */ jsx(TableHead, { className: "w-10 text-foreground h-12", children: /* @__PURE__ */ jsx(
6666
- Checkbox,
6667
- {
6668
- "aria-label": "Select all rows",
6669
- checked: table.getIsAllPageRowsSelected(),
6670
- onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value)
6671
- }
6672
- ) }),
6673
- hasExpansion && /* @__PURE__ */ jsx(TableHead, { "aria-label": "Expand column", className: "w-10 text-foreground h-12" }),
6674
- hg.headers.map((header) => /* @__PURE__ */ jsx(TableHead, { className: "text-foreground h-12", 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: [
6675
- flexRender(header.column.columnDef.header, header.getContext()),
6676
- header.column.getCanSort() && showSorting && /* @__PURE__ */ jsx("span", { children: getSortIcon(header.column) })
6677
- ] }) }, header.id))
6678
- ] }, hg.id)) }),
6679
- /* @__PURE__ */ jsx(TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => {
6680
- const isSelectedByRowId = Boolean(selectedRowId && row.original?.id === selectedRowId);
6681
- const canExpand = hasExpansion && row.getCanExpand();
6682
- const isExpanded = canExpand && row.getIsExpanded();
6683
- const totalCols = row.getVisibleCells().length + (showCheckbox ? 1 : 0) + (hasExpansion ? 1 : 0);
6684
- return /* @__PURE__ */ jsxs(React32__default.Fragment, { children: [
6685
- /* @__PURE__ */ jsxs(
6686
- TableRow,
6687
- {
6688
- "data-row": "true",
6689
- "data-state": row.getIsSelected() && "selected",
6690
- "data-selected-row": isSelectedByRowId ? "true" : void 0,
6691
- onClick: () => onRowClick?.(row.original),
6692
- onContextMenu: onRowContextMenu ? (e) => onRowContextMenu(e, row.original) : void 0,
6693
- className: cn(classNames?.row, onRowClick && "cursor-pointer", isSelectedByRowId && "bg-brand/5 hover:bg-brand/5"),
6694
- children: [
6695
- showCheckbox && /* @__PURE__ */ jsx(TableCell, { className: "h-14 w-10", children: /* @__PURE__ */ jsx(
6696
- Checkbox,
6697
- {
6698
- "aria-label": `Select row ${row.id}`,
6699
- checked: row.getIsSelected(),
6700
- onClick: (e) => e.stopPropagation(),
6701
- onCheckedChange: (value) => row.toggleSelected(!!value)
6702
- }
6703
- ) }),
6704
- hasExpansion && /* @__PURE__ */ jsx(TableCell, { className: "h-14 w-10", children: canExpand ? /* @__PURE__ */ jsx(
6705
- "button",
6706
- {
6707
- type: "button",
6708
- "aria-label": `${isExpanded ? "Collapse" : "Expand"} row ${row.id}`,
6709
- "aria-expanded": isExpanded,
6710
- onClick: (e) => {
6711
- e.stopPropagation();
6712
- row.toggleExpanded();
6713
- },
6714
- className: "flex h-6 w-6 items-center justify-center rounded hover:bg-muted",
6715
- children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
6716
- }
6717
- ) : null }),
6718
- row.getVisibleCells().map((cell) => {
6719
- const columnDef = cell.column.columnDef;
6720
- const meta = columnDef.meta || {};
6721
- const isEditable = Boolean(onCellEdit) && Boolean(meta.editable);
6722
- return /* @__PURE__ */ jsx(TableCell, { className: "h-14", children: isEditable ? /* @__PURE__ */ jsx(EditableCell, { cell, onCellEdit }) : flexRender(columnDef.cell, cell.getContext()) }, cell.id);
6723
- })
6724
- ]
6725
- }
6726
- ),
6727
- 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) }) })
6728
- ] }, row.id);
6729
- }) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length + (showCheckbox ? 1 : 0) + (hasExpansion ? 1 : 0), className: "h-16 text-center", children: noResultsText }) }) })
6730
- ] }) }) : /* @__PURE__ */ jsxs(Table, { children: [
6731
- /* @__PURE__ */ jsx(TableHeader, { className: cn(headerClassName, classNames?.tableHeader), children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsxs(TableRow, { className: "hover:bg-muted/30", children: [
6732
- showCheckbox && /* @__PURE__ */ jsx(TableHead, { className: "w-10 text-foreground h-12", children: /* @__PURE__ */ jsx(
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(
6733
7624
  Checkbox,
6734
7625
  {
6735
7626
  "aria-label": "Select all rows",
@@ -6737,8 +7628,8 @@ function NTableContent({ effectiveMode }) {
6737
7628
  onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value)
6738
7629
  }
6739
7630
  ) }),
6740
- hasExpansion && /* @__PURE__ */ jsx(TableHead, { "aria-label": "Expand column", className: "w-10 text-foreground h-12" }),
6741
- hg.headers.map((header) => /* @__PURE__ */ jsx(TableHead, { className: "text-foreground h-12", 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: [
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: [
6742
7633
  flexRender(header.column.columnDef.header, header.getContext()),
6743
7634
  header.column.getCanSort() && showSorting && /* @__PURE__ */ jsx("span", { children: getSortIcon(header.column) })
6744
7635
  ] }) }, header.id))
@@ -6748,16 +7639,20 @@ function NTableContent({ effectiveMode }) {
6748
7639
  const canExpand = hasExpansion && row.getCanExpand();
6749
7640
  const isExpanded = canExpand && row.getIsExpanded();
6750
7641
  const totalCols = row.getVisibleCells().length + (showCheckbox ? 1 : 0) + (hasExpansion ? 1 : 0);
6751
- return /* @__PURE__ */ jsxs(React32__default.Fragment, { children: [
7642
+ return /* @__PURE__ */ jsxs(React38__default.Fragment, { children: [
6752
7643
  /* @__PURE__ */ jsxs(
6753
7644
  TableRow,
6754
7645
  {
6755
7646
  "data-row": "true",
7647
+ "data-row-id": row.id,
6756
7648
  "data-state": row.getIsSelected() && "selected",
6757
7649
  "data-selected-row": isSelectedByRowId ? "true" : void 0,
6758
7650
  onClick: () => onRowClick?.(row.original),
6759
- onContextMenu: onRowContextMenu ? (e) => onRowContextMenu(e, row.original) : void 0,
6760
- className: cn(classNames?.row, onRowClick && "cursor-pointer", isSelectedByRowId && "bg-brand/5 hover:bg-brand/5"),
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"),
6761
7656
  children: [
6762
7657
  showCheckbox && /* @__PURE__ */ jsx(TableCell, { className: "h-14 w-10", children: /* @__PURE__ */ jsx(
6763
7658
  Checkbox,
@@ -6778,7 +7673,10 @@ function NTableContent({ effectiveMode }) {
6778
7673
  e.stopPropagation();
6779
7674
  row.toggleExpanded();
6780
7675
  },
6781
- className: "flex h-6 w-6 items-center justify-center rounded hover:bg-muted",
7676
+ className: cn(
7677
+ "flex h-6 w-6 items-center justify-center rounded hover:bg-muted",
7678
+ bordered && "border border-muted-foreground"
7679
+ ),
6782
7680
  children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
6783
7681
  }
6784
7682
  ) : null }),
@@ -6796,49 +7694,272 @@ function NTableContent({ effectiveMode }) {
6796
7694
  }) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length + (showCheckbox ? 1 : 0) + (hasExpansion ? 1 : 0), className: "h-16 text-center", children: noResultsText }) }) })
6797
7695
  ] }) });
6798
7696
  }
6799
- function NTableCards({ effectiveMode }) {
6800
- const table = useTableStore.use.table();
6801
- const onRowClick = useTableStore.use.onRowClick();
6802
- const onRowContextMenu = useTableStore.use.onRowContextMenu();
6803
- const CardComponent = useTableStore.use.CardComponent();
6804
- const storeIsCardView = useTableStore.use.isCardView();
6805
- const isLoading = useTableStore.use.isLoading();
6806
- const error = useTableStore.use.error();
6807
- const hasNoData = useTableStore.use.hasNoData();
6808
- const showContent = useTableStore.use.showContent();
6809
- const classNames = useTableStore.use.classNames();
6810
- const renderSubRow = useTableStore.use.renderSubRow();
6811
- const userGetRowCanExpand = useTableStore.use.getRowCanExpand();
6812
- useTableStore.use.selectedRowId();
6813
- if (isLoading || error || hasNoData || !showContent || !table) return null;
6814
- const isCardView = effectiveMode ? effectiveMode === "cards" : storeIsCardView;
6815
- if (!isCardView) return null;
6816
- const rows = table.getRowModel().rows;
6817
- if (!CardComponent) return /* @__PURE__ */ jsx("div", { className: "text-center py-8 text-muted-foreground", children: "No CardComponent provided." });
6818
- const defaultContainerClass = "flex flex-wrap gap-3 p-3 overflow-y-auto";
6819
- const containerClass = classNames?.cards ?? defaultContainerClass;
6820
- return /* @__PURE__ */ jsx("div", { className: cn(containerClass), children: rows.map((row) => {
6821
- const hasExpansion = Boolean(renderSubRow || userGetRowCanExpand);
6822
- const canExpand = hasExpansion && row.getCanExpand();
6823
- const isExpanded = canExpand && row.getIsExpanded();
6824
- const handleClick = () => onRowClick?.(row.original);
6825
- const handleContextMenu = (e) => onRowContextMenu?.(e, row.original);
7697
+ function NDataCardShell({ row, onClick, onContextMenu, actions, children, className, showCheckbox = true, selectedRowId, openRowMenu, menuButton, bordered = false }) {
7698
+ const canExpand = row.getCanExpand();
7699
+ const isExpanded = canExpand && row.getIsExpanded();
7700
+ const isSelected = row.getIsSelected();
7701
+ const isHighlighted = selectedRowId != null && row.original?.id === selectedRowId;
7702
+ const isActive = isSelected || isHighlighted;
7703
+ const useMenuButton = menuButton && openRowMenu;
7704
+ return /* @__PURE__ */ jsxs(
7705
+ "div",
7706
+ {
7707
+ "data-row": "true",
7708
+ "data-row-id": row.id,
7709
+ onClick,
7710
+ onContextMenu,
7711
+ className: cn(
7712
+ "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"),
7715
+ onClick && "cursor-pointer",
7716
+ className
7717
+ ),
7718
+ children: [
7719
+ showCheckbox && /* @__PURE__ */ jsx("div", { className: cn("absolute top-2 left-2 z-10 transition-opacity duration-200", isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100"), children: /* @__PURE__ */ jsx(
7720
+ Checkbox,
7721
+ {
7722
+ checked: isSelected,
7723
+ onCheckedChange: (value) => {
7724
+ row.toggleSelected(!!value);
7725
+ },
7726
+ onClick: (e) => e.stopPropagation(),
7727
+ className: "h-4 w-4"
7728
+ }
7729
+ ) }),
7730
+ useMenuButton ? /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 h-auto z-10 opacity-0 transition-opacity duration-200 group-hover:opacity-100 focus-within:opacity-100", children: /* @__PURE__ */ jsx(
7731
+ "button",
7732
+ {
7733
+ type: "button",
7734
+ "aria-label": "Row actions",
7735
+ onClick: (e) => {
7736
+ e.stopPropagation();
7737
+ openRowMenu(e, row.original);
7738
+ },
7739
+ className: "flex h-7 w-7 p-0 rounded-md cursor-pointer justify-center items-center text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
7740
+ children: /* @__PURE__ */ jsx(MoreVertical, { className: "h-4 w-4" })
7741
+ }
7742
+ ) }) : actions && (actions.onView || actions.onEdit || actions.onDelete) ? /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 h-auto z-10 opacity-0 transition-opacity duration-200 group-hover:opacity-100 focus-within:opacity-100", children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
7743
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
7744
+ "div",
7745
+ {
7746
+ onClick: (e) => e.stopPropagation(),
7747
+ className: "flex h-7 w-7 p-0 rounded-md cursor-pointer justify-center items-center text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
7748
+ "aria-label": "Card actions",
7749
+ children: /* @__PURE__ */ jsx(MoreVertical, { className: "h-4 w-4" })
7750
+ }
7751
+ ) }),
7752
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-40", children: [
7753
+ actions.onView && /* @__PURE__ */ jsxs(
7754
+ DropdownMenuItem,
7755
+ {
7756
+ onClick: (e) => {
7757
+ e.stopPropagation();
7758
+ actions.onView(row.original);
7759
+ },
7760
+ className: "cursor-pointer",
7761
+ children: [
7762
+ /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4 mr-2" }),
7763
+ "View"
7764
+ ]
7765
+ }
7766
+ ),
7767
+ actions.onEdit && /* @__PURE__ */ jsxs(
7768
+ DropdownMenuItem,
7769
+ {
7770
+ onClick: (e) => {
7771
+ e.stopPropagation();
7772
+ actions.onEdit(row.original);
7773
+ },
7774
+ className: "cursor-pointer",
7775
+ children: [
7776
+ /* @__PURE__ */ jsx(Edit, { className: "h-4 w-4 mr-2" }),
7777
+ "Edit"
7778
+ ]
7779
+ }
7780
+ ),
7781
+ actions.onDelete && /* @__PURE__ */ jsxs(
7782
+ DropdownMenuItem,
7783
+ {
7784
+ onClick: (e) => {
7785
+ e.stopPropagation();
7786
+ actions.onDelete(row.original);
7787
+ },
7788
+ className: "cursor-pointer text-red-500",
7789
+ children: [
7790
+ /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4 mr-2 text-red-500" }),
7791
+ "Delete"
7792
+ ]
7793
+ }
7794
+ )
7795
+ ] })
7796
+ ] }) }) : null,
7797
+ canExpand && /* @__PURE__ */ jsx(
7798
+ "button",
7799
+ {
7800
+ type: "button",
7801
+ "aria-label": `${isExpanded ? "Collapse" : "Expand"} row ${row.id}`,
7802
+ "aria-expanded": isExpanded,
7803
+ onClick: (e) => {
7804
+ e.stopPropagation();
7805
+ row.toggleExpanded();
7806
+ },
7807
+ className: cn(
7808
+ "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"
7810
+ ),
7811
+ children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
7812
+ }
7813
+ ),
7814
+ children
7815
+ ]
7816
+ }
7817
+ );
7818
+ }
7819
+ var ROW_CONTEXT_HANDLED2 = "__ntableRowContextHandled";
7820
+ function markRowContextHandled(e) {
7821
+ e.nativeEvent[ROW_CONTEXT_HANDLED2] = true;
7822
+ }
7823
+ function isRowContextHandled(e) {
7824
+ return Boolean(e.nativeEvent[ROW_CONTEXT_HANDLED2]);
7825
+ }
7826
+ function NTableCards({ effectiveMode }) {
7827
+ const table = useTableStore.use.table();
7828
+ const onRowClick = useTableStore.use.onRowClick();
7829
+ const onRowContextMenu = useTableStore.use.onRowContextMenu();
7830
+ const onBackgroundContextMenu = useTableStore.use.onBackgroundContextMenu();
7831
+ const openRowMenu = useTableStore.use.openRowMenu();
7832
+ const menuButton = useTableStore.use.menuButton();
7833
+ const onView = useTableStore.use.onView();
7834
+ const onEdit = useTableStore.use.onEdit();
7835
+ const onDelete = useTableStore.use.onDelete();
7836
+ const showCheckbox = useTableStore.use.showCheckbox();
7837
+ const selectedRowId = useTableStore.use.selectedRowId();
7838
+ const CardComponent = useTableStore.use.CardComponent();
7839
+ const storeIsCardView = useTableStore.use.isCardView();
7840
+ const isLoading = useTableStore.use.isLoading();
7841
+ const error = useTableStore.use.error();
7842
+ const hasNoData = useTableStore.use.hasNoData();
7843
+ const showContent = useTableStore.use.showContent();
7844
+ const classNames = useTableStore.use.classNames();
7845
+ const bordered = useTableStore.use.bordered();
7846
+ const renderSubRow = useTableStore.use.renderSubRow();
7847
+ const userGetRowCanExpand = useTableStore.use.getRowCanExpand();
7848
+ const handleContainerContextMenu = useCallback((e) => {
7849
+ if (isRowContextHandled(e)) return;
7850
+ const gridContainer = e.currentTarget;
7851
+ let el = e.target;
7852
+ let gridChild = null;
7853
+ while (el && el.parentElement && el.parentElement !== gridContainer) {
7854
+ el = el.parentElement;
7855
+ }
7856
+ gridChild = el.parentElement === gridContainer ? el : null;
7857
+ if (gridChild) {
7858
+ const rows2 = table?.getRowModel()?.rows;
7859
+ if (!rows2) return;
7860
+ const children = Array.from(gridContainer.children);
7861
+ const idx = children.indexOf(gridChild);
7862
+ if (idx >= 0 && idx < rows2.length) {
7863
+ const row = rows2[idx];
7864
+ if (onRowContextMenu) {
7865
+ markRowContextHandled(e);
7866
+ onRowContextMenu(e, row.original);
7867
+ }
7868
+ return;
7869
+ }
7870
+ }
7871
+ if (onBackgroundContextMenu) {
7872
+ onBackgroundContextMenu(e);
7873
+ }
7874
+ }, [table, onRowContextMenu, onBackgroundContextMenu]);
7875
+ if (isLoading || error || hasNoData || !showContent || !table) return null;
7876
+ const isCardView = effectiveMode ? effectiveMode === "cards" : storeIsCardView;
7877
+ if (!isCardView) return null;
7878
+ const rows = table.getRowModel().rows;
7879
+ if (!CardComponent) return /* @__PURE__ */ jsx("div", { className: "text-center py-8 text-muted-foreground", children: "No CardComponent provided." });
7880
+ const defaultContainerClass = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3";
7881
+ const containerClass = classNames?.cards ?? defaultContainerClass;
7882
+ const actions = !menuButton && (onView || onEdit || onDelete) ? { onView, onEdit, onDelete } : void 0;
7883
+ return /* @__PURE__ */ jsx(NajmScroll, { axis: "y", className: "min-h-0 flex-1 overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: cn(containerClass), onContextMenu: handleContainerContextMenu, children: rows.map((row) => {
7884
+ const noShell = Boolean(row.original?.__smsNoShell);
7885
+ const hasExpansion = Boolean(renderSubRow || userGetRowCanExpand);
7886
+ const canExpand = hasExpansion && row.getCanExpand();
7887
+ const isExpanded = canExpand && row.getIsExpanded();
7888
+ const handleClick = onRowClick ? () => onRowClick(row.original) : void 0;
7889
+ const handleCardContextMenu = onRowContextMenu ? (e) => {
7890
+ if (isRowContextHandled(e)) return;
7891
+ markRowContextHandled(e);
7892
+ onRowContextMenu(e, row.original);
7893
+ } : void 0;
7894
+ if (noShell) {
7895
+ return /* @__PURE__ */ jsxs(
7896
+ "div",
7897
+ {
7898
+ onContextMenu: handleCardContextMenu,
7899
+ "data-row": "true",
7900
+ "data-row-id": row.id,
7901
+ className: "group relative",
7902
+ children: [
7903
+ menuButton && openRowMenu && /* @__PURE__ */ jsx(
7904
+ "button",
7905
+ {
7906
+ type: "button",
7907
+ "aria-label": "Row actions",
7908
+ onClick: (e) => {
7909
+ e.stopPropagation();
7910
+ openRowMenu(e, row.original);
7911
+ },
7912
+ className: "absolute top-2 right-2 z-10 flex h-7 w-7 items-center justify-center rounded-md p-0 text-muted-foreground opacity-0 transition-all duration-200 hover:bg-muted/50 hover:text-foreground group-hover:opacity-100 focus:opacity-100 focus-visible:opacity-100",
7913
+ children: /* @__PURE__ */ jsx(MoreVertical, { className: "h-4 w-4" })
7914
+ }
7915
+ ),
7916
+ /* @__PURE__ */ jsx(
7917
+ CardComponent,
7918
+ {
7919
+ data: row.original,
7920
+ row,
7921
+ onClick: handleClick,
7922
+ onContextMenu: handleCardContextMenu,
7923
+ isExpanded,
7924
+ onToggleExpanded: () => row.toggleExpanded(),
7925
+ canExpand,
7926
+ renderSubRow: canExpand && isExpanded ? renderSubRow : void 0,
7927
+ "data-row": "true",
7928
+ "data-row-id": row.id
7929
+ }
7930
+ )
7931
+ ]
7932
+ },
7933
+ row.id
7934
+ );
7935
+ }
6826
7936
  return /* @__PURE__ */ jsx(
6827
- CardComponent,
7937
+ NDataCardShell,
6828
7938
  {
6829
- data: row.original,
6830
7939
  row,
6831
7940
  onClick: handleClick,
6832
- onContextMenu: handleContextMenu,
6833
- isExpanded,
6834
- onToggleExpanded: () => row.toggleExpanded(),
6835
- canExpand,
6836
- renderSubRow: canExpand && isExpanded ? renderSubRow : void 0,
6837
- "data-row": "true"
7941
+ onContextMenu: handleCardContextMenu,
7942
+ actions,
7943
+ showCheckbox,
7944
+ selectedRowId,
7945
+ openRowMenu,
7946
+ menuButton,
7947
+ bordered,
7948
+ children: /* @__PURE__ */ jsx(
7949
+ CardComponent,
7950
+ {
7951
+ data: row.original,
7952
+ row,
7953
+ isExpanded,
7954
+ onToggleExpanded: () => row.toggleExpanded(),
7955
+ canExpand,
7956
+ renderSubRow: canExpand && isExpanded ? renderSubRow : void 0
7957
+ }
7958
+ )
6838
7959
  },
6839
7960
  row.id
6840
7961
  );
6841
- }) });
7962
+ }) }) });
6842
7963
  }
6843
7964
  function NTablePagination() {
6844
7965
  const table = useTableStore.use.table();
@@ -6853,12 +7974,14 @@ function NTablePagination() {
6853
7974
  const rowCount = useTableStore.use.rowCount();
6854
7975
  const setPagination = useTableStore.use.setPagination();
6855
7976
  const isPaginationControlled = useTableStore.use.isPaginationControlled();
7977
+ const bordered = useTableStore.use.bordered();
6856
7978
  if (!table || !showContent || !showPagination || viewMode === "json" || viewMode === "files") return null;
6857
7979
  const filteredRows = table.getFilteredRowModel().rows;
6858
7980
  const selectedRows = table.getFilteredSelectedRowModel().rows;
6859
7981
  const { pageIndex, pageSize } = table.getState().pagination;
6860
7982
  const effectivePageCount = manualPagination && pageCount !== void 0 ? pageCount : table.getPageCount();
6861
7983
  const currentPagination = pagination ?? { pageIndex, pageSize };
7984
+ const currentPageSizeOptions = pageSizeOptions.includes(pageSize) ? pageSizeOptions : [...pageSizeOptions, pageSize].sort((a, b) => a - b);
6862
7985
  const navigate = (direction) => {
6863
7986
  let next;
6864
7987
  switch (direction) {
@@ -6886,8 +8009,8 @@ function NTablePagination() {
6886
8009
  (!isPaginationControlled || manualPagination) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6887
8010
  /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Rows/page" }),
6888
8011
  /* @__PURE__ */ jsxs(Select, { value: `${pageSize}`, onValueChange: handlePageSizeChange, children: [
6889
- /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 w-[70px]", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: pageSize }) }),
6890
- /* @__PURE__ */ jsx(SelectContent, { side: "top", children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx(SelectItem, { value: `${size}`, children: size }, size)) })
8012
+ /* @__PURE__ */ jsx(SelectTrigger, { className: cn("h-8 w-[80px]", bordered && "border-muted-foreground"), children: /* @__PURE__ */ jsx(SelectValue, { placeholder: pageSize }) }),
8013
+ /* @__PURE__ */ jsx(SelectContent, { side: "top", children: currentPageSizeOptions.map((size) => /* @__PURE__ */ jsx(SelectItem, { value: `${size}`, children: size }, size)) })
6891
8014
  ] })
6892
8015
  ] }),
6893
8016
  /* @__PURE__ */ jsxs("div", { className: "text-sm font-medium", children: [
@@ -6897,10 +8020,10 @@ function NTablePagination() {
6897
8020
  effectivePageCount
6898
8021
  ] }),
6899
8022
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6900
- /* @__PURE__ */ jsx(Button, { variant: "outline", className: "h-8 w-8 p-0 hidden lg:flex", "aria-label": "First page", onClick: () => navigate("first"), disabled: !table.getCanPreviousPage?.() || pageIndex === 0, children: /* @__PURE__ */ jsx(ChevronsLeft, { className: "h-4 w-4" }) }),
6901
- /* @__PURE__ */ jsx(Button, { variant: "outline", className: "h-8 w-8 p-0", "aria-label": "Previous", onClick: () => navigate("prev"), disabled: !table.getCanPreviousPage?.() || pageIndex === 0, children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" }) }),
6902
- /* @__PURE__ */ jsx(Button, { variant: "outline", className: "h-8 w-8 p-0", "aria-label": "Next", onClick: () => navigate("next"), disabled: !table.getCanNextPage?.() || pageIndex >= effectivePageCount - 1, children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }) }),
6903
- /* @__PURE__ */ jsx(Button, { variant: "outline", className: "h-8 w-8 p-0 hidden lg:flex", "aria-label": "Last page", onClick: () => navigate("last"), disabled: !table.getCanNextPage?.() || pageIndex >= effectivePageCount - 1, children: /* @__PURE__ */ jsx(ChevronsRight, { className: "h-4 w-4" }) })
8023
+ /* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: "h-8 w-8 p-0 hidden lg:flex", "aria-label": "First page", onClick: () => navigate("first"), disabled: !table.getCanPreviousPage?.() || pageIndex === 0, children: /* @__PURE__ */ jsx(ChevronsLeft, { className: "h-4 w-4" }) }),
8024
+ /* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: "h-8 w-8 p-0", "aria-label": "Previous", onClick: () => navigate("prev"), disabled: !table.getCanPreviousPage?.() || pageIndex === 0, children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" }) }),
8025
+ /* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: "h-8 w-8 p-0", "aria-label": "Next", onClick: () => navigate("next"), disabled: !table.getCanNextPage?.() || pageIndex >= effectivePageCount - 1, children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }) }),
8026
+ /* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: "h-8 w-8 p-0 hidden lg:flex", "aria-label": "Last page", onClick: () => navigate("last"), disabled: !table.getCanNextPage?.() || pageIndex >= effectivePageCount - 1, children: /* @__PURE__ */ jsx(ChevronsRight, { className: "h-4 w-4" }) })
6904
8027
  ] })
6905
8028
  ] }),
6906
8029
  /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
@@ -6911,101 +8034,196 @@ function NTablePagination() {
6911
8034
  ] })
6912
8035
  ] });
6913
8036
  }
8037
+ function SearchFilter({ placeholder }) {
8038
+ const table = useTableStore.use.table();
8039
+ const bordered = useTableStore.use.bordered();
8040
+ if (!table) return null;
8041
+ const value = table.getState().globalFilter ?? "";
8042
+ return /* @__PURE__ */ jsx(TextInput, { icon: Search, value, onChange: (v) => table.setGlobalFilter(v), placeholder: placeholder ?? "Search\u2026", bordered });
8043
+ }
6914
8044
  function TextFilter({ name, placeholder }) {
6915
8045
  const table = useTableStore.use.table();
8046
+ const bordered = useTableStore.use.bordered();
6916
8047
  const column = table?.getColumn?.(name);
6917
8048
  if (!column) return null;
6918
- return /* @__PURE__ */ jsx(TextInput, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value), placeholder });
8049
+ return /* @__PURE__ */ jsx(TextInput, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value), placeholder, bordered });
6919
8050
  }
6920
8051
  function SelectFilter({ name, options, placeholder, inputType }) {
6921
8052
  const table = useTableStore.use.table();
8053
+ const bordered = useTableStore.use.bordered();
6922
8054
  const column = table?.getColumn?.(name);
6923
8055
  if (!column) return null;
6924
8056
  const allOptions = [{ value: "__clear__", label: "All" }, ...options.map((o) => typeof o === "string" ? { value: o, label: o } : o)];
6925
8057
  const InputComponent = inputType === "combobox" ? ComboboxInput : SelectInput;
6926
- return /* @__PURE__ */ jsx(InputComponent, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value === "" || value === "__clear__" ? void 0 : value), items: allOptions, placeholder: placeholder || "Filter..." });
8058
+ return /* @__PURE__ */ jsx(InputComponent, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value === "" || value === "__clear__" ? void 0 : value), items: allOptions, placeholder: placeholder || "Filter...", bordered });
6927
8059
  }
6928
- function TableFilters() {
6929
- const table = useTableStore.use.table();
6930
- const filters = useTableStore.use.filters();
6931
- if (!table || !filters?.length) return null;
6932
- return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-4 w-full", children: filters.map((filter) => /* @__PURE__ */ jsx("div", { className: "flex flex-col w-full lg:w-62", children: filter.type === "text" && !filter.onChange ? /* @__PURE__ */ jsx(TextFilter, { name: filter.name, placeholder: filter.placeholder }) : /* @__PURE__ */ jsx(SelectFilter, { name: filter.name, options: filter.options || [], placeholder: filter.placeholder, inputType: filter.type }) }, filter.name)) });
6933
- }
6934
- function getModeLabel(mode) {
6935
- if (mode === "json") return "JSON";
6936
- if (mode === "files") return "Files";
6937
- return mode.charAt(0).toUpperCase() + mode.slice(1);
8060
+ function defaultWrapperClass(filter) {
8061
+ return filter.type === "search" ? "flex-1 min-w-[160px] max-w-sm" : "w-full sm:w-40 shrink-0";
6938
8062
  }
6939
- function TableModeButtons() {
6940
- const showViewToggle = useTableStore.use.showViewToggle();
6941
- const toolbarLabels = useTableStore.use.toolbarLabels();
6942
- const availableModes = useTableStore.use.availableModes();
6943
- const viewMode = useTableStore.use.viewMode();
6944
- const setViewMode = useTableStore.use.setViewMode();
6945
- const jsonValue = useTableStore.use.jsonValue();
6946
- const renderJson = useTableStore.use.renderJson();
6947
- const cardComponent = useTableStore.use.CardComponent();
6948
- if (!showViewToggle) return null;
6949
- const modes = [];
6950
- const allModes = ["table", "cards", "json", "files"];
6951
- const filteredModes = availableModes ?? allModes;
6952
- if (filteredModes.includes("table")) {
6953
- modes.push({ mode: "table", icon: /* @__PURE__ */ jsx(List, { className: "h-3.5 w-3.5" }), active: viewMode === "table" });
8063
+ function RenderFilter({ filter }) {
8064
+ const table = useTableStore.use.table();
8065
+ const bordered = useTableStore.use.bordered();
8066
+ if (filter.type === "search") {
8067
+ return /* @__PURE__ */ jsx(SearchFilter, { placeholder: filter.placeholder });
6954
8068
  }
6955
- if (filteredModes.includes("cards") && cardComponent) {
6956
- modes.push({ mode: "cards", icon: /* @__PURE__ */ jsx(LayoutGrid, { className: "h-3.5 w-3.5" }), active: viewMode === "cards" });
8069
+ if (filter.type === "date" && typeof filter.onChange === "function") {
8070
+ return /* @__PURE__ */ jsx(
8071
+ DateInput,
8072
+ {
8073
+ value: filter.value ?? "",
8074
+ onChange: filter.onChange,
8075
+ placeholder: filter.placeholder,
8076
+ bordered,
8077
+ className: "w-full"
8078
+ }
8079
+ );
6957
8080
  }
6958
- if (filteredModes.includes("json") && (jsonValue !== void 0 || renderJson)) {
6959
- modes.push({ mode: "json", icon: /* @__PURE__ */ jsx(Code, { className: "h-3.5 w-3.5" }), active: viewMode === "json" });
8081
+ if (typeof filter.onChange === "function") {
8082
+ if (filter.type === "text" || !filter.type && typeof filter.value === "string") {
8083
+ return /* @__PURE__ */ jsx(
8084
+ TextInput,
8085
+ {
8086
+ value: filter.value ?? "",
8087
+ onChange: filter.onChange,
8088
+ placeholder: filter.placeholder,
8089
+ bordered,
8090
+ className: "w-full"
8091
+ }
8092
+ );
8093
+ }
8094
+ if (filter.type === "combobox") {
8095
+ return /* @__PURE__ */ jsx(
8096
+ ComboboxInput,
8097
+ {
8098
+ value: filter.value ?? "",
8099
+ onChange: filter.onChange,
8100
+ items: filter.options || [],
8101
+ placeholder: filter.placeholder,
8102
+ searchPlaceholder: filter.searchPlaceholder,
8103
+ emptyMessage: filter.emptyMessage,
8104
+ icon: "filter",
8105
+ showIcon: true,
8106
+ disabled: filter.disabled,
8107
+ bordered,
8108
+ className: "w-full"
8109
+ }
8110
+ );
8111
+ }
8112
+ return /* @__PURE__ */ jsx(
8113
+ SelectInput,
8114
+ {
8115
+ value: filter.value ?? "",
8116
+ onChange: filter.onChange,
8117
+ items: filter.options || [],
8118
+ placeholder: filter.placeholder,
8119
+ icon: "filter",
8120
+ showIcon: true,
8121
+ disabled: filter.disabled,
8122
+ bordered,
8123
+ className: "w-full"
8124
+ }
8125
+ );
6960
8126
  }
6961
- if (filteredModes.includes("files")) {
6962
- modes.push({ mode: "files", icon: /* @__PURE__ */ jsx(FolderOpen, { className: "h-3.5 w-3.5" }), active: viewMode === "files" });
8127
+ if (filter.type === "text") {
8128
+ return /* @__PURE__ */ jsx(TextFilter, { name: filter.name, placeholder: filter.placeholder });
6963
8129
  }
6964
- return /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": "View mode", className: "hidden items-center rounded-md border border-border bg-muted p-0.5 lg:flex h-10", children: modes.map(({ mode, icon, active }) => /* @__PURE__ */ jsxs(
6965
- "button",
8130
+ if (!table) return null;
8131
+ return /* @__PURE__ */ jsx(SelectFilter, { name: filter.name, options: filter.options || [], placeholder: filter.placeholder, inputType: filter.type });
8132
+ }
8133
+ function TableFilters() {
8134
+ const filters = useTableStore.use.filters();
8135
+ if (!filters?.length) return null;
8136
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2 flex-1 min-w-0", children: filters.map((filter) => /* @__PURE__ */ jsx(
8137
+ "div",
6966
8138
  {
6967
- type: "button",
6968
- role: "tab",
6969
- "aria-label": `${mode.charAt(0).toUpperCase() + mode.slice(1)} view`,
6970
- "aria-selected": active,
6971
- onClick: () => setViewMode(mode),
6972
- className: cn(
6973
- "inline-flex h-8 items-center justify-center gap-1.5 rounded px-2.5 text-xs font-medium text-muted-foreground transition-colors",
6974
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
6975
- active ? "bg-background text-foreground shadow-sm" : "hover:bg-accent hover:text-foreground"
6976
- ),
6977
- children: [
6978
- icon,
6979
- toolbarLabels && /* @__PURE__ */ jsx("span", { children: getModeLabel(mode) })
6980
- ]
8139
+ className: cn(defaultWrapperClass(filter), filter.className),
8140
+ children: /* @__PURE__ */ jsx(RenderFilter, { filter })
6981
8141
  },
6982
- mode
8142
+ filter.name
6983
8143
  )) });
6984
8144
  }
6985
8145
  function TableAddButton() {
6986
8146
  const onAddClick = useTableStore.use.onAddClick();
6987
8147
  const showAddButton = useTableStore.use.showAddButton();
6988
8148
  const addButtonText = useTableStore.use.addButtonText();
8149
+ const headerColor = useTableStore.use.headerColor();
8150
+ const bordered = useTableStore.use.bordered();
6989
8151
  if (!showAddButton) return null;
6990
- return /* @__PURE__ */ jsxs(Fragment, { children: [
6991
- /* @__PURE__ */ jsxs("div", { onClick: onAddClick, className: "lg:hidden flex justify-center w-full items-center gap-2 cursor-pointer bg-primary h-10 px-4 rounded-lg hover:bg-primary/90", children: [
6992
- /* @__PURE__ */ jsx(Plus, { className: "h-5 w-5 text-white" }),
6993
- /* @__PURE__ */ jsx("span", { className: "text-white text-sm font-medium", children: addButtonText || "Create" })
6994
- ] }),
6995
- /* @__PURE__ */ jsx("button", { type: "button", onClick: onAddClick ?? void 0, className: "hidden lg:flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary text-white transition-colors hover:bg-primary/90", children: /* @__PURE__ */ jsx(Plus, { className: "h-5 w-5" }) })
6996
- ] });
8152
+ const accentHex = headerColor ? HEADER_HEX[headerColor] : void 0;
8153
+ const btnStyle = accentHex ? { backgroundColor: accentHex } : void 0;
8154
+ const baseCls = accentHex ? "hover:opacity-90" : "bg-primary hover:bg-primary/90";
8155
+ const borderedCls = bordered ? "border border-muted-foreground" : "";
8156
+ return /* @__PURE__ */ jsx(
8157
+ "button",
8158
+ {
8159
+ type: "button",
8160
+ onClick: onAddClick ?? void 0,
8161
+ style: btnStyle,
8162
+ "aria-label": addButtonText || "Create",
8163
+ title: addButtonText || "Create",
8164
+ className: `h-10 w-10 shrink-0 cursor-pointer flex items-center justify-center rounded-lg text-white transition-opacity ${baseCls} ${borderedCls}`,
8165
+ children: /* @__PURE__ */ jsx(Plus, { className: "h-5 w-5" })
8166
+ }
8167
+ );
6997
8168
  }
6998
- function ColumnVisibility() {
6999
- const table = useTableStore.use.table();
8169
+ function TableSettingsMenu() {
8170
+ const showViewToggle = useTableStore.use.showViewToggle();
7000
8171
  const showColumnVisibility = useTableStore.use.showColumnVisibility();
7001
- const toolbarLabels = useTableStore.use.toolbarLabels();
7002
- if (!table || !showColumnVisibility) return null;
7003
- return /* @__PURE__ */ jsxs(Select, { children: [
7004
- /* @__PURE__ */ jsx(SelectTrigger, { className: cn("h-10 bg-card border-border text-sm gap-1.5 px-3", toolbarLabels ? "min-w-[110px]" : "w-10 justify-center [&>svg:last-child]:hidden"), children: toolbarLabels ? /* @__PURE__ */ jsx(SelectValue, { placeholder: "Columns" }) : /* @__PURE__ */ jsx(List, { className: "h-4 w-4 shrink-0" }) }),
7005
- /* @__PURE__ */ jsx(SelectContent, { children: table.getAllColumns().filter((column) => column.getCanHide()).map((column) => /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2 py-1 px-2", children: [
7006
- /* @__PURE__ */ jsx(Checkbox, { id: column.id, checked: column.getIsVisible(), onCheckedChange: (checked) => column.toggleVisibility(!!checked) }),
7007
- /* @__PURE__ */ jsx("label", { htmlFor: column.id, className: "capitalize cursor-pointer text-sm", children: column.id })
7008
- ] }, column.id)) })
8172
+ const availableModes = useTableStore.use.availableModes();
8173
+ const viewMode = useTableStore.use.viewMode();
8174
+ const setViewMode = useTableStore.use.setViewMode();
8175
+ const jsonValue = useTableStore.use.jsonValue();
8176
+ const renderJson = useTableStore.use.renderJson();
8177
+ const cardComponent = useTableStore.use.CardComponent();
8178
+ const table = useTableStore.use.table();
8179
+ const bordered = useTableStore.use.bordered();
8180
+ if (!showViewToggle && !showColumnVisibility) return null;
8181
+ const allModes = ["table", "cards", "json", "files"];
8182
+ const filteredModes = availableModes ?? allModes;
8183
+ const modeItems = [];
8184
+ if (showViewToggle) {
8185
+ if (filteredModes.includes("table"))
8186
+ modeItems.push({ value: "table", label: "Table", icon: /* @__PURE__ */ jsx(List, { className: "h-4 w-4" }) });
8187
+ if (filteredModes.includes("cards") && cardComponent)
8188
+ modeItems.push({ value: "cards", label: "Cards", icon: /* @__PURE__ */ jsx(LayoutGrid, { className: "h-4 w-4" }) });
8189
+ if (filteredModes.includes("json") && (jsonValue !== void 0 || renderJson))
8190
+ modeItems.push({ value: "json", label: "JSON", icon: /* @__PURE__ */ jsx(Code, { className: "h-4 w-4" }) });
8191
+ if (filteredModes.includes("files"))
8192
+ modeItems.push({ value: "files", label: "Files", icon: /* @__PURE__ */ jsx(FolderOpen, { className: "h-4 w-4" }) });
8193
+ }
8194
+ const columns = table?.getAllColumns?.().filter((c) => c.getCanHide()) ?? [];
8195
+ const hasModes = modeItems.length > 0;
8196
+ const hasColumns = columns.length > 0;
8197
+ 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" }) }) }),
8199
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-56 bg-card", children: [
8200
+ showViewToggle && hasModes && /* @__PURE__ */ jsxs(Fragment, { children: [
8201
+ /* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "flex items-center gap-2", children: [
8202
+ /* @__PURE__ */ jsx(Eye, { className: "h-3.5 w-3.5" }),
8203
+ "View"
8204
+ ] }),
8205
+ /* @__PURE__ */ jsx(DropdownMenuRadioGroup, { value: viewMode, onValueChange: (v) => setViewMode(v), children: modeItems.map((item) => /* @__PURE__ */ jsxs(DropdownMenuRadioItem, { value: item.value, children: [
8206
+ item.icon,
8207
+ /* @__PURE__ */ jsx("span", { children: item.label })
8208
+ ] }, item.value)) })
8209
+ ] }),
8210
+ showViewToggle && hasModes && showColumnVisibility && hasColumns && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
8211
+ showColumnVisibility && hasColumns && /* @__PURE__ */ jsxs(Fragment, { children: [
8212
+ /* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "flex items-center gap-2", children: [
8213
+ /* @__PURE__ */ jsx(Columns3, { className: "h-3.5 w-3.5" }),
8214
+ "Columns"
8215
+ ] }),
8216
+ columns.map((col) => /* @__PURE__ */ jsx(
8217
+ DropdownMenuCheckboxItem,
8218
+ {
8219
+ checked: col.getIsVisible(),
8220
+ onCheckedChange: (c) => col.toggleVisibility(!!c),
8221
+ children: /* @__PURE__ */ jsx("span", { className: "capitalize", children: col.id })
8222
+ },
8223
+ col.id
8224
+ ))
8225
+ ] })
8226
+ ] })
7009
8227
  ] });
7010
8228
  }
7011
8229
  function TableToolbarSlot() {
@@ -7019,31 +8237,41 @@ function NTableHeader() {
7019
8237
  const hasControls = useTableStore.use.hasControls();
7020
8238
  const isLoading = useTableStore.use.isLoading();
7021
8239
  const error = useTableStore.use.error();
8240
+ const hasNoData = useTableStore.use.hasNoData();
8241
+ const isFilteredEmpty = useTableStore.use.isFilteredEmpty();
7022
8242
  const filters = useTableStore.use.filters();
7023
8243
  const headerSlot = useTableStore.use.headerSlot();
7024
8244
  const renderToolbar = useTableStore.use.renderToolbar();
7025
8245
  const classNames = useTableStore.use.classNames();
7026
8246
  const isCustomMode = useTableStore.use.isCustomMode();
7027
8247
  const showViewToggle = useTableStore.use.showViewToggle();
7028
- if (isLoading || error) return null;
8248
+ const showColumnVisibility = useTableStore.use.showColumnVisibility();
8249
+ const hideDataChrome = isLoading || error || hasNoData && !isFilteredEmpty;
7029
8250
  if (isCustomMode) {
7030
- if (!showViewToggle && !headerSlot) return null;
7031
- return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-3 flex-wrap lg:flex-nowrap", headerSlot ? "justify-between" : "justify-end", classNames?.header), children: [
7032
- headerSlot && /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: headerSlot }),
7033
- showViewToggle && /* @__PURE__ */ jsx(TableModeButtons, {})
8251
+ if (!showViewToggle && !showColumnVisibility && !headerSlot && !hasControls) return null;
8252
+ if (hideDataChrome && !hasControls) return null;
8253
+ const justify2 = headerSlot && !hideDataChrome ? "justify-between" : "justify-end";
8254
+ return /* @__PURE__ */ jsxs("div", { "data-ntable-header": true, className: cn("flex shrink-0 items-center gap-3 flex-wrap lg:flex-nowrap", justify2, classNames?.header), children: [
8255
+ headerSlot && !hideDataChrome && /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: headerSlot }),
8256
+ hasControls && /* @__PURE__ */ jsxs("div", { className: "flex gap-2 shrink-0", children: [
8257
+ /* @__PURE__ */ jsx(TableSettingsMenu, {}),
8258
+ /* @__PURE__ */ jsx(TableAddButton, {})
8259
+ ] })
7034
8260
  ] });
7035
8261
  }
7036
8262
  const hasFilters = Array.isArray(filters) && filters.length > 0;
7037
8263
  const hasToolbar = Boolean(renderToolbar);
7038
8264
  if (!hasFilters && !hasControls && !headerSlot && !hasToolbar) return null;
7039
- return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-3 flex-wrap lg:flex-nowrap", hasControls || headerSlot || hasToolbar ? "justify-between" : "justify-start", classNames?.header), children: [
7040
- /* @__PURE__ */ jsx(TableFilters, {}),
7041
- headerSlot && /* @__PURE__ */ jsx("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: headerSlot }),
7042
- /* @__PURE__ */ jsx(TableToolbarSlot, {}),
7043
- hasControls && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
7044
- /* @__PURE__ */ jsx(TableModeButtons, {}),
7045
- /* @__PURE__ */ jsx(TableAddButton, {}),
7046
- /* @__PURE__ */ jsx(ColumnVisibility, {})
8265
+ if (hideDataChrome && !hasControls) return null;
8266
+ const onlyControls = hideDataChrome && hasControls && !headerSlot && !hasToolbar;
8267
+ const justify = onlyControls ? "justify-end" : hasControls || headerSlot || hasToolbar ? "justify-between" : "justify-start";
8268
+ return /* @__PURE__ */ jsxs("div", { "data-ntable-header": true, className: cn("flex shrink-0 items-center gap-3 flex-wrap lg:flex-nowrap", justify, classNames?.header), children: [
8269
+ !hideDataChrome && /* @__PURE__ */ jsx(TableFilters, {}),
8270
+ headerSlot && !hideDataChrome && /* @__PURE__ */ jsx("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: headerSlot }),
8271
+ !hideDataChrome && /* @__PURE__ */ jsx(TableToolbarSlot, {}),
8272
+ hasControls && /* @__PURE__ */ jsxs("div", { className: "flex gap-2 shrink-0", children: [
8273
+ /* @__PURE__ */ jsx(TableSettingsMenu, {}),
8274
+ /* @__PURE__ */ jsx(TableAddButton, {})
7047
8275
  ] })
7048
8276
  ] });
7049
8277
  }
@@ -7060,7 +8288,7 @@ function NTableJson() {
7060
8288
  const renderJson = useTableStore.use.renderJson();
7061
8289
  const jsonValue = useTableStore.use.jsonValue();
7062
8290
  if (viewMode !== "json") return null;
7063
- return /* @__PURE__ */ jsx("div", { className: "flex-1 flex flex-col min-h-0 overflow-hidden", children: renderJson?.() ?? /* @__PURE__ */ jsx("pre", { className: "h-full min-h-0 overflow-auto rounded-md border border-border bg-muted/40 p-4 font-mono text-xs leading-relaxed text-foreground", children: formatJsonValue(jsonValue) }) });
8291
+ return /* @__PURE__ */ jsx("div", { className: "flex-1 flex flex-col min-h-0 overflow-hidden", children: renderJson?.() ?? /* @__PURE__ */ jsx(NajmScroll, { axis: "both", className: "h-full min-h-0 rounded-md border border-border bg-muted/40", children: /* @__PURE__ */ jsx("pre", { className: "p-4 font-mono text-xs leading-relaxed text-foreground", children: formatJsonValue(jsonValue) }) }) });
7064
8292
  }
7065
8293
  var DEFAULT_ROWS = 6;
7066
8294
  function NTableLoadingSkeleton({ rows = DEFAULT_ROWS }) {
@@ -7080,10 +8308,10 @@ function NTableLoadingSkeleton({ rows = DEFAULT_ROWS }) {
7080
8308
  "data-testid": "ntable-loading-skeleton",
7081
8309
  "aria-busy": "true",
7082
8310
  "aria-label": loadingText,
7083
- className: cn("rounded-md p-0 border", dynamicHeight ? "overflow-hidden" : "overflow-auto", classNames?.content),
8311
+ className: cn("rounded-md p-0 border", dynamicHeight ? "overflow-hidden" : "najm-overlay-scroll", classNames?.content),
7084
8312
  children: [
7085
8313
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: loadingText }),
7086
- /* @__PURE__ */ jsx("div", { className: dynamicHeight ? "overflow-auto" : void 0, children: /* @__PURE__ */ jsxs(Table, { children: [
8314
+ /* @__PURE__ */ jsx("div", { className: dynamicHeight ? "najm-overlay-scroll" : void 0, children: /* @__PURE__ */ jsxs(Table, { children: [
7087
8315
  /* @__PURE__ */ jsx(TableHeader, { className: cn(headerClassName, dynamicHeight && "sticky top-0 z-10", classNames?.tableHeader), children: /* @__PURE__ */ jsxs(TableRow, { className: "hover:bg-muted/30", children: [
7088
8316
  showCheckbox && /* @__PURE__ */ jsx(TableHead, { "aria-label": "Select column", className: "w-10 text-foreground h-12" }),
7089
8317
  hasExpansion && /* @__PURE__ */ jsx(TableHead, { "aria-label": "Expand column", className: "w-10 text-foreground h-12" }),
@@ -7115,11 +8343,43 @@ function NTableLoadingSkeleton({ rows = DEFAULT_ROWS }) {
7115
8343
  }
7116
8344
  );
7117
8345
  }
8346
+ function TableStateSlot({ children }) {
8347
+ return /* @__PURE__ */ jsx("div", { className: "flex min-h-64 flex-1 items-center justify-center", children });
8348
+ }
8349
+ function DefaultTableEmptyState({ title }) {
8350
+ const onAddClick = useTableStore.use.onAddClick();
8351
+ const showAddButton = useTableStore.use.showAddButton();
8352
+ const addButtonText = useTableStore.use.addButtonText();
8353
+ const bordered = useTableStore.use.bordered();
8354
+ const canAdd = Boolean(showAddButton && onAddClick);
8355
+ return /* @__PURE__ */ jsx(
8356
+ NEmptyState,
8357
+ {
8358
+ icon: Inbox,
8359
+ title,
8360
+ description: canAdd ? "Add your first item to get started." : void 0,
8361
+ action: canAdd ? /* @__PURE__ */ jsxs(Button, { size: "sm", bordered, onClick: () => onAddClick?.(), children: [
8362
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
8363
+ addButtonText || "Add item"
8364
+ ] }) : void 0
8365
+ }
8366
+ );
8367
+ }
8368
+ function DefaultTableFilteredEmptyState() {
8369
+ return /* @__PURE__ */ jsx(
8370
+ NEmptyState,
8371
+ {
8372
+ icon: SearchX,
8373
+ title: "No results found",
8374
+ description: "Try adjusting your filters."
8375
+ }
8376
+ );
8377
+ }
7118
8378
  function TableLayout(props) {
7119
8379
  const containerRef = useRef(null);
7120
8380
  const classNames = useTableStore.use.classNames?.();
7121
8381
  const className = useTableStore.use.className();
7122
- const dynamicHeight = useTableStore.use.dynamicHeight();
8382
+ useTableStore.use.dynamicHeight();
7123
8383
  const isLoading = useTableStore.use.isLoading();
7124
8384
  const error = useTableStore.use.error();
7125
8385
  const hasNoData = useTableStore.use.hasNoData();
@@ -7143,7 +8403,11 @@ function TableLayout(props) {
7143
8403
  }, []);
7144
8404
  useDynamicPageSize(containerRef);
7145
8405
  useTable();
7146
- useTableKeyboard();
8406
+ useTableKeyboard({
8407
+ scopeRef: containerRef,
8408
+ contextMenuClose: props.contextMenuClose,
8409
+ contextMenuOpen: props.contextMenuOpen
8410
+ });
7147
8411
  const effectiveMode = (() => {
7148
8412
  if (viewMode === "json") return "json";
7149
8413
  if (isMobile && responsiveCards && CardComponent) return "cards";
@@ -7152,18 +8416,18 @@ function TableLayout(props) {
7152
8416
  const showFilteredEmpty = isFilteredEmpty && !isLoading && !error;
7153
8417
  const showEmpty = hasNoData && !isLoading && !error && !showFilteredEmpty;
7154
8418
  const customRenderer = isCustomMode ? renderCustomMode?.[viewMode] : void 0;
7155
- return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: cn("flex flex-col gap-2 w-full h-full px-4 py-2", !dynamicHeight && "overflow-auto", classNames?.root, className), children: [
8419
+ return /* @__PURE__ */ jsxs("div", { ref: containerRef, "data-ntable-root": true, className: cn("flex h-full min-h-0 flex-1 w-full flex-col gap-2 overflow-hidden", classNames?.root, className), children: [
7156
8420
  /* @__PURE__ */ jsx(NTableHeader, {}),
7157
- isCustomMode ? customRenderer ? customRenderer() : null : /* @__PURE__ */ jsxs(Fragment, { children: [
7158
- isLoading && (props.renderLoading ? props.renderLoading() : effectiveMode === "table" ? /* @__PURE__ */ jsx(NTableLoadingSkeleton, {}) : /* @__PURE__ */ jsx(NLoadingState, { label: loadingText })),
7159
- error && !isLoading && (props.renderError ? props.renderError(error) : /* @__PURE__ */ jsx(NErrorState, { message: typeof error === "string" ? error : "An error occurred" })),
7160
- showFilteredEmpty && (props.renderFilteredEmpty ? props.renderFilteredEmpty() : renderFilteredEmpty ? renderFilteredEmpty() : props.renderEmpty ? props.renderEmpty() : /* @__PURE__ */ jsx(NEmptyState, { title: "No results found" })),
7161
- showEmpty && (props.renderEmpty ? props.renderEmpty() : /* @__PURE__ */ jsx(NEmptyState, { title: noDataText })),
8421
+ /* @__PURE__ */ jsx("div", { "data-ntable-body": true, className: "flex min-h-0 flex-1 flex-col gap-2 overflow-hidden", children: isCustomMode ? customRenderer ? customRenderer() : null : /* @__PURE__ */ jsxs(Fragment, { children: [
8422
+ isLoading && (props.renderLoading ? /* @__PURE__ */ jsx(TableStateSlot, { children: props.renderLoading() }) : effectiveMode === "table" ? /* @__PURE__ */ jsx(NTableLoadingSkeleton, {}) : /* @__PURE__ */ jsx(TableStateSlot, { children: /* @__PURE__ */ jsx(NLoadingState, { label: loadingText }) })),
8423
+ error && !isLoading && /* @__PURE__ */ jsx(TableStateSlot, { children: props.renderError ? props.renderError(error) : /* @__PURE__ */ jsx(NErrorState, { message: typeof error === "string" ? error : "An error occurred" }) }),
8424
+ showFilteredEmpty && /* @__PURE__ */ jsx(TableStateSlot, { children: props.renderFilteredEmpty ? props.renderFilteredEmpty() : renderFilteredEmpty ? renderFilteredEmpty() : props.renderEmpty ? props.renderEmpty() : /* @__PURE__ */ jsx(DefaultTableFilteredEmptyState, {}) }),
8425
+ showEmpty && /* @__PURE__ */ jsx(TableStateSlot, { children: props.renderEmpty ? props.renderEmpty() : /* @__PURE__ */ jsx(DefaultTableEmptyState, { title: noDataText }) }),
7162
8426
  /* @__PURE__ */ jsx(NTableContent, { effectiveMode }),
7163
8427
  /* @__PURE__ */ jsx(NTableCards, { effectiveMode }),
7164
- /* @__PURE__ */ jsx(NTableJson, {}),
7165
- /* @__PURE__ */ jsx(NTablePagination, {})
7166
- ] })
8428
+ /* @__PURE__ */ jsx(NTableJson, {})
8429
+ ] }) }),
8430
+ /* @__PURE__ */ jsx("div", { "data-ntable-pagination": true, className: "shrink-0", children: /* @__PURE__ */ jsx(NTablePagination, {}) })
7167
8431
  ] });
7168
8432
  }
7169
8433
  function NTable(props) {
@@ -7194,6 +8458,57 @@ function NTable(props) {
7194
8458
  console.warn(`NTable ignored custom renderer(s) not listed in availableModes: ${ignored.join(", ")}`);
7195
8459
  }
7196
8460
  }, [props.renderCustomMode, availableModes]);
8461
+ const ctx = useContextMenu();
8462
+ const { onView, onEdit, onDelete, menu, menuButton: menuButtonProp, onRowContextMenu } = props;
8463
+ const normalizedMenu = typeof menu === "function" ? { row: menu } : menu ?? {};
8464
+ const hasDefaultActions = Boolean(onView || onEdit || onDelete);
8465
+ const defaultActionRowMenu = useCallback(
8466
+ (row) => {
8467
+ const items = [];
8468
+ if (onView) items.push({ label: "View", icon: Eye, onSelect: () => onView(row) });
8469
+ if (onEdit) items.push({ label: "Edit", icon: Pencil, onSelect: () => onEdit(row) });
8470
+ if (onDelete) {
8471
+ items.push({ label: "Delete", icon: Trash2, danger: true, separatorBefore: items.length > 0, onSelect: () => onDelete(row) });
8472
+ }
8473
+ return items;
8474
+ },
8475
+ [onView, onEdit, onDelete]
8476
+ );
8477
+ const effectiveRowMenu = normalizedMenu.row ?? (hasDefaultActions ? defaultActionRowMenu : void 0);
8478
+ const openItems = useCallback((e, items) => {
8479
+ if (!items.length) return;
8480
+ ctx.open(e, items);
8481
+ }, [ctx]);
8482
+ const handleRowContextMenu = useCallback(
8483
+ (e, row) => {
8484
+ onRowContextMenu?.(e, row);
8485
+ if (e.defaultPrevented || !effectiveRowMenu) return;
8486
+ openItems(e, effectiveRowMenu(row));
8487
+ },
8488
+ [onRowContextMenu, effectiveRowMenu, openItems]
8489
+ );
8490
+ const handleBackgroundContextMenu = useCallback(
8491
+ (e) => {
8492
+ if (!normalizedMenu.background) return;
8493
+ openItems(e, normalizedMenu.background());
8494
+ },
8495
+ [normalizedMenu.background, openItems]
8496
+ );
8497
+ const handleOpenRowMenu = useCallback(
8498
+ (e, row) => {
8499
+ if (!effectiveRowMenu) return;
8500
+ openItems(e, effectiveRowMenu(row));
8501
+ },
8502
+ [effectiveRowMenu, openItems]
8503
+ );
8504
+ const handleManualRowMenu = useCallback(
8505
+ (e, row) => {
8506
+ onRowContextMenu?.(e, row);
8507
+ },
8508
+ [onRowContextMenu]
8509
+ );
8510
+ const autoOpenRowMenu = effectiveRowMenu ? handleOpenRowMenu : onRowContextMenu ? handleManualRowMenu : null;
8511
+ const effectiveMenuButton = Boolean(autoOpenRowMenu) && (menuButtonProp ?? true);
7197
8512
  const store = useStoreSync({
7198
8513
  data: props.data ?? [],
7199
8514
  columns: props.columns ?? [],
@@ -7206,7 +8521,9 @@ function NTable(props) {
7206
8521
  CardComponent: props.renderCard ?? null,
7207
8522
  className: props.className ?? "",
7208
8523
  classNames: props.classNames ?? {},
8524
+ bordered: props.bordered ?? false,
7209
8525
  headerClassName: props.headerClassName ?? "bg-card",
8526
+ headerColor: props.headerColor ?? "primary",
7210
8527
  showCheckbox: props.showCheckbox ?? true,
7211
8528
  selectedRowId: props.selectedRowId ?? null,
7212
8529
  headerSlot: props.headerSlot ?? null,
@@ -7215,7 +8532,10 @@ function NTable(props) {
7215
8532
  onEdit: props.onEdit ?? null,
7216
8533
  onDelete: props.onDelete ?? null,
7217
8534
  onRowClick: props.onRowClick ?? null,
7218
- onRowContextMenu: props.onRowContextMenu ?? null,
8535
+ onRowContextMenu: onRowContextMenu || effectiveRowMenu ? handleRowContextMenu : null,
8536
+ onBackgroundContextMenu: normalizedMenu.background ? handleBackgroundContextMenu : null,
8537
+ openRowMenu: autoOpenRowMenu,
8538
+ menuButton: effectiveMenuButton,
7219
8539
  onCellEdit: props.onCellEdit ?? null,
7220
8540
  onBulkDelete: props.onBulkDelete ?? null,
7221
8541
  onStateChange: props.onStateChange ?? null,
@@ -7268,115 +8588,20 @@ function NTable(props) {
7268
8588
  getRowCanExpand: props.getRowCanExpand ?? null,
7269
8589
  renderSubRow: props.renderSubRow ?? null
7270
8590
  });
7271
- return /* @__PURE__ */ jsx(TableStoreContext.Provider, { value: store, children: /* @__PURE__ */ jsx(
7272
- TableLayout,
7273
- {
7274
- renderEmpty: props.renderEmpty,
7275
- renderFilteredEmpty: props.renderFilteredEmpty,
7276
- renderError: props.renderError,
7277
- renderLoading: props.renderLoading
7278
- }
7279
- ) });
7280
- }
7281
- function NDataCardShell({ row, onClick, onContextMenu, actions, children, className }) {
7282
- const canExpand = row.getCanExpand();
7283
- const isExpanded = canExpand && row.getIsExpanded();
7284
- const isSelected = row.getIsSelected();
7285
- return /* @__PURE__ */ jsxs(
7286
- Card,
7287
- {
7288
- onClick,
7289
- onContextMenu,
7290
- className: cn(
7291
- "relative p-4 h-auto transition-all duration-200 hover:shadow-md group w-full sm:w-[calc(50%-12px)] lg:w-[calc(33%-16px)] xl:w-[calc(25%-18px)]",
7292
- isSelected && "ring-1 ring-primary",
7293
- className
7294
- ),
7295
- children: [
7296
- /* @__PURE__ */ jsx("div", { className: cn("absolute top-2 left-2 z-10 transition-opacity duration-200", isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100"), children: /* @__PURE__ */ jsx(
7297
- Checkbox,
7298
- {
7299
- checked: isSelected,
7300
- onCheckedChange: (value) => {
7301
- row.toggleSelected(!!value);
7302
- },
7303
- onClick: (e) => e.stopPropagation(),
7304
- className: "h-4 w-4"
7305
- }
7306
- ) }),
7307
- actions && (actions.onView || actions.onEdit || actions.onDelete) && /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 h-auto", children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
7308
- /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
7309
- "div",
7310
- {
7311
- onClick: (e) => e.stopPropagation(),
7312
- className: "flex h-8 w-8 p-0 rounded-full cursor-pointer justify-center items-center",
7313
- "aria-label": "Card actions",
7314
- children: /* @__PURE__ */ jsx(MoreVertical, { className: "h-5 w-5" })
7315
- }
7316
- ) }),
7317
- /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-40", children: [
7318
- actions.onView && /* @__PURE__ */ jsxs(
7319
- DropdownMenuItem,
7320
- {
7321
- onClick: (e) => {
7322
- e.stopPropagation();
7323
- actions.onView(row.original);
7324
- },
7325
- className: "cursor-pointer",
7326
- children: [
7327
- /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4 mr-2" }),
7328
- "View"
7329
- ]
7330
- }
7331
- ),
7332
- actions.onEdit && /* @__PURE__ */ jsxs(
7333
- DropdownMenuItem,
7334
- {
7335
- onClick: (e) => {
7336
- e.stopPropagation();
7337
- actions.onEdit(row.original);
7338
- },
7339
- className: "cursor-pointer",
7340
- children: [
7341
- /* @__PURE__ */ jsx(Edit, { className: "h-4 w-4 mr-2" }),
7342
- "Edit"
7343
- ]
7344
- }
7345
- ),
7346
- actions.onDelete && /* @__PURE__ */ jsxs(
7347
- DropdownMenuItem,
7348
- {
7349
- onClick: (e) => {
7350
- e.stopPropagation();
7351
- actions.onDelete(row.original);
7352
- },
7353
- className: "cursor-pointer text-red-500",
7354
- children: [
7355
- /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4 mr-2 text-red-500" }),
7356
- "Delete"
7357
- ]
7358
- }
7359
- )
7360
- ] })
7361
- ] }) }),
7362
- canExpand && /* @__PURE__ */ jsx(
7363
- "button",
7364
- {
7365
- type: "button",
7366
- "aria-label": `${isExpanded ? "Collapse" : "Expand"} row ${row.id}`,
7367
- "aria-expanded": isExpanded,
7368
- onClick: (e) => {
7369
- e.stopPropagation();
7370
- row.toggleExpanded();
7371
- },
7372
- className: "absolute bottom-2 right-2 z-10 flex h-6 w-6 items-center justify-center rounded hover:bg-muted",
7373
- children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
7374
- }
7375
- ),
7376
- children
7377
- ]
7378
- }
7379
- );
8591
+ return /* @__PURE__ */ jsxs(TableStoreContext.Provider, { value: store, children: [
8592
+ /* @__PURE__ */ jsx(
8593
+ TableLayout,
8594
+ {
8595
+ renderEmpty: props.renderEmpty,
8596
+ renderFilteredEmpty: props.renderFilteredEmpty,
8597
+ renderError: props.renderError,
8598
+ renderLoading: props.renderLoading,
8599
+ contextMenuClose: ctx.close,
8600
+ contextMenuOpen: ctx.isOpen
8601
+ }
8602
+ ),
8603
+ ctx.menu
8604
+ ] });
7380
8605
  }
7381
8606
  function NTableCardRoot({ card, children, className, ...rest }) {
7382
8607
  return /* @__PURE__ */ jsx(
@@ -7666,7 +8891,7 @@ function NSmartPasteDialog({
7666
8891
  title,
7667
8892
  description: subtitle,
7668
8893
  width: 560,
7669
- bodyClassName: "min-h-0 flex-1 overflow-y-auto px-6 pt-2 pb-5 flex flex-col",
8894
+ bodyClassName: "px-6 pt-2 pb-5 flex flex-col",
7670
8895
  footer: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-3", children: [
7671
8896
  /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleCancel, children: "Cancel" }),
7672
8897
  /* @__PURE__ */ jsxs(
@@ -7731,7 +8956,7 @@ function NSmartPasteDialog({
7731
8956
  }
7732
8957
  function NSidebarHeader({ children, collapsed, className, classNames }) {
7733
8958
  if (!children) return null;
7734
- return /* @__PURE__ */ jsx("div", { className: cn("flex items-center h-14 min-h-14 px-4 border-b border-border/70 shrink-0", collapsed ? "justify-center" : "justify-between gap-2", classNames?.sidebarHeader, className), children: /* @__PURE__ */ jsx("div", { className: "min-w-0", children }) });
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 }) });
7735
8960
  }
7736
8961
  function NSidebarLogo({
7737
8962
  icon,
@@ -7741,7 +8966,7 @@ function NSidebarLogo({
7741
8966
  collapsed = false
7742
8967
  }) {
7743
8968
  if (!icon && !title && !subtitle) return null;
7744
- const IconNode = typeof icon === "function" || typeof icon === "object" && icon !== null && "$$typeof" in icon ? React32__default.createElement(icon, { className: "h-5 w-5 text-primary" }) : icon;
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;
7745
8970
  return /* @__PURE__ */ jsxs(
7746
8971
  "button",
7747
8972
  {
@@ -7766,6 +8991,9 @@ function defaultIsActive(item, activePath) {
7766
8991
  if (item.id) return activePath === item.id;
7767
8992
  return false;
7768
8993
  }
8994
+ function hasActiveChild(item, activePath, isActive) {
8995
+ return Boolean(item.children?.some((child) => isActive(child, activePath) || hasActiveChild(child, activePath, isActive)));
8996
+ }
7769
8997
  function NSidebarItem({
7770
8998
  item,
7771
8999
  activePath = "",
@@ -7776,14 +9004,18 @@ function NSidebarItem({
7776
9004
  depth = 0,
7777
9005
  classNames
7778
9006
  }) {
7779
- const [open, setOpen] = useState(false);
7780
9007
  const active = isActive(item, activePath);
7781
9008
  const hasChildren = item.children && item.children.length > 0;
9009
+ const childActive = hasActiveChild(item, activePath, isActive);
9010
+ const [open, setOpen] = useState(childActive);
7782
9011
  const Icon2 = item.icon;
9012
+ useEffect(() => {
9013
+ if (childActive) setOpen(true);
9014
+ }, [childActive]);
7783
9015
  const baseClasses = cn(
7784
9016
  "flex items-center gap-3 w-full rounded-md text-sm px-2 font-medium transition-colors h-8 text-left",
7785
9017
  depth > 0 && "pl-7",
7786
- item.disabled ? "opacity-50 cursor-not-allowed" : active ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-accent hover:text-accent-foreground",
9018
+ 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",
7787
9019
  classNames?.sidebarItem
7788
9020
  );
7789
9021
  const handleClick = () => {
@@ -7904,7 +9136,7 @@ function NSidebarContent({
7904
9136
  showSectionSeparators,
7905
9137
  classNames
7906
9138
  }) {
7907
- return /* @__PURE__ */ jsx("nav", { className: "flex-1 overflow-y-auto flex flex-col gap-3 px-4 py-2", children: groups.map((group, gi) => /* @__PURE__ */ jsx(
9139
+ return /* @__PURE__ */ jsx(NajmScroll, { axis: "y", className: "flex-1", children: /* @__PURE__ */ jsx("nav", { className: "flex flex-col gap-3 px-4 py-2", children: groups.map((group, gi) => /* @__PURE__ */ jsx(
7908
9140
  NSidebarSection,
7909
9141
  {
7910
9142
  group,
@@ -7920,24 +9152,25 @@ function NSidebarContent({
7920
9152
  classNames
7921
9153
  },
7922
9154
  gi
7923
- )) });
9155
+ )) }) });
7924
9156
  }
7925
9157
  function DefaultFooter({
7926
9158
  onSettings,
7927
9159
  settingsLabel = "Settings",
7928
9160
  onLogout,
7929
- logoutLabel = "Logout"
9161
+ logoutLabel = "Logout",
9162
+ collapsed = false
7930
9163
  }) {
7931
9164
  if (!onSettings && !onLogout) return null;
7932
- const itemClass = "flex items-center gap-3 w-full h-9 rounded-md text-sm font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors text-left";
9165
+ const itemClass = "flex h-8 w-full cursor-pointer items-center gap-3 rounded-md px-2 text-left text-sm font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors";
7933
9166
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
7934
- onSettings && /* @__PURE__ */ jsxs("button", { type: "button", onClick: onSettings, className: itemClass, children: [
9167
+ onSettings && /* @__PURE__ */ jsxs("button", { type: "button", onClick: onSettings, className: itemClass, "aria-label": settingsLabel, title: settingsLabel, children: [
7935
9168
  /* @__PURE__ */ jsx(Settings, { className: "h-4 w-4 shrink-0" }),
7936
- /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: settingsLabel })
9169
+ !collapsed && /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: settingsLabel })
7937
9170
  ] }),
7938
- onLogout && /* @__PURE__ */ jsxs("button", { type: "button", onClick: onLogout, className: itemClass, children: [
9171
+ onLogout && /* @__PURE__ */ jsxs("button", { type: "button", onClick: onLogout, className: itemClass, "aria-label": logoutLabel, title: logoutLabel, children: [
7939
9172
  /* @__PURE__ */ jsx(LogOut, { className: "h-4 w-4 shrink-0" }),
7940
- /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: logoutLabel })
9173
+ !collapsed && /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: logoutLabel })
7941
9174
  ] })
7942
9175
  ] });
7943
9176
  }
@@ -7950,25 +9183,28 @@ function NSidebarFooter({
7950
9183
  showCollapseButton,
7951
9184
  collapsed = false,
7952
9185
  onToggleCollapsed,
7953
- collapseLabel = "Collapse sidebar",
7954
- expandLabel = "Expand sidebar",
9186
+ collapseLabel = "Collapse",
9187
+ expandLabel = "Expand",
7955
9188
  isMobile = false,
7956
9189
  className,
7957
9190
  classNames
7958
9191
  }) {
7959
- const defaultFooter = !(onSettings || onLogout) ? null : /* @__PURE__ */ jsx(DefaultFooter, { onSettings, settingsLabel, onLogout, logoutLabel });
9192
+ const defaultFooter = !(onSettings || onLogout) ? null : /* @__PURE__ */ jsx(DefaultFooter, { onSettings, settingsLabel, onLogout, logoutLabel, collapsed });
7960
9193
  const footerContent = children ?? defaultFooter;
7961
9194
  const showCollapseInFooter = showCollapseButton && !isMobile;
7962
9195
  const CollapseIcon = collapsed ? PanelLeftOpen : PanelLeftClose;
7963
9196
  if (!footerContent && !showCollapseInFooter) return null;
7964
- return /* @__PURE__ */ jsxs("div", { className: cn("border-t border-border/70 p-2 shrink-0 flex flex-col gap-1", classNames?.sidebarFooter, className), children: [
9197
+ return /* @__PURE__ */ jsxs("div", { className: cn("border-t border-border/70 px-4 py-2 shrink-0 flex flex-col gap-1", classNames?.sidebarFooter, className), children: [
7965
9198
  footerContent,
7966
9199
  showCollapseInFooter && /* @__PURE__ */ jsxs(
7967
9200
  "button",
7968
9201
  {
7969
9202
  type: "button",
7970
9203
  onClick: onToggleCollapsed,
7971
- className: "flex items-center gap-3 w-full rounded-md text-sm font-medium transition-colors h-8 text-left text-muted-foreground hover:bg-accent hover:text-accent-foreground",
9204
+ className: cn(
9205
+ "flex items-center w-full cursor-pointer rounded-md text-sm font-medium transition-colors h-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground",
9206
+ "gap-3 px-2 text-left"
9207
+ ),
7972
9208
  "aria-label": collapsed ? expandLabel : collapseLabel,
7973
9209
  title: collapsed ? expandLabel : collapseLabel,
7974
9210
  children: [
@@ -7984,11 +9220,13 @@ function NSidebarMobile({
7984
9220
  onOpen,
7985
9221
  onClose,
7986
9222
  mobileBreakpoint = "md",
9223
+ width = 240,
7987
9224
  hamburgerLabel = "Open sidebar",
7988
9225
  closeLabel = "Close sidebar",
7989
9226
  hamburgerClassName,
7990
9227
  showHamburgerButton = true,
7991
- children
9228
+ children,
9229
+ bordered = false
7992
9230
  }) {
7993
9231
  const mobileClass = mobileBreakpoint === "sm" ? "sm:hidden" : mobileBreakpoint === "lg" ? "lg:hidden" : "md:hidden";
7994
9232
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -8019,10 +9257,12 @@ function NSidebarMobile({
8019
9257
  "aside",
8020
9258
  {
8021
9259
  className: cn(
8022
- "fixed inset-y-0 left-0 z-50 w-60 bg-card border-r flex flex-col transition-transform duration-200",
9260
+ "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",
8023
9262
  mobileClass,
8024
9263
  open ? "translate-x-0" : "-translate-x-full"
8025
9264
  ),
9265
+ style: { width },
8026
9266
  children: [
8027
9267
  /* @__PURE__ */ jsx(
8028
9268
  "button",
@@ -8068,6 +9308,7 @@ function NSidebar({
8068
9308
  showSectionLabels = true,
8069
9309
  showSectionIcons = true,
8070
9310
  showSectionSeparators = false,
9311
+ bordered = false,
8071
9312
  footer,
8072
9313
  className,
8073
9314
  classNames,
@@ -8078,8 +9319,8 @@ function NSidebar({
8078
9319
  closeOnNavigate = true,
8079
9320
  hamburgerLabel = "Open sidebar",
8080
9321
  closeLabel = "Close sidebar",
8081
- collapseLabel = "Collapse sidebar",
8082
- expandLabel = "Expand sidebar",
9322
+ collapseLabel = "Collapse",
9323
+ expandLabel = "Expand",
8083
9324
  hamburgerClassName,
8084
9325
  showHamburgerButton = true,
8085
9326
  logoIcon,
@@ -8089,7 +9330,8 @@ function NSidebar({
8089
9330
  onSettings,
8090
9331
  settingsLabel,
8091
9332
  onLogout,
8092
- logoutLabel
9333
+ logoutLabel,
9334
+ widths
8093
9335
  }) {
8094
9336
  const [_mobileOpen, _setMobileOpen] = useState(defaultMobileOpen);
8095
9337
  const [_collapsed, _setCollapsed] = useState(defaultCollapsed);
@@ -8111,6 +9353,9 @@ function NSidebar({
8111
9353
  }, [onNavigate, closeOnNavigate]);
8112
9354
  const groups = useMemo(() => buildGroups(navItems), [navItems]);
8113
9355
  const desktopClass = mobileBreakpoint === "sm" ? "hidden sm:flex" : mobileBreakpoint === "lg" ? "hidden lg:flex" : "hidden md:flex";
9356
+ const expandedWidth = widths?.expanded ?? 240;
9357
+ const collapsedWidth = widths?.collapsed ?? 64;
9358
+ const mobileWidth = widths?.mobile ?? expandedWidth;
8114
9359
  const defaultLogoContent = logoIcon || logoTitle || logoSubtitle ? /* @__PURE__ */ jsx(NSidebarLogo, { icon: logoIcon, title: logoTitle, subtitle: logoSubtitle, onClick: onLogoClick, collapsed }) : null;
8115
9360
  const headerContent = logo ?? defaultLogoContent;
8116
9361
  const contentProps = {
@@ -8156,14 +9401,29 @@ function NSidebar({
8156
9401
  onOpen: () => setMobileOpen(true),
8157
9402
  onClose: () => setMobileOpen(false),
8158
9403
  mobileBreakpoint,
9404
+ width: mobileWidth,
8159
9405
  hamburgerLabel,
8160
9406
  closeLabel,
8161
9407
  hamburgerClassName,
8162
9408
  showHamburgerButton,
9409
+ bordered,
8163
9410
  children: mobileInner
8164
9411
  }
8165
9412
  ),
8166
- /* @__PURE__ */ jsx("aside", { className: cn(desktopClass, "flex flex-col h-full bg-card transition-all duration-200", collapsed ? "w-16" : "w-60", classNames?.sidebar, className), children: sidebarInner })
9413
+ /* @__PURE__ */ jsx(
9414
+ "aside",
9415
+ {
9416
+ className: cn(
9417
+ desktopClass,
9418
+ "flex flex-col h-full bg-card transition-all duration-200",
9419
+ bordered && "border border-muted-foreground shadow-none",
9420
+ classNames?.sidebar,
9421
+ className
9422
+ ),
9423
+ style: { width: collapsed ? collapsedWidth : expandedWidth },
9424
+ children: sidebarInner
9425
+ }
9426
+ )
8167
9427
  ] });
8168
9428
  }
8169
9429
  function getInitials2(name) {
@@ -8187,7 +9447,7 @@ function NNavbar({
8187
9447
  "header",
8188
9448
  {
8189
9449
  className: cn(
8190
- "flex items-center justify-between h-14 px-4 border-b bg-card shrink-0",
9450
+ "flex items-center justify-between h-14 px-4 bg-card shadow-sm shrink-0",
8191
9451
  classNames?.navbar,
8192
9452
  className
8193
9453
  ),
@@ -8232,7 +9492,7 @@ function NNavbar({
8232
9492
  (userMenuActions.length > 0 || onLogout) && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
8233
9493
  userMenuActions.map((action) => {
8234
9494
  const ActionIcon = action.icon;
8235
- return /* @__PURE__ */ jsxs(React32__default.Fragment, { children: [
9495
+ return /* @__PURE__ */ jsxs(React38__default.Fragment, { children: [
8236
9496
  action.separator && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
8237
9497
  /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: action.onClick, className: "cursor-pointer", children: [
8238
9498
  ActionIcon && /* @__PURE__ */ jsx(ActionIcon, { className: "h-4 w-4 mr-2" }),
@@ -8271,6 +9531,7 @@ function NAppShell({
8271
9531
  defaultCollapsed = false,
8272
9532
  onCollapsedChange,
8273
9533
  collapseButtonPosition,
9534
+ widths,
8274
9535
  sidebarFooter,
8275
9536
  navbarLeft,
8276
9537
  navbarRight,
@@ -8318,6 +9579,7 @@ function NAppShell({
8318
9579
  onCollapsedChange: handleToggleCollapsed,
8319
9580
  footer: sidebarFooter,
8320
9581
  collapseButtonPosition,
9582
+ widths,
8321
9583
  classNames,
8322
9584
  mobileOpen,
8323
9585
  onMobileOpenChange: setMobileOpen,
@@ -8341,7 +9603,7 @@ function NAppShell({
8341
9603
  classNames
8342
9604
  }
8343
9605
  ),
8344
- /* @__PURE__ */ jsx("main", { className: cn("flex-1 overflow-y-auto", classNames?.content), children })
9606
+ /* @__PURE__ */ jsx(NajmScroll, { element: "main", axis: "y", className: cn("flex-1", classNames?.content), children })
8345
9607
  ] })
8346
9608
  ] });
8347
9609
  }
@@ -8383,50 +9645,82 @@ function NCommandPalette({
8383
9645
  ] })
8384
9646
  ] });
8385
9647
  }
8386
- function NPageHeader({ icon: Icon2, title, subtitle, actions, filters, top, footer, search, children, contentClassName, contentRef }) {
9648
+ function NPageHeaderActions({ children, className }) {
9649
+ return /* @__PURE__ */ jsx("div", { className: cn("flex shrink-0 items-center gap-2 sm:gap-3", className), children });
9650
+ }
9651
+ NPageHeaderActions.displayName = "NPageHeaderActions";
9652
+ function NPageHeaderFilters({ children, className }) {
9653
+ return /* @__PURE__ */ jsx("div", { className: cn("px-4 py-3 sm:px-5", className), children });
9654
+ }
9655
+ NPageHeaderFilters.displayName = "NPageHeaderFilters";
9656
+ function NPageHeaderTop({ children, className }) {
9657
+ return /* @__PURE__ */ jsx("div", { className, children });
9658
+ }
9659
+ NPageHeaderTop.displayName = "NPageHeaderTop";
9660
+ function isPageHeaderSlot(child, slot) {
9661
+ return React38__default.isValidElement(child) && child.type === slot;
9662
+ }
9663
+ function getSlotElements(children, slot) {
9664
+ const matches = React38__default.Children.toArray(children).filter((child) => isPageHeaderSlot(child, slot));
9665
+ return matches.length > 0 ? matches : void 0;
9666
+ }
9667
+ function NPageHeader({ icon: Icon2, title, subtitle, actions, filters, top, search, children, className, headerClassName, bordered = false }) {
8387
9668
  const [internalSearch, setInternalSearch] = useState("");
8388
9669
  const searchValue = search?.value ?? internalSearch;
8389
9670
  const handleSearchChange = useCallback((e) => {
8390
9671
  setInternalSearch(e.target.value);
8391
9672
  search?.onChange?.(e);
8392
9673
  }, [search?.onChange]);
8393
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
8394
- /* @__PURE__ */ jsxs("div", { className: "flex min-h-14 flex-row items-center justify-between gap-2 border-b border-border px-4 pl-16 sm:px-5 md:pl-5", children: [
8395
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [
8396
- /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 shrink-0 rounded-lg bg-primary/10 items-center justify-center", children: /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4 text-primary" }) }),
8397
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
8398
- /* @__PURE__ */ jsx("h2", { className: "truncate text-sm font-semibold text-foreground", children: title }),
8399
- subtitle && /* @__PURE__ */ jsx("p", { className: "truncate text-xs leading-relaxed text-muted-foreground sm:text-sm sm:leading-normal", children: subtitle })
8400
- ] })
8401
- ] }),
8402
- /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-3", children: [
8403
- search && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
8404
- /* @__PURE__ */ jsx(Search, { size: 14, className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none" }),
8405
- /* @__PURE__ */ jsx(
8406
- "input",
8407
- {
8408
- ref: search.ref,
8409
- type: "text",
8410
- value: searchValue,
8411
- placeholder: search.placeholder ?? "Search...",
8412
- className: cn(
8413
- "h-9 w-full max-w-[280px] rounded-lg bg-background pl-9 pr-3 text-sm text-foreground placeholder:text-muted-foreground outline-none border border-border focus:border-primary focus:ring-1 focus:ring-primary/20 transition-colors",
8414
- search.className
8415
- ),
8416
- onChange: handleSearchChange
8417
- }
8418
- )
9674
+ const slottedActions = getSlotElements(children, NPageHeaderActions);
9675
+ const slottedFilters = getSlotElements(children, NPageHeaderFilters);
9676
+ const slottedTop = getSlotElements(children, NPageHeaderTop);
9677
+ const resolvedActions = slottedActions ?? actions;
9678
+ const resolvedFilters = slottedFilters ?? filters;
9679
+ const resolvedTop = slottedTop ?? top;
9680
+ return /* @__PURE__ */ jsxs(
9681
+ "div",
9682
+ {
9683
+ "data-slot": "page-header",
9684
+ className: cn(
9685
+ "border-b border-border",
9686
+ bordered && "rounded-xl border border-muted-foreground bg-card shadow-none",
9687
+ className
9688
+ ),
9689
+ children: [
9690
+ resolvedTop,
9691
+ /* @__PURE__ */ jsxs("div", { className: cn("flex min-h-14 flex-row items-center justify-between gap-2 px-4 pl-16 sm:px-5 md:pl-5", headerClassName), children: [
9692
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [
9693
+ /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 shrink-0 rounded-lg bg-primary/10 items-center justify-center", children: /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4 text-primary" }) }),
9694
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
9695
+ /* @__PURE__ */ jsx("h2", { className: "truncate text-sm font-semibold text-foreground", children: title }),
9696
+ subtitle && /* @__PURE__ */ jsx("p", { className: "truncate text-xs leading-relaxed text-muted-foreground sm:text-sm sm:leading-normal", children: subtitle })
9697
+ ] })
9698
+ ] }),
9699
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-3", children: [
9700
+ search && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
9701
+ /* @__PURE__ */ jsx(Search, { size: 14, className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none" }),
9702
+ /* @__PURE__ */ jsx(
9703
+ "input",
9704
+ {
9705
+ ref: search.ref,
9706
+ type: "text",
9707
+ value: searchValue,
9708
+ placeholder: search.placeholder ?? "Search...",
9709
+ className: cn(
9710
+ "h-9 w-full max-w-[280px] rounded-lg bg-background pl-9 pr-3 text-sm text-foreground placeholder:text-muted-foreground outline-none border border-border focus:border-primary focus:ring-1 focus:ring-primary/20 transition-colors",
9711
+ search.className
9712
+ ),
9713
+ onChange: handleSearchChange
9714
+ }
9715
+ )
9716
+ ] }),
9717
+ resolvedActions && (slottedActions ? resolvedActions : /* @__PURE__ */ jsx(NPageHeaderActions, { children: resolvedActions }))
9718
+ ] })
8419
9719
  ] }),
8420
- actions && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2 sm:gap-3", children: actions })
8421
- ] })
8422
- ] }),
8423
- top,
8424
- /* @__PURE__ */ jsxs("div", { ref: contentRef, className: contentClassName ?? "flex-1 overflow-auto", children: [
8425
- filters && /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-20 bg-background/95 backdrop-blur", children: /* @__PURE__ */ jsx("div", { className: "px-4 py-3 sm:px-5", children: filters }) }),
8426
- children
8427
- ] }),
8428
- footer
8429
- ] });
9720
+ resolvedFilters && (slottedFilters ? resolvedFilters : /* @__PURE__ */ jsx(NPageHeaderFilters, { children: resolvedFilters }))
9721
+ ]
9722
+ }
9723
+ );
8430
9724
  }
8431
9725
  function NInspectorSheet({ open, onClose, title, children }) {
8432
9726
  useEffect(() => {
@@ -8452,4 +9746,4 @@ function NInspectorSheet({ open, onClose, title, children }) {
8452
9746
  ] }) });
8453
9747
  }
8454
9748
 
8455
- 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, Input, Label, LangInput, MultiSelectInput, NAlert, NAppShell, NCard as NAsyncCard, NAvatar, NBadge, NBulkActionsBar, NButton, NCard, NCardAction, NCardFooter, NCommandPalette, NConfirmDialog, NContextMenu, NDataCardShell, NDeleteDialogContent, NDetailCard, NDetailItem, NDetailList, NDialog, NEmptyState, NErrorBoundary, NErrorState, NFileBrowser, NFileTypeIcon, NFilterBar, NFolderIcon, NForm, NFormSectionHeader, NIcon, NInspectorSheet, NLoadingState, NMultiDialog, NNavbar, NPageHeader, NPortalScopeProvider, NProgress, NRowActions, NSection, NSectionHeader, NSectionInfo, NSectionWithInfo, NSheet, NSidebar, NSidebarContent, NSidebarFooter, NSidebarHeader, NSidebarItem, NSidebarLogo, NSidebarMobile, NSidebarSection, NSkeleton, NSkeletonCalendar, NSkeletonChart, NSkeletonDonut, NSkeletonEventList, NSkeletonWidget, NSkeletonWidgets, NSmartPasteDialog, NSpinner, NStatCard, NStatCardSkeleton, Swap as NSwap, NTable, NTableCardRoot, NTableCards, NTableContent, NTableHeader, NTableJson, NTableLoadingSkeleton, NTablePagination, NTableRowSkeleton, NTableSkeleton, NUploader, NViewBody, NViewToggle, 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, StarRatingInput, StatusPill, StepIndicator, StepsHeader, StepsProgress, Swap, SwapIndeterminate, SwapOff, SwapOn, Switch, SwitchInput, 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, resolvePreset, resolveSlot, 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 };
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 };