najm-kit 2.10.0 → 2.11.0

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,11 +1,13 @@
1
1
  import { resolveAvatarSrc } from './chunk-BEGOH366.mjs';
2
2
  export { isPlaceholderAvatar, resolveAvatarSrc } from './chunk-BEGOH366.mjs';
3
- import { useResolvedFormDevTools, useNBranding } from './chunk-HML2JZXT.mjs';
4
- export { FormDevToolsProvider, NBrandingProvider, NBrandingStateProvider, NajmFormatProvider, buildFormFill, normalizeBranding, useNBranding, useNBrandingEditor, useNajmFormat, useNajmFormatContext } from './chunk-HML2JZXT.mjs';
5
- import { normalizeImageSources, useImageChain, useNBadgeDefaults, mergeBadgeMaps, resolveStatusColor, resolveBadgeStatusLabel, colorTextClass, useResolvedPaginationLabels } from './chunk-FDONJASN.mjs';
6
- export { DEFAULT_PAGINATION_KEY_PREFIX, DEFAULT_TIME_ZONE, EMPTY_DESIGN, NAJM_COLOR_TEXT_CLASSES, NAJM_STATUS_COLORS, NTableDefaultsProvider, NajmDesignEditorProvider, NajmPreferencesProvider, NajmUIProvider, buildPaginationLabels, colorTextClass, findStatusColor, normalizeStatusToken, resolveStatusColor, statusTextClass, useNTableDefaults, useNajmDesignEditor, useNajmPreferencesContext, useNajmTheme, useNajmTimeZone } from './chunk-FDONJASN.mjs';
7
- import { inputBorderClasses, Button, NIcon, NajmScroll, surfaceBorderClasses, useNajmScrollViewport, buttonVariants, NButton, useTableStore, TableStoreContext, sidebarBorderClasses, NTableJson } from './chunk-JUYT2ISO.mjs';
8
- export { Button, NButton, NIcon, NTableJson, NajmScroll, TableStoreContext, buttonVariants, inputBorderClasses, sidebarBorderClasses, surfaceBorderClasses, useTableStore } from './chunk-JUYT2ISO.mjs';
3
+ import { NLoadingState, NErrorState, NEmptyState, useResolvedFormDevTools, useNBranding } from './chunk-2GFWF46W.mjs';
4
+ export { FormDevToolsProvider, NBrandingProvider, NBrandingStateProvider, NEmptyState, NErrorState, NForbiddenState, NLoadingState, NNotFoundState, NPageLayout, NSpinner, NajmFormatProvider, buildFormFill, normalizeBranding, useNBranding, useNBrandingEditor, useNajmFormat, useNajmFormatContext } from './chunk-2GFWF46W.mjs';
5
+ import { normalizeImageSources, useImageChain, useNBadgeDefaults, mergeBadgeMaps, resolveStatusColor, resolveBadgeStatusLabel, colorTextClass, useResolvedPaginationLabels } from './chunk-EEBLEDNI.mjs';
6
+ export { DEFAULT_PAGINATION_KEY_PREFIX, DEFAULT_TIME_ZONE, EMPTY_DESIGN, NAJM_COLOR_TEXT_CLASSES, NAJM_STATUS_COLORS, NTableDefaultsProvider, NajmDesignEditorProvider, NajmPreferencesProvider, NajmUIProvider, buildPaginationLabels, colorTextClass, findStatusColor, normalizeStatusToken, resolveStatusColor, statusTextClass, useNTableDefaults, useNajmDesignEditor, useNajmPreferencesContext, useNajmTheme, useNajmTimeZone } from './chunk-EEBLEDNI.mjs';
7
+ import { NajmScroll, useNajmScrollViewport, useTableStore, TableStoreContext, NTableJson } from './chunk-K7T7X6PX.mjs';
8
+ export { NTableJson, NajmScroll, TableStoreContext, useTableStore } from './chunk-K7T7X6PX.mjs';
9
+ import { inputBorderClasses, Button, NIcon, surfaceBorderClasses, buttonVariants, NButton, sidebarBorderClasses } from './chunk-XZL32HFR.mjs';
10
+ export { Button, NButton, NIcon, buttonVariants, inputBorderClasses, sidebarBorderClasses, surfaceBorderClasses } from './chunk-XZL32HFR.mjs';
9
11
  import { useNajmComponentStyle, cn, NajmThemeContainerCtx, useNajmThemeMode, useNajmDesign, composePreset } from './chunk-KVZACF4G.mjs';
10
12
  export { NajmDesignProvider, NajmThemeProvider, cn, composePreset, resolvePreset, useNajmAppearance, useNajmComponentStyle, useNajmDesign, useNajmThemeMode } from './chunk-KVZACF4G.mjs';
11
13
  export { DEFAULT_CARD_BREAKPOINT, DEFAULT_CARD_PAGINATION_KEY_PREFIX, buildCardPaginationLabels, createCardPagination, useCardViewport, useDesktopTableMode, useMediaQuery } from './chunk-OUS7OYVA.mjs';
@@ -19,7 +21,7 @@ import * as React61 from 'react';
19
21
  import React61__default, { createContext, useRef, useMemo, useState, useEffect, useContext, useCallback, useLayoutEffect, isValidElement } from 'react';
20
22
  import * as TabsPrimitive from '@radix-ui/react-tabs';
21
23
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
22
- import { ChevronDown, AlertTriangle, RefreshCw, X, XIcon, Menu, Search, SearchIcon, CheckIcon, ChevronUp, ChevronDownIcon, ChevronUpIcon, Eye, EyeOff, ChevronsUpDown, Check, CircleIcon, ChevronLeftIcon, ChevronRightIcon, Calendar as Calendar$1, FileUp, Folder, UploadCloud, CheckCircle2, AlertCircle, Camera, Star, Globe, Clock, Trash2, Plus, Upload, Download, RotateCcw, Table as Table$1, FileJson, ChevronRight, ArrowUpDown, Loader2, MoreVertical, Edit, ChevronsLeft, ChevronLeft, ChevronsRight, Pencil, Merge, PanelLeftOpen, PanelLeftClose, LogOut, Image, ArrowUp, ArrowDown, CheckSquare, FilePlus, FolderPlus, Share2, Move, ClipboardPaste, Copy, Scissors, LoaderCircleIcon, LoaderPinwheelIcon, LoaderIcon, ArrowUpRight, ArrowDownRight, SlidersHorizontal, Columns3, Settings, Filter, SearchX, Inbox, List, LayoutGrid, Code, FolderOpen } from 'lucide-react';
24
+ import { ChevronDown, AlertTriangle, RefreshCw, X, XIcon, Menu, Search, SearchIcon, CheckIcon, ChevronUp, ChevronDownIcon, ChevronUpIcon, Eye, EyeOff, ChevronsUpDown, Check, CircleIcon, ChevronLeftIcon, ChevronRightIcon, Calendar as Calendar$1, FileUp, Folder, UploadCloud, CheckCircle2, AlertCircle, Camera, Star, Globe, Clock, Trash2, Plus, Upload, Download, RotateCcw, Table as Table$1, FileJson, ChevronRight, ArrowUpDown, Loader2, Copy, MoreVertical, Edit, ChevronsLeft, ChevronLeft, ChevronsRight, Pencil, Merge, PanelLeftOpen, PanelLeftClose, LogOut, Image, ArrowUp, ArrowDown, CheckSquare, FilePlus, FolderPlus, Share2, Move, ClipboardPaste, Scissors, ArrowUpRight, ArrowDownRight, SlidersHorizontal, Columns3, Settings, Filter, SearchX, Inbox, List, LayoutGrid, Code, FolderOpen } from 'lucide-react';
23
25
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
24
26
  import { cva } from 'class-variance-authority';
25
27
  import { HexColorPicker } from 'react-colorful';
@@ -51,6 +53,9 @@ import { FormProvider, Controller, useFormContext, useForm, useFieldArray } from
51
53
  import { zodResolver } from '@hookform/resolvers/zod';
52
54
  import { getExpandedRowModel, getSortedRowModel, getPaginationRowModel, getFilteredRowModel, getCoreRowModel, useReactTable, flexRender } from '@tanstack/react-table';
53
55
 
56
+ // src/theme/focus.ts
57
+ var focusRingClasses = "outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50";
58
+ var focusRingWithinClasses = "focus-visible:ring-[3px] focus-visible:ring-ring/50 has-[:focus-visible]:ring-[3px] has-[:focus-visible]:ring-ring/50";
54
59
  function Tabs({
55
60
  className,
56
61
  variant = "pills",
@@ -134,7 +139,8 @@ function TabsTrigger({
134
139
  {
135
140
  "data-slot": "tabs-trigger",
136
141
  className: cn(
137
- "inline-flex cursor-pointer items-center justify-center gap-1.5 text-sm font-medium whitespace-nowrap text-muted-foreground transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
142
+ "inline-flex cursor-pointer items-center justify-center gap-1.5 text-sm font-medium whitespace-nowrap text-muted-foreground transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
143
+ focusRingClasses,
138
144
  triggerVariantMap[variant],
139
145
  className
140
146
  ),
@@ -143,7 +149,14 @@ function TabsTrigger({
143
149
  );
144
150
  }
145
151
  function TabsContent({ className, ...props }) {
146
- return /* @__PURE__ */ jsx(TabsPrimitive.Content, { "data-slot": "tabs-content", className: cn("flex-1 outline-none", className), ...props });
152
+ return /* @__PURE__ */ jsx(
153
+ TabsPrimitive.Content,
154
+ {
155
+ "data-slot": "tabs-content",
156
+ className: cn("flex-1", focusRingClasses, className),
157
+ ...props
158
+ }
159
+ );
147
160
  }
148
161
 
149
162
  // src/components/tabs/tabColors.ts
@@ -472,6 +485,13 @@ var BaseInput = React61__default.forwardRef(
472
485
  style: recipeRadius ? { borderRadius: recipeRadius, ...style } : style,
473
486
  className: cn(
474
487
  inputVariants({ variant, status, hasIcon, disabled }),
488
+ // The wrapper is what the user reads as "the field": the inner
489
+ // control is stripped of its own ring precisely so this element can
490
+ // carry the border. Until this was added, the border merely changed
491
+ // colour on focus — a 1px hue shift and nothing else — and the number
492
+ // fields and the multi-select trigger came out of the acceptance walk
493
+ // as tab stops with no visible indicator at all.
494
+ !isGhost && focusRingWithinClasses,
475
495
  !isGhost && borderClass,
476
496
  !isGhost && colorClass,
477
497
  className
@@ -835,8 +855,18 @@ function SegmentedControl({
835
855
  function Collapsible({ ...props }) {
836
856
  return /* @__PURE__ */ jsx(CollapsiblePrimitive.Root, { "data-slot": "collapsible", ...props });
837
857
  }
838
- function CollapsibleTrigger2({ ...props }) {
839
- return /* @__PURE__ */ jsx(CollapsiblePrimitive.CollapsibleTrigger, { "data-slot": "collapsible-trigger", ...props });
858
+ function CollapsibleTrigger2({
859
+ className,
860
+ ...props
861
+ }) {
862
+ return /* @__PURE__ */ jsx(
863
+ CollapsiblePrimitive.CollapsibleTrigger,
864
+ {
865
+ "data-slot": "collapsible-trigger",
866
+ className: cn(focusRingClasses, className),
867
+ ...props
868
+ }
869
+ );
840
870
  }
841
871
  function CollapsibleContent2({ ...props }) {
842
872
  return /* @__PURE__ */ jsx(CollapsiblePrimitive.CollapsibleContent, { "data-slot": "collapsible-content", ...props });
@@ -1126,9 +1156,18 @@ function useResponsivePadding(value) {
1126
1156
  }, [value]);
1127
1157
  return resolved;
1128
1158
  }
1129
- function DialogContent({ className, children, padding, hideClose = false, ...props }) {
1159
+ function DialogContent({
1160
+ className,
1161
+ children,
1162
+ padding,
1163
+ hideClose = false,
1164
+ onOpenAutoFocus,
1165
+ onCloseAutoFocus,
1166
+ ...props
1167
+ }) {
1130
1168
  const resolvedPadding = useResponsivePadding(padding);
1131
1169
  const portalClassName = useNPortalScope();
1170
+ const openerRef = React61.useRef(null);
1132
1171
  return /* @__PURE__ */ jsx(DialogPortal, { "data-slot": "dialog-portal", children: /* @__PURE__ */ jsxs("div", { className: portalClassName, children: [
1133
1172
  /* @__PURE__ */ jsx(DialogOverlay, {}),
1134
1173
  /* @__PURE__ */ jsxs(
@@ -1136,6 +1175,22 @@ function DialogContent({ className, children, padding, hideClose = false, ...pro
1136
1175
  {
1137
1176
  "data-slot": "dialog-content",
1138
1177
  "data-padding": resolvedPadding,
1178
+ onOpenAutoFocus: (event) => {
1179
+ const active = document.activeElement;
1180
+ openerRef.current = active instanceof HTMLElement && active !== document.body ? active : null;
1181
+ onOpenAutoFocus?.(event);
1182
+ },
1183
+ onCloseAutoFocus: (event) => {
1184
+ onCloseAutoFocus?.(event);
1185
+ if (event.defaultPrevented) return;
1186
+ const opener = openerRef.current;
1187
+ setTimeout(() => {
1188
+ if (!opener?.isConnected) return;
1189
+ const active = document.activeElement;
1190
+ const lost = !active || active === document.body || active === document.documentElement || !active.isConnected;
1191
+ if (lost) opener.focus();
1192
+ }, 0);
1193
+ },
1139
1194
  className: cn(
1140
1195
  "bg-card text-card-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-sm translate-x-[-50%] translate-y-[-50%] gap-4 rounded-none lg:rounded-lg najm-border border-border shadow-lg duration-200",
1141
1196
  dialogPaddingMap[resolvedPadding],
@@ -3676,7 +3731,8 @@ function CollapsibleSection({
3676
3731
  className: cn(
3677
3732
  "flex w-full items-center justify-between gap-2 px-3 py-2 text-xs font-semibold uppercase tracking-wide",
3678
3733
  "text-muted-foreground hover:text-foreground",
3679
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:rounded-md",
3734
+ focusRingClasses,
3735
+ "focus-visible:rounded-md",
3680
3736
  "disabled:pointer-events-none disabled:opacity-50"
3681
3737
  ),
3682
3738
  children: [
@@ -3994,7 +4050,8 @@ function TokenGroupSection({
3994
4050
  className: cn(
3995
4051
  "flex w-full items-center justify-between gap-2 px-3 py-2 text-xs font-semibold uppercase tracking-wide",
3996
4052
  "text-muted-foreground hover:text-foreground",
3997
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:rounded-md",
4053
+ focusRingClasses,
4054
+ "focus-visible:rounded-md",
3998
4055
  "disabled:pointer-events-none disabled:opacity-50"
3999
4056
  ),
4000
4057
  "aria-label": labelText,
@@ -8088,115 +8145,6 @@ function TableCell({ className, ...props }) {
8088
8145
  function TableCaption({ className, ...props }) {
8089
8146
  return /* @__PURE__ */ jsx("caption", { "data-slot": "table-caption", className: cn("text-muted-foreground mt-4 text-sm", className), ...props });
8090
8147
  }
8091
- var Default = ({ className, ...props }) => /* @__PURE__ */ jsx(LoaderIcon, { className: cn("animate-spin", className), ...props });
8092
- var Circle = ({ className, ...props }) => /* @__PURE__ */ jsx(LoaderCircleIcon, { className: cn("animate-spin", className), ...props });
8093
- var Pinwheel = ({ className, ...props }) => /* @__PURE__ */ jsx(LoaderPinwheelIcon, { className: cn("animate-spin", className), ...props });
8094
- var CircleFilled = ({ className, size = 24, ...props }) => /* @__PURE__ */ jsxs("div", { className: "relative", style: { width: size, height: size }, children: [
8095
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 rotate-180", children: /* @__PURE__ */ jsx(LoaderCircleIcon, { className: cn("animate-spin", className, "text-foreground opacity-20"), size, ...props }) }),
8096
- /* @__PURE__ */ jsx(LoaderCircleIcon, { className: cn("relative animate-spin", className), size, ...props })
8097
- ] });
8098
- var Ellipsis = ({ size = 24, ...props }) => /* @__PURE__ */ jsxs("svg", { height: size, viewBox: "0 0 24 24", width: size, xmlns: "http://www.w3.org/2000/svg", ...props, children: [
8099
- /* @__PURE__ */ jsx("title", { children: "Loading..." }),
8100
- /* @__PURE__ */ jsx("circle", { cx: "4", cy: "12", fill: "currentColor", r: "2", children: /* @__PURE__ */ jsx("animate", { attributeName: "cy", begin: "0;ellipsis3.end+0.25s", calcMode: "spline", dur: "0.6s", id: "ellipsis1", keySplines: ".33,.66,.66,1;.33,0,.66,.33", values: "12;6;12" }) }),
8101
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", fill: "currentColor", r: "2", children: /* @__PURE__ */ jsx("animate", { attributeName: "cy", begin: "ellipsis1.begin+0.1s", calcMode: "spline", dur: "0.6s", keySplines: ".33,.66,.66,1;.33,0,.66,.33", values: "12;6;12" }) }),
8102
- /* @__PURE__ */ jsx("circle", { cx: "20", cy: "12", fill: "currentColor", r: "2", children: /* @__PURE__ */ jsx("animate", { attributeName: "cy", begin: "ellipsis1.begin+0.2s", calcMode: "spline", dur: "0.6s", id: "ellipsis3", keySplines: ".33,.66,.66,1;.33,0,.66,.33", values: "12;6;12" }) })
8103
- ] });
8104
- var Ring = ({ size = 24, ...props }) => /* @__PURE__ */ jsxs("svg", { height: size, stroke: "currentColor", viewBox: "0 0 44 44", width: size, xmlns: "http://www.w3.org/2000/svg", ...props, children: [
8105
- /* @__PURE__ */ jsx("title", { children: "Loading..." }),
8106
- /* @__PURE__ */ jsxs("g", { fill: "none", fillRule: "evenodd", strokeWidth: "2", children: [
8107
- /* @__PURE__ */ jsxs("circle", { cx: "22", cy: "22", r: "1", children: [
8108
- /* @__PURE__ */ jsx("animate", { attributeName: "r", begin: "0s", calcMode: "spline", dur: "1.8s", keySplines: "0.165, 0.84, 0.44, 1", keyTimes: "0; 1", repeatCount: "indefinite", values: "1; 20" }),
8109
- /* @__PURE__ */ jsx("animate", { attributeName: "stroke-opacity", begin: "0s", calcMode: "spline", dur: "1.8s", keySplines: "0.3, 0.61, 0.355, 1", keyTimes: "0; 1", repeatCount: "indefinite", values: "1; 0" })
8110
- ] }),
8111
- /* @__PURE__ */ jsxs("circle", { cx: "22", cy: "22", r: "1", children: [
8112
- /* @__PURE__ */ jsx("animate", { attributeName: "r", begin: "-0.9s", calcMode: "spline", dur: "1.8s", keySplines: "0.165, 0.84, 0.44, 1", keyTimes: "0; 1", repeatCount: "indefinite", values: "1; 20" }),
8113
- /* @__PURE__ */ jsx("animate", { attributeName: "stroke-opacity", begin: "-0.9s", calcMode: "spline", dur: "1.8s", keySplines: "0.3, 0.61, 0.355, 1", keyTimes: "0; 1", repeatCount: "indefinite", values: "1; 0" })
8114
- ] })
8115
- ] })
8116
- ] });
8117
- var Bars = ({ size = 24, ...props }) => /* @__PURE__ */ jsxs("svg", { height: size, viewBox: "0 0 24 24", width: size, xmlns: "http://www.w3.org/2000/svg", ...props, children: [
8118
- /* @__PURE__ */ jsx("title", { children: "Loading..." }),
8119
- /* @__PURE__ */ jsx("rect", { fill: "currentColor", height: "4", rx: "1", width: "4", x: "1", y: "10", children: /* @__PURE__ */ jsx("animate", { attributeName: "opacity", begin: "0s", dur: "0.6s", keyTimes: "0;0.5;1", repeatCount: "indefinite", values: "1;0.3;1" }) }),
8120
- /* @__PURE__ */ jsx("rect", { fill: "currentColor", height: "4", rx: "1", width: "4", x: "10", y: "10", children: /* @__PURE__ */ jsx("animate", { attributeName: "opacity", begin: "0.1s", dur: "0.6s", keyTimes: "0;0.5;1", repeatCount: "indefinite", values: "1;0.3;1" }) }),
8121
- /* @__PURE__ */ jsx("rect", { fill: "currentColor", height: "4", rx: "1", width: "4", x: "19", y: "10", children: /* @__PURE__ */ jsx("animate", { attributeName: "opacity", begin: "0.2s", dur: "0.6s", keyTimes: "0;0.5;1", repeatCount: "indefinite", values: "1;0.3;1" }) })
8122
- ] });
8123
- var Infinite = ({ size = 24, ...props }) => /* @__PURE__ */ jsxs(
8124
- "svg",
8125
- {
8126
- height: size,
8127
- preserveAspectRatio: "xMidYMid",
8128
- viewBox: "0 0 100 100",
8129
- width: size,
8130
- xmlns: "http://www.w3.org/2000/svg",
8131
- ...props,
8132
- children: [
8133
- /* @__PURE__ */ jsx("title", { children: "Loading..." }),
8134
- /* @__PURE__ */ jsx(
8135
- "path",
8136
- {
8137
- d: "M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40 C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z",
8138
- fill: "none",
8139
- stroke: "currentColor",
8140
- strokeDasharray: "205.271142578125 51.317785644531256",
8141
- strokeLinecap: "round",
8142
- strokeWidth: "10",
8143
- style: { transform: "scale(0.8)", transformOrigin: "50px 50px" },
8144
- children: /* @__PURE__ */ jsx(
8145
- "animate",
8146
- {
8147
- attributeName: "stroke-dashoffset",
8148
- dur: "2s",
8149
- keyTimes: "0;1",
8150
- repeatCount: "indefinite",
8151
- values: "0;256.58892822265625"
8152
- }
8153
- )
8154
- }
8155
- )
8156
- ]
8157
- }
8158
- );
8159
- var spinnerVariants = {
8160
- default: Default,
8161
- circle: Circle,
8162
- pinwheel: Pinwheel,
8163
- "circle-filled": CircleFilled,
8164
- ellipsis: Ellipsis,
8165
- ring: Ring,
8166
- bars: Bars,
8167
- infinite: Infinite
8168
- };
8169
- function NSpinner({ variant = "default", size = 24, className, ...props }) {
8170
- const Component = spinnerVariants[variant] || Default;
8171
- return /* @__PURE__ */ jsx(Component, { className, size, ...props });
8172
- }
8173
- function NLoadingState({ label = "Loading...", className, fullScreen = false, spinnerVariant = "circle", spinnerSize = 32 }) {
8174
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-center justify-center gap-3 py-8", fullScreen && "fixed inset-0 z-50 bg-background/80", className), children: [
8175
- /* @__PURE__ */ jsx(NSpinner, { variant: spinnerVariant, size: spinnerSize }),
8176
- label && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: label })
8177
- ] });
8178
- }
8179
- function NErrorState({ title = "Something went wrong", message, onRetry, retryLabel = "Try again", className, icon }) {
8180
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-center justify-center gap-4 py-8", className), children: [
8181
- /* @__PURE__ */ jsx("div", { className: "text-destructive", children: icon || /* @__PURE__ */ jsx(AlertTriangle, { className: "h-10 w-10" }) }),
8182
- /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
8183
- /* @__PURE__ */ jsx("h3", { className: "font-semibold text-foreground", children: title }),
8184
- message && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm mt-1", children: message })
8185
- ] }),
8186
- onRetry && /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onRetry, children: retryLabel })
8187
- ] });
8188
- }
8189
- function NEmptyState({ title = "No data", description, icon, action, className }) {
8190
- const iconContent = icon ? React61__default.isValidElement(icon) ? icon : React61__default.createElement(icon, { className: "h-8 w-8" }) : null;
8191
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-center justify-center gap-3 py-12", className), children: [
8192
- iconContent && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground/50", children: iconContent }),
8193
- /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
8194
- /* @__PURE__ */ jsx("h3", { className: "font-semibold text-foreground", children: title }),
8195
- description && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm mt-1", children: description })
8196
- ] }),
8197
- action && /* @__PURE__ */ jsx("div", { className: "mt-2", children: action })
8198
- ] });
8199
- }
8200
8148
  var NErrorBoundary = class extends React61__default.Component {
8201
8149
  constructor(props) {
8202
8150
  super(props);
@@ -10375,6 +10323,224 @@ function FloatingSelectSegment({
10375
10323
  )) })
10376
10324
  ] });
10377
10325
  }
10326
+ var DEFAULT_COPY_LABEL = "Copy details";
10327
+ var DEFAULT_COPIED_LABEL = "Copied";
10328
+ var DEFAULT_COPY_ERROR_LABEL = "Copy failed";
10329
+ var DEFAULT_HEADER_ICON = "circle-check";
10330
+ var REVERT_MS = 2e3;
10331
+ function defaultCopyText(fields) {
10332
+ return fields.map((f) => `${f.label}: ${f.value}`).join("\n");
10333
+ }
10334
+ function resolveClipboard() {
10335
+ if (typeof navigator === "undefined") return null;
10336
+ const clipboard = navigator.clipboard;
10337
+ if (!clipboard || typeof clipboard.writeText !== "function") return null;
10338
+ return { writeText: clipboard.writeText.bind(clipboard) };
10339
+ }
10340
+ function NCredentialsCard({
10341
+ fields,
10342
+ title,
10343
+ description,
10344
+ icon,
10345
+ copyLabel = DEFAULT_COPY_LABEL,
10346
+ copiedLabel = DEFAULT_COPIED_LABEL,
10347
+ copyErrorLabel = DEFAULT_COPY_ERROR_LABEL,
10348
+ copyText,
10349
+ hideCopyAction = false,
10350
+ onCopy,
10351
+ onCopyError,
10352
+ actions,
10353
+ className,
10354
+ classNames
10355
+ }) {
10356
+ const [status, setStatus] = React61.useState("idle");
10357
+ const revertTimer = React61.useRef(null);
10358
+ const mountedRef = React61.useRef(true);
10359
+ const requestTokenRef = React61.useRef(0);
10360
+ React61.useEffect(() => {
10361
+ mountedRef.current = true;
10362
+ return () => {
10363
+ mountedRef.current = false;
10364
+ if (revertTimer.current) clearTimeout(revertTimer.current);
10365
+ revertTimer.current = null;
10366
+ };
10367
+ }, []);
10368
+ const scheduleRevert = React61.useCallback(() => {
10369
+ if (revertTimer.current) clearTimeout(revertTimer.current);
10370
+ revertTimer.current = setTimeout(() => {
10371
+ revertTimer.current = null;
10372
+ if (mountedRef.current) setStatus("idle");
10373
+ }, REVERT_MS);
10374
+ }, []);
10375
+ const handleCopy = React61.useCallback(() => {
10376
+ if (status === "pending") return;
10377
+ if (revertTimer.current) {
10378
+ clearTimeout(revertTimer.current);
10379
+ revertTimer.current = null;
10380
+ }
10381
+ const token = ++requestTokenRef.current;
10382
+ const isStale = () => !mountedRef.current || token !== requestTokenRef.current;
10383
+ let text;
10384
+ try {
10385
+ text = (copyText ?? defaultCopyText)(fields);
10386
+ } catch (error) {
10387
+ if (isStale()) return;
10388
+ setStatus("error");
10389
+ onCopyError?.(error);
10390
+ scheduleRevert();
10391
+ return;
10392
+ }
10393
+ const clipboard = resolveClipboard();
10394
+ if (!clipboard) {
10395
+ if (isStale()) return;
10396
+ setStatus("error");
10397
+ onCopyError?.(new Error("Clipboard is not available in this context."));
10398
+ scheduleRevert();
10399
+ return;
10400
+ }
10401
+ setStatus("pending");
10402
+ let promise;
10403
+ try {
10404
+ promise = clipboard.writeText(text);
10405
+ } catch (error) {
10406
+ if (isStale()) return;
10407
+ setStatus("error");
10408
+ onCopyError?.(error);
10409
+ scheduleRevert();
10410
+ return;
10411
+ }
10412
+ promise.then(
10413
+ () => {
10414
+ if (isStale()) return;
10415
+ setStatus("success");
10416
+ onCopy?.();
10417
+ scheduleRevert();
10418
+ },
10419
+ (error) => {
10420
+ if (isStale()) return;
10421
+ setStatus("error");
10422
+ onCopyError?.(error);
10423
+ scheduleRevert();
10424
+ }
10425
+ );
10426
+ }, [copyText, fields, onCopy, onCopyError, scheduleRevert, status]);
10427
+ const showHeader = Boolean(title || description);
10428
+ const showFields = fields.length > 0;
10429
+ const showActions = !hideCopyAction || Boolean(actions);
10430
+ const buttonLabel = status === "success" ? copiedLabel : status === "error" ? copyErrorLabel : copyLabel;
10431
+ const headerIcon = icon ?? DEFAULT_HEADER_ICON;
10432
+ return /* @__PURE__ */ jsxs(
10433
+ "div",
10434
+ {
10435
+ className: cn(
10436
+ "flex flex-col rounded-lg border bg-card p-5 shadow-sm",
10437
+ classNames?.root,
10438
+ className
10439
+ ),
10440
+ "data-testid": "credentials-card",
10441
+ children: [
10442
+ showHeader && /* @__PURE__ */ jsxs("div", { className: cn("flex items-start gap-3 mb-4", classNames?.header), children: [
10443
+ /* @__PURE__ */ jsx(
10444
+ "div",
10445
+ {
10446
+ className: "flex items-center justify-center w-10 h-10 rounded-full bg-muted shrink-0",
10447
+ "data-testid": "credentials-card-header-icon",
10448
+ children: /* @__PURE__ */ jsx(
10449
+ NIcon,
10450
+ {
10451
+ "aria-hidden": "true",
10452
+ icon: headerIcon,
10453
+ className: "w-5 h-5 text-muted-foreground"
10454
+ }
10455
+ )
10456
+ }
10457
+ ),
10458
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
10459
+ title && /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground", children: title }),
10460
+ description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: description })
10461
+ ] })
10462
+ ] }),
10463
+ showFields && /* @__PURE__ */ jsx("dl", { className: cn("space-y-3", classNames?.list), "data-testid": "credentials-card-list", children: fields.map((field, index) => {
10464
+ const useMono = field.mono ?? true;
10465
+ const breakAll = field.breakAll ?? true;
10466
+ return /* @__PURE__ */ jsxs(
10467
+ "div",
10468
+ {
10469
+ className: cn(
10470
+ "flex items-center gap-3 rounded-xl bg-background px-4 py-3",
10471
+ classNames?.field
10472
+ ),
10473
+ "data-testid": "credentials-card-field",
10474
+ children: [
10475
+ field.icon && /* @__PURE__ */ jsx(
10476
+ NIcon,
10477
+ {
10478
+ "aria-hidden": "true",
10479
+ icon: field.icon,
10480
+ className: "w-4 h-4 text-muted-foreground shrink-0"
10481
+ }
10482
+ ),
10483
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
10484
+ /* @__PURE__ */ jsx("dt", { className: "text-xs text-muted-foreground", children: field.label }),
10485
+ /* @__PURE__ */ jsx(
10486
+ "dd",
10487
+ {
10488
+ dir: "auto",
10489
+ className: cn(
10490
+ "text-sm text-foreground font-semibold",
10491
+ useMono && "font-mono",
10492
+ breakAll && "break-all"
10493
+ ),
10494
+ children: field.value
10495
+ }
10496
+ )
10497
+ ] })
10498
+ ]
10499
+ },
10500
+ `${field.label}-${index}`
10501
+ );
10502
+ }) }),
10503
+ showActions && /* @__PURE__ */ jsxs(
10504
+ "div",
10505
+ {
10506
+ className: cn(
10507
+ "mt-5 flex justify-end gap-3 flex-wrap",
10508
+ classNames?.actions
10509
+ ),
10510
+ "data-testid": "credentials-card-actions",
10511
+ children: [
10512
+ !hideCopyAction && /* @__PURE__ */ jsx(
10513
+ Button,
10514
+ {
10515
+ type: "button",
10516
+ variant: "outline",
10517
+ leftIcon: status === "success" ? Check : status === "error" ? X : Copy,
10518
+ onClick: handleCopy,
10519
+ loading: status === "pending",
10520
+ disabledWhileLoading: true,
10521
+ "data-testid": "credentials-card-copy",
10522
+ children: buttonLabel
10523
+ }
10524
+ ),
10525
+ actions
10526
+ ]
10527
+ }
10528
+ ),
10529
+ /* @__PURE__ */ jsx(
10530
+ "span",
10531
+ {
10532
+ "aria-live": "polite",
10533
+ role: "status",
10534
+ className: "sr-only",
10535
+ "data-testid": "credentials-card-status",
10536
+ children: status === "success" ? copiedLabel : status === "error" ? copyErrorLabel : ""
10537
+ }
10538
+ )
10539
+ ]
10540
+ }
10541
+ );
10542
+ }
10543
+ NCredentialsCard.displayName = "NCredentialsCard";
10378
10544
  function SearchField({ value, onChange, placeholder = "Search...", className }) {
10379
10545
  return /* @__PURE__ */ jsxs("div", { className: `relative ${className ?? ""}`, children: [
10380
10546
  /* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" }),
@@ -15138,37 +15304,6 @@ function NCommandPalette({
15138
15304
  ] })
15139
15305
  ] });
15140
15306
  }
15141
- function NPageLayout({
15142
- as: Comp = "main",
15143
- className,
15144
- style,
15145
- ...props
15146
- }) {
15147
- const { layout } = useNajmDesign();
15148
- const pageGutter = layout?.pageGutter ?? "var(--page-gutter, 24px)";
15149
- const sectionGap = layout?.sectionGap ?? "var(--section-gap, 20px)";
15150
- return /* @__PURE__ */ jsx(
15151
- Comp,
15152
- {
15153
- className: cn("flex min-w-0 flex-col", className),
15154
- style: {
15155
- /**
15156
- * Published so descendants can cancel the page padding exactly. A
15157
- * full-bleed child (a non-card NPageHeader) cannot guess these: the
15158
- * design config resolves them to literals, not to the `--page-gutter`
15159
- * / `--section-gap` fallbacks.
15160
- */
15161
- "--najm-page-gutter": pageGutter,
15162
- "--najm-section-gap": sectionGap,
15163
- gap: sectionGap,
15164
- paddingInline: pageGutter,
15165
- paddingBlock: sectionGap,
15166
- ...style
15167
- },
15168
- ...props
15169
- }
15170
- );
15171
- }
15172
15307
  function NInspectorSheet({ open, onClose, title, children }) {
15173
15308
  useEffect(() => {
15174
15309
  const handleKey = (e) => {
@@ -15255,4 +15390,4 @@ function NGridItem({
15255
15390
  return /* @__PURE__ */ jsx("div", { className: itemClassName, ...props, children });
15256
15391
  }
15257
15392
 
15258
- export { Alert, NCard as AsyncCard, Avatar, AvatarFallback, AvatarFormInput, AvatarGroup, AvatarImage, AvatarInput, AvatarStatus, Badge, BaseInput, 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, DEFAULT_THEME_FILE_NAME, 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, Indicator4 as Indicator, Input, Label2 as Label, LangInput, MultiSelectInput, NAJM_SAVED_THEME_VALUE, NAlert, NAppShell, NCard as NAsyncCard, NAvatar, NBadge, NBarChart, NBulkActionsBar, NCard, NCardAction, NCardFooter, NCardInfo, NCardMedia, NCardSection, NChartSkeleton, NCommandPalette, NConfirmDialog, NContextMenu, NDataCardShell, NDeleteDialog, NDeleteDialogContent, NDetailCard, NDetailItem, NDetailList, NDialog, NDialogDescription, NDialogHeader, NDialogPrimaryButton, NDialogSecondaryButton, NDonutCard, NEditorTabs, NEmptyState, NErrorBoundary, NErrorState, NFileBrowser, NFileTypeIcon, NFilterBar, NFolderIcon, NForm, NFormSectionHeader, NGrid, NGridItem, NImage, NIndicator, NInspectorSheet, NLineChart, NLoadingState, NMultiDialog, NNavbar, NPageHeader, NPageHeaderActions, NPageHeaderCompactActions, NPageHeaderFilters, NPageHeaderTop, NPageLayout, NPieChart, NPortalScopeProvider, NProgress, NRowActions, NSection, NSectionHeader, NSectionInfo, NSectionWithInfo, NSheet, NSidebar, NSidebarBrand, NSidebarContent, NSidebarFooter, NSidebarHeader, NSidebarItem, NSidebarMobile, NSidebarProvider, NSidebarSection, NSkeleton, NSkeletonCalendar, NSkeletonChart, NSkeletonDonut, NSkeletonEventList, NSkeletonWidget, NSkeletonWidgets, NSlider, NSmartPasteDialog, NSpinner, NStatCard, NStatCardSkeleton, NStatusBreakdown, Swap as NSwap, NTable, NTableCardRoot, NTableCards, NTableContent, NTableHeader, NTableLoadingSkeleton, NTablePagination, NTableRowSkeleton, NTableSkeleton, NTabs, NThemeCustomizer, NThemePresets, NUploader, NViewBody, NViewToggle, NativeSelect, NumberInput, OtpInput, PasswordInput, PhoneInput, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PrefixProvider, Progress, 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, Tabs, TabsContent, TabsList, TabsTrigger, TextAreaInput, TextInput, Textarea, TimeInput, TimeZoneInput, Toaster, Toggle, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, VariantProvider, WizardForm, alertVariants, avatarVariants, badgeColorVariants, badgeVariants, buildDefaultFileColumns, buildPageItems, createDialogStore, createTableStore, detectFormat, dialogVariants, filterResponsiveColumns, formatColor, formatFileBytes, formatFileRelative, getIconColorProps, getNChartColor, getNextEditorTabValue, hiddenBelowClasses, indicatorVariants, normalizeThemeFileName, parseColor, parseThemeFile, resolveHiddenBelowClass, resolveSlot, sliderVariants, stringifyThemeFile, swapVariants, toPickerHex, toggleVariants, tooltipContentVariants, truncateByCharacters, useClickOutside, useContextMenu, useDebouncedValue, useDelayedLoading, useDialog, useDialogStore, useDynamicPageSize, useFormField, useFormSubmission, useInfiniteScroll, useKeyboard, useLocalStorageState, useNForm, useNPortalScope, useNSidebar, usePrefix, useSelection, useStepNavigation, useStorageContextMenu, useStoreSync, useTable, useTableKeyboard, useVariant, useVariantPreset };
15393
+ export { Alert, NCard as AsyncCard, Avatar, AvatarFallback, AvatarFormInput, AvatarGroup, AvatarImage, AvatarInput, AvatarStatus, Badge, BaseInput, 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, DEFAULT_THEME_FILE_NAME, 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, Indicator4 as Indicator, Input, Label2 as Label, LangInput, MultiSelectInput, NAJM_SAVED_THEME_VALUE, NAlert, NAppShell, NCard as NAsyncCard, NAvatar, NBadge, NBarChart, NBulkActionsBar, NCard, NCardAction, NCardFooter, NCardInfo, NCardMedia, NCardSection, NChartSkeleton, NCommandPalette, NConfirmDialog, NContextMenu, NCredentialsCard, NDataCardShell, NDeleteDialog, NDeleteDialogContent, NDetailCard, NDetailItem, NDetailList, NDialog, NDialogDescription, NDialogHeader, NDialogPrimaryButton, NDialogSecondaryButton, NDonutCard, NEditorTabs, NErrorBoundary, NFileBrowser, NFileTypeIcon, NFilterBar, NFolderIcon, NForm, NFormSectionHeader, NGrid, NGridItem, NImage, NIndicator, NInspectorSheet, NLineChart, NMultiDialog, NNavbar, NPageHeader, NPageHeaderActions, NPageHeaderCompactActions, NPageHeaderFilters, NPageHeaderTop, NPieChart, NPortalScopeProvider, NProgress, NRowActions, NSection, NSectionHeader, NSectionInfo, NSectionWithInfo, NSheet, NSidebar, NSidebarBrand, NSidebarContent, NSidebarFooter, NSidebarHeader, NSidebarItem, NSidebarMobile, NSidebarProvider, NSidebarSection, NSkeleton, NSkeletonCalendar, NSkeletonChart, NSkeletonDonut, NSkeletonEventList, NSkeletonWidget, NSkeletonWidgets, NSlider, NSmartPasteDialog, NStatCard, NStatCardSkeleton, NStatusBreakdown, Swap as NSwap, NTable, NTableCardRoot, NTableCards, NTableContent, NTableHeader, NTableLoadingSkeleton, NTablePagination, NTableRowSkeleton, NTableSkeleton, NTabs, NThemeCustomizer, NThemePresets, NUploader, NViewBody, NViewToggle, NativeSelect, NumberInput, OtpInput, PasswordInput, PhoneInput, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PrefixProvider, Progress, 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, Tabs, TabsContent, TabsList, TabsTrigger, TextAreaInput, TextInput, Textarea, TimeInput, TimeZoneInput, Toaster, Toggle, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, VariantProvider, WizardForm, alertVariants, avatarVariants, badgeColorVariants, badgeVariants, buildDefaultFileColumns, buildPageItems, createDialogStore, createTableStore, detectFormat, dialogVariants, filterResponsiveColumns, focusRingClasses, focusRingWithinClasses, formatColor, formatFileBytes, formatFileRelative, getIconColorProps, getNChartColor, getNextEditorTabValue, hiddenBelowClasses, indicatorVariants, normalizeThemeFileName, parseColor, parseThemeFile, resolveHiddenBelowClass, resolveSlot, sliderVariants, stringifyThemeFile, swapVariants, toPickerHex, toggleVariants, tooltipContentVariants, truncateByCharacters, useClickOutside, useContextMenu, useDebouncedValue, useDelayedLoading, useDialog, useDialogStore, useDynamicPageSize, useFormField, useFormSubmission, useInfiniteScroll, useKeyboard, useLocalStorageState, useNForm, useNPortalScope, useNSidebar, usePrefix, useSelection, useStepNavigation, useStorageContextMenu, useStoreSync, useTable, useTableKeyboard, useVariant, useVariantPreset };
package/dist/json.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { Button } from './chunk-JUYT2ISO.mjs';
2
- export { NTableJson } from './chunk-JUYT2ISO.mjs';
1
+ export { NTableJson } from './chunk-K7T7X6PX.mjs';
2
+ import { Button } from './chunk-XZL32HFR.mjs';
3
3
  import { cn } from './chunk-KVZACF4G.mjs';
4
4
  import './chunk-TFHWLE7N.mjs';
5
5
  import { useMemo, useRef, useCallback } from 'react';
package/dist/theme.css CHANGED
@@ -307,10 +307,10 @@ input:autofill {
307
307
  overflow-x: auto;
308
308
  scrollbar-width: none;
309
309
  }
310
- .najm-overlay-scroll-x::-webkit-scrollbar {
311
- display: none;
312
- }
313
-
310
+ .najm-overlay-scroll-x::-webkit-scrollbar {
311
+ display: none;
312
+ }
313
+
314
314
  /* Responsive table actions stay discoverable on touch and tablet layouts.
315
315
  Fine-pointer desktops may keep the quieter hover/focus reveal treatment. */
316
316
  .ntable-card-action {
@@ -367,7 +367,7 @@ input:autofill {
367
367
  .nimage-input-compact-overlay:focus-visible {
368
368
  opacity: 1;
369
369
  }
370
- }
370
+ }
371
371
 
372
372
  /* OverlayScrollbars theme used by the <NajmScroll> component — a thin,
373
373
  translucent slate bar that floats over content with no reserved space.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "najm-kit",
3
- "version": "2.10.0",
3
+ "version": "2.11.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Reusable React UI component package for Najm framework",
@@ -84,6 +84,8 @@
84
84
  "test": "bun test && bun run test:rsc",
85
85
  "test:rsc": "cd test/rsc && bun test --conditions react-server",
86
86
  "test:next16": "bun run build && bun integration/next16-ui-bootstrap/run.ts",
87
+ "test:acceptance": "playwright test",
88
+ "typecheck:acceptance": "tsc --noEmit -p acceptance/tsconfig.json",
87
89
  "clean": "rimraf dist tsconfig.tsbuildinfo"
88
90
  },
89
91
  "peerDependencies": {