najm-kit 0.0.29 → 0.0.31

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.d.ts CHANGED
@@ -2139,6 +2139,7 @@ interface WizardClassNames {
2139
2139
  indicator?: string;
2140
2140
  progressBar?: string;
2141
2141
  }
2142
+ type WizardFooterDivider = boolean | "none" | "solid" | "dashed" | "dotted";
2142
2143
  interface WizardFormProps {
2143
2144
  steps: StepConfig[];
2144
2145
  schema: any;
@@ -2157,6 +2158,8 @@ interface WizardFormProps {
2157
2158
  className?: string;
2158
2159
  classNames?: WizardClassNames;
2159
2160
  footerSlot?: ReactNode;
2161
+ footerDivider?: WizardFooterDivider;
2162
+ footerDividerClassName?: string;
2160
2163
  children?: ReactNode;
2161
2164
  }
2162
2165
  interface StepMeta {
@@ -2165,7 +2168,7 @@ interface StepMeta {
2165
2168
  title: string;
2166
2169
  }
2167
2170
 
2168
- declare function WizardForm({ steps, schema, defaultValues, onSubmit, currentStep: controlledStep, onCurrentStepChange, onStepComplete, showHeader, showFooter, nextLabel, previousLabel, submitLabel, variant, bordered, className, classNames, footerSlot, }: WizardFormProps): react_jsx_runtime.JSX.Element;
2171
+ declare function WizardForm({ steps, schema, defaultValues, onSubmit, currentStep: controlledStep, onCurrentStepChange, onStepComplete, showHeader, showFooter, nextLabel, previousLabel, submitLabel, variant, bordered, className, classNames, footerSlot, footerDivider, footerDividerClassName, }: WizardFormProps): react_jsx_runtime.JSX.Element;
2169
2172
 
2170
2173
  interface StepIndicatorProps {
2171
2174
  stepNumber: number;
package/dist/index.mjs CHANGED
@@ -1090,7 +1090,7 @@ var buttonVariants = cva(
1090
1090
  variant: {
1091
1091
  default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
1092
1092
  destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
1093
- outline: "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:hover:bg-input/50",
1093
+ outline: "border border-input shadow-xs hover:bg-accent hover:text-accent-foreground",
1094
1094
  secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
1095
1095
  tertiary: "bg-tertiary text-tertiary-foreground shadow-xs hover:bg-tertiary/80",
1096
1096
  ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
@@ -1622,7 +1622,7 @@ function Input({ className, type, ...props }) {
1622
1622
  type,
1623
1623
  "data-slot": "input",
1624
1624
  className: cn(
1625
- "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",
1625
+ "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 text-foreground 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",
1626
1626
  "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
1627
1627
  "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
1628
1628
  className
@@ -1637,7 +1637,7 @@ function Textarea({ className, ...props }) {
1637
1637
  {
1638
1638
  "data-slot": "textarea",
1639
1639
  className: cn(
1640
- "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1640
+ "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base text-foreground shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1641
1641
  className
1642
1642
  ),
1643
1643
  ...props
@@ -2978,7 +2978,7 @@ function Checkbox({ className, ...props }) {
2978
2978
  {
2979
2979
  "data-slot": "checkbox",
2980
2980
  className: cn(
2981
- "peer border-foreground/40 dark:border-foreground/50 dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
2981
+ "peer cursor-pointer border-foreground/40 dark:border-foreground/50 dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
2982
2982
  className
2983
2983
  ),
2984
2984
  ...props,
@@ -3873,7 +3873,7 @@ function CommandItem({ className, ...props }) {
3873
3873
  Command$1.Item,
3874
3874
  {
3875
3875
  "data-slot": "command-item",
3876
- className: cn("data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
3876
+ className: cn("data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50 [&>svg.opacity-0:first-child]:hidden [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
3877
3877
  ...props
3878
3878
  }
3879
3879
  );
@@ -4130,7 +4130,7 @@ function FormMessage({ className, children, ...props }) {
4130
4130
  return /* @__PURE__ */ jsx("p", { "data-slot": "form-message", id: formMessageId, className: cn("text-destructive text-[0.8rem] font-medium", className), ...props, children: body });
4131
4131
  }
4132
4132
  function Table({ className, ...props }) {
4133
- 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 }) });
4133
+ 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 text-foreground", className), ...props }) });
4134
4134
  }
4135
4135
  function TableHeader({ className, ...props }) {
4136
4136
  return /* @__PURE__ */ jsx("thead", { "data-slot": "table-header", className: cn("[&_tr]:border-b [&_tr]:border-border/40", className), ...props });
@@ -4148,7 +4148,7 @@ function TableHead({ className, ...props }) {
4148
4148
  return /* @__PURE__ */ jsx("th", { "data-slot": "table-head", className: cn("text-foreground h-9 px-3 text-left align-middle text-xs font-medium uppercase tracking-wide whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className), ...props });
4149
4149
  }
4150
4150
  function TableCell({ className, ...props }) {
4151
- return /* @__PURE__ */ jsx("td", { "data-slot": "table-cell", className: cn("px-3 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className), ...props });
4151
+ return /* @__PURE__ */ jsx("td", { "data-slot": "table-cell", className: cn("px-3 align-middle whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className), ...props });
4152
4152
  }
4153
4153
  function TableCaption({ className, ...props }) {
4154
4154
  return /* @__PURE__ */ jsx("caption", { "data-slot": "table-caption", className: cn("text-muted-foreground mt-4 text-sm", className), ...props });
@@ -5081,7 +5081,7 @@ function NContextMenu({ x, y, items, onAction, onClose, className }) {
5081
5081
  onClose();
5082
5082
  },
5083
5083
  className: cn(
5084
- "flex w-full items-center justify-between gap-2 px-3 py-1.5 text-xs hover:bg-accent hover:text-accent-foreground disabled:opacity-40 disabled:cursor-not-allowed",
5084
+ "flex w-full cursor-pointer items-center justify-between gap-2 px-3 py-1.5 text-xs hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:opacity-40",
5085
5085
  item.danger && "text-destructive hover:text-destructive"
5086
5086
  ),
5087
5087
  children: [
@@ -5107,7 +5107,7 @@ function NContextMenu({ x, y, items, onAction, onClose, className }) {
5107
5107
  onClose();
5108
5108
  },
5109
5109
  className: cn(
5110
- "flex w-full items-center gap-2 px-3 py-1.5 text-xs hover:bg-accent hover:text-accent-foreground disabled:opacity-40",
5110
+ "flex w-full cursor-pointer items-center gap-2 px-3 py-1.5 text-xs hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:opacity-40",
5111
5111
  sub.danger && "text-destructive hover:text-destructive"
5112
5112
  ),
5113
5113
  children: [
@@ -5691,7 +5691,7 @@ var PRESETS2 = {
5691
5691
  destructive: "border-red-600"
5692
5692
  };
5693
5693
  var inputVariants = cva(
5694
- "relative w-full flex items-center h-10 bg-card overflow-hidden transition-colors",
5694
+ "relative w-full flex items-center h-10 bg-card text-foreground overflow-hidden transition-colors",
5695
5695
  {
5696
5696
  variants: {
5697
5697
  variant: {
@@ -5766,7 +5766,7 @@ var TextInput = ({ value, onChange, placeholder = "", icon, showIcon = true, ico
5766
5766
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5767
5767
  return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), disabled, children: [
5768
5768
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5769
- /* @__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 })
5769
+ /* @__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-foreground placeholder:text-muted-foreground", disabled, ...props })
5770
5770
  ] });
5771
5771
  };
5772
5772
  var NumberInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderColor }) => {
@@ -5774,7 +5774,7 @@ var NumberInput = ({ value, onChange, placeholder = "", icon, showIcon = true, i
5774
5774
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5775
5775
  return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), children: [
5776
5776
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5777
- /* @__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" })
5777
+ /* @__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-foreground placeholder:text-muted-foreground" })
5778
5778
  ] });
5779
5779
  };
5780
5780
  var PasswordInput = ({ value, onChange, placeholder = "", icon, showIcon = true, iconColor, className = "", variant = "default", status = "default", bordered, borderColor }) => {
@@ -5783,20 +5783,39 @@ var PasswordInput = ({ value, onChange, placeholder = "", icon, showIcon = true,
5783
5783
  const iconProps = getIconColorProps(iconColor, "h-4 w-4");
5784
5784
  return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("gap-2", className), children: [
5785
5785
  shouldDisplayIcon && /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }),
5786
- /* @__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" }),
5786
+ /* @__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-foreground placeholder:text-muted-foreground" }),
5787
5787
  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) })
5788
5788
  ] });
5789
5789
  };
5790
- var TextAreaInput = ({ value, onChange, placeholder = "", className = "", variant = "default", status = "default", bordered, borderColor, rows }) => /* @__PURE__ */ jsx(BaseInput, { variant, status, bordered, borderColor, className: cn("items-start", className), children: /* @__PURE__ */ jsx(
5791
- Textarea,
5792
- {
5793
- rows,
5794
- placeholder,
5795
- value,
5796
- onChange: (ev) => onChange(ev.target.value),
5797
- className: "h-full border-0 bg-transparent p-0 text-muted-foreground shadow-none focus-visible:border-transparent focus-visible:ring-0 focus-visible:ring-transparent focus-visible:ring-offset-0 dark:bg-transparent"
5798
- }
5799
- ) });
5790
+ var DEFAULT_ROWS = 3;
5791
+ var MIN_ROWS = 2;
5792
+ var REM_PER_ROW = 1.5;
5793
+ var VERTICAL_PADDING_REM = 1;
5794
+ var TextAreaInput = ({ value, onChange, placeholder = "", className = "", variant = "default", status = "default", bordered, borderColor, rows }) => {
5795
+ const visibleRows = Math.max(rows ?? DEFAULT_ROWS, MIN_ROWS);
5796
+ const minHeight = `${visibleRows * REM_PER_ROW + VERTICAL_PADDING_REM}rem`;
5797
+ return /* @__PURE__ */ jsx(
5798
+ BaseInput,
5799
+ {
5800
+ variant,
5801
+ status,
5802
+ bordered,
5803
+ borderColor,
5804
+ className: cn("h-auto items-start", className),
5805
+ style: { minHeight },
5806
+ children: /* @__PURE__ */ jsx(
5807
+ Textarea,
5808
+ {
5809
+ rows: visibleRows,
5810
+ placeholder,
5811
+ value,
5812
+ onChange: (ev) => onChange(ev.target.value),
5813
+ className: "h-full min-h-0 resize-y border-0 bg-transparent p-0 text-foreground placeholder:text-muted-foreground shadow-none focus-visible:border-transparent focus-visible:ring-0 focus-visible:ring-transparent focus-visible:ring-offset-0 dark:bg-transparent"
5814
+ }
5815
+ )
5816
+ }
5817
+ );
5818
+ };
5800
5819
  function renderItems(items) {
5801
5820
  return items.map((item) => {
5802
5821
  const value = typeof item === "string" ? item : item.value;
@@ -6012,7 +6031,7 @@ var DateInput = ({ value, onChange, placeholder = "Pick a date", className = "",
6012
6031
  const toDateString = (date) => date?.toISOString().split("T")[0];
6013
6032
  return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className, children: [
6014
6033
  /* @__PURE__ */ jsxs(Popover, { children: [
6015
- /* @__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 }) }) }),
6034
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx("div", { className: "w-full flex items-center cursor-pointer gap-2 justify-start text-left font-normal", children: /* @__PURE__ */ jsx(Label, { className: cn("cursor-pointer", value ? "text-foreground" : "text-muted-foreground"), children: value ? format(typeof value === "string" ? new Date(value) : value, "PPP") : placeholder }) }) }),
6016
6035
  /* @__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" }) })
6017
6036
  ] }),
6018
6037
  !icon && showIcon && /* @__PURE__ */ jsx(Calendar$1, { className: iconProps.className, style: iconProps.style })
@@ -6033,13 +6052,13 @@ var FileInput = ({ value, onChange, placeholder = "No file chosen", icon, showIc
6033
6052
  const filename = typeof value === "string" ? value.split(/[\\/]/).pop() || "" : value.name;
6034
6053
  return truncateFilename(filename);
6035
6054
  };
6036
- return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("flex px-0 p-0 text-muted-foreground", className), onClick: () => fileInputRef.current?.click(), children: [
6055
+ return /* @__PURE__ */ jsxs(BaseInput, { variant, status, bordered, borderColor, className: cn("flex px-0 p-0", className), onClick: () => fileInputRef.current?.click(), children: [
6037
6056
  /* @__PURE__ */ jsx("input", { type: "file", ref: fileInputRef, onChange: (e) => onChange(e.target.files?.[0] || null), className: "hidden" }),
6038
6057
  /* @__PURE__ */ jsxs("div", { className: "bg-muted flex h-full items-center px-3", children: [
6039
6058
  showIcon && (icon ? /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }) : /* @__PURE__ */ jsx(FileUp, { className: cn(iconProps.className) })),
6040
6059
  /* @__PURE__ */ jsx(Label, { className: "flex cursor-pointer h-full justify-center items-center px-2 text-muted-foreground", children: "Choose File" })
6041
6060
  ] }),
6042
- /* @__PURE__ */ jsx(Label, { className: "ml-2 flex-1", children: displayFilename() || /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: placeholder }) })
6061
+ /* @__PURE__ */ jsx(Label, { className: "ml-2 flex-1 text-foreground", children: displayFilename() || /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: placeholder }) })
6043
6062
  ] });
6044
6063
  };
6045
6064
  function formatBytes2(bytes) {
@@ -6858,7 +6877,7 @@ var TimeInput = ({ value = "", onChange, placeholder = "", icon, showIcon = true
6858
6877
  showIcon && (icon ? /* @__PURE__ */ jsx("span", { className: iconProps.className, style: iconProps.style, children: resolveIcon(icon) }) : /* @__PURE__ */ jsx(Clock, { className: iconProps.className, style: iconProps.style })),
6859
6878
  /* @__PURE__ */ jsx(Input, { type: "text", placeholder: placeholder || (showSeconds ? "HH:MM:SS" : "HH:MM"), value: inputValue, onChange: (e) => handleInputChange(e.target.value), onKeyDown: (e) => {
6860
6879
  if (!/\d/.test(e.key) && !["Backspace", "Delete", "ArrowLeft", "ArrowRight", "Tab"].includes(e.key)) e.preventDefault();
6861
- }, 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") })
6880
+ }, onBlur: handleBlur, disabled, className: cn("p-0 border-0 shadow-none bg-transparent dark:bg-transparent focus-visible:ring-0 placeholder:text-muted-foreground", !isValid ? "text-red-500" : "text-foreground") })
6862
6881
  ] });
6863
6882
  };
6864
6883
  var RANGE_COLOR = {
@@ -7744,6 +7763,12 @@ function issuePath(issue) {
7744
7763
  function matchesFieldPath(path, field) {
7745
7764
  return path === field || path.startsWith(`${field}.`) || field.startsWith(`${path}.`);
7746
7765
  }
7766
+ function footerDividerClass(divider = "none") {
7767
+ if (divider === false || divider === "none") return "border-t-0";
7768
+ if (divider === "dashed") return "border-t border-dashed border-border";
7769
+ if (divider === "dotted") return "border-t border-dotted border-border";
7770
+ return "border-t border-solid border-border";
7771
+ }
7747
7772
  function WizardForm({
7748
7773
  steps,
7749
7774
  schema,
@@ -7761,7 +7786,9 @@ function WizardForm({
7761
7786
  bordered,
7762
7787
  className,
7763
7788
  classNames,
7764
- footerSlot
7789
+ footerSlot,
7790
+ footerDivider = "none",
7791
+ footerDividerClassName
7765
7792
  }) {
7766
7793
  const nav = useStepNavigation({
7767
7794
  steps,
@@ -7876,13 +7903,25 @@ function WizardForm({
7876
7903
  ]
7877
7904
  }
7878
7905
  ) }) }),
7879
- showFooter && /* @__PURE__ */ jsxs("div", { className: cn("sticky bottom-0 z-10 mt-auto flex shrink-0 items-center justify-between border-t border-border bg-background/95 pt-3 backdrop-blur", classNames?.footer), children: [
7880
- /* @__PURE__ */ jsx("div", { children: !nav.isFirstStep && /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: nav.handlePrevious, children: previousLabel }) }),
7881
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
7882
- footerSlot,
7883
- nav.isLastStep ? /* @__PURE__ */ jsx(Button, { type: "submit", form: `step-${currentStepConfig.id}`, children: submitLabel }) : /* @__PURE__ */ jsx(Button, { type: "submit", form: `step-${currentStepConfig.id}`, children: nextLabel })
7884
- ] })
7885
- ] })
7906
+ showFooter && /* @__PURE__ */ jsxs(
7907
+ "div",
7908
+ {
7909
+ "data-najm-wizard-footer": "true",
7910
+ className: cn(
7911
+ "sticky bottom-0 z-10 mt-auto flex shrink-0 items-center justify-between bg-background/95 pt-3 backdrop-blur",
7912
+ footerDividerClass(footerDivider),
7913
+ footerDividerClassName,
7914
+ classNames?.footer
7915
+ ),
7916
+ children: [
7917
+ /* @__PURE__ */ jsx("div", { children: !nav.isFirstStep && /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: nav.handlePrevious, children: previousLabel }) }),
7918
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
7919
+ footerSlot,
7920
+ nav.isLastStep ? /* @__PURE__ */ jsx(Button, { type: "submit", form: `step-${currentStepConfig.id}`, children: submitLabel }) : /* @__PURE__ */ jsx(Button, { type: "submit", form: `step-${currentStepConfig.id}`, children: nextLabel })
7921
+ ] })
7922
+ ]
7923
+ }
7924
+ )
7886
7925
  ]
7887
7926
  }
7888
7927
  );
@@ -8745,7 +8784,7 @@ function NDataCardShell({ row, onClick, onContextMenu, actions, children, classN
8745
8784
  onContextMenu,
8746
8785
  style: recipeStyle,
8747
8786
  className: cn(
8748
- "relative group w-full rounded-lg bg-card",
8787
+ "relative group w-full rounded-lg bg-card overflow-hidden",
8749
8788
  surfaceBorderClasses(bordered),
8750
8789
  isActive && (bordered ? "border-primary" : "ring-2 ring-primary ring-offset-1 ring-offset-background"),
8751
8790
  onClick && "cursor-pointer",
@@ -8947,7 +8986,7 @@ function NTableCards({ effectiveMode }) {
8947
8986
  e.stopPropagation();
8948
8987
  openRowMenu(e, row.original);
8949
8988
  },
8950
- 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",
8989
+ className: "absolute top-2 right-2 z-10 flex h-7 w-7 cursor-pointer 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",
8951
8990
  children: /* @__PURE__ */ jsx(MoreVertical, { className: "h-4 w-4" })
8952
8991
  }
8953
8992
  ),
@@ -9043,36 +9082,36 @@ function NTablePagination() {
9043
9082
  const newSize = Number(value);
9044
9083
  setPagination({ pageIndex: 0, pageSize: newSize });
9045
9084
  };
9046
- return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-4", classNames?.pagination), children: [
9047
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 lg:gap-6", children: [
9048
- (!isPaginationControlled || manualPagination) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
9049
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Rows/page" }),
9085
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex w-full min-w-0 flex-wrap items-center justify-between gap-x-4 gap-y-2 py-1 text-foreground", classNames?.pagination), children: [
9086
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-4 lg:gap-6", children: [
9087
+ (!isPaginationControlled || manualPagination) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-foreground", children: [
9088
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: "Rows/page" }),
9050
9089
  /* @__PURE__ */ jsxs(Select, { value: `${pageSize}`, onValueChange: handlePageSizeChange, children: [
9051
9090
  /* @__PURE__ */ jsx(
9052
9091
  SelectTrigger,
9053
9092
  {
9054
9093
  "data-bordered": bordered ? "true" : void 0,
9055
- className: cn("h-8 w-[80px]", bordered && "najm-border border-border"),
9094
+ className: cn("h-8 w-[80px] text-foreground", bordered && "najm-border border-border"),
9056
9095
  children: /* @__PURE__ */ jsx(SelectValue, { placeholder: pageSize })
9057
9096
  }
9058
9097
  ),
9059
9098
  /* @__PURE__ */ jsx(SelectContent, { side: "top", children: currentPageSizeOptions.map((size) => /* @__PURE__ */ jsx(SelectItem, { value: `${size}`, children: size }, size)) })
9060
9099
  ] })
9061
9100
  ] }),
9062
- /* @__PURE__ */ jsxs("div", { className: "text-sm font-medium", children: [
9101
+ /* @__PURE__ */ jsxs("div", { className: "text-sm font-medium text-foreground", children: [
9063
9102
  "Page ",
9064
9103
  pageIndex + 1,
9065
9104
  " of ",
9066
9105
  effectivePageCount
9067
9106
  ] }),
9068
9107
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
9069
- /* @__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" }) }),
9070
- /* @__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" }) }),
9071
- /* @__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" }) }),
9072
- /* @__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" }) })
9108
+ /* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: "hidden h-8 w-8 p-0 text-foreground disabled:text-muted-foreground disabled:opacity-70 lg:flex", "aria-label": "First page", onClick: () => navigate("first"), disabled: !table.getCanPreviousPage?.() || pageIndex === 0, children: /* @__PURE__ */ jsx(ChevronsLeft, { className: "h-4 w-4" }) }),
9109
+ /* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: "h-8 w-8 p-0 text-foreground disabled:text-muted-foreground disabled:opacity-70", "aria-label": "Previous", onClick: () => navigate("prev"), disabled: !table.getCanPreviousPage?.() || pageIndex === 0, children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" }) }),
9110
+ /* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: "h-8 w-8 p-0 text-foreground disabled:text-muted-foreground disabled:opacity-70", "aria-label": "Next", onClick: () => navigate("next"), disabled: !table.getCanNextPage?.() || pageIndex >= effectivePageCount - 1, children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }) }),
9111
+ /* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: "hidden h-8 w-8 p-0 text-foreground disabled:text-muted-foreground disabled:opacity-70 lg:flex", "aria-label": "Last page", onClick: () => navigate("last"), disabled: !table.getCanNextPage?.() || pageIndex >= effectivePageCount - 1, children: /* @__PURE__ */ jsx(ChevronsRight, { className: "h-4 w-4" }) })
9073
9112
  ] })
9074
9113
  ] }),
9075
- /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
9114
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-none whitespace-nowrap text-sm text-muted-foreground max-sm:hidden", children: [
9076
9115
  selectedRows.length,
9077
9116
  " of ",
9078
9117
  manualPagination && rowCount !== void 0 ? rowCount : filteredRows.length,
@@ -9338,7 +9377,7 @@ function NTableJson() {
9338
9377
  if (viewMode !== "json") return null;
9339
9378
  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) }) }) });
9340
9379
  }
9341
- var DEFAULT_ROWS = 6;
9380
+ var DEFAULT_ROWS2 = 6;
9342
9381
  function NTableHeaderSkeleton() {
9343
9382
  const filters = useTableStore.use.filters();
9344
9383
  const showViewToggle = useTableStore.use.showViewToggle();
@@ -9363,7 +9402,7 @@ function NTableHeaderSkeleton() {
9363
9402
  ] })
9364
9403
  ] });
9365
9404
  }
9366
- function NTableLoadingSkeleton({ rows = DEFAULT_ROWS }) {
9405
+ function NTableLoadingSkeleton({ rows = DEFAULT_ROWS2 }) {
9367
9406
  const columns = useTableStore.use.columns();
9368
9407
  const showCheckbox = useTableStore.use.showCheckbox();
9369
9408
  const headerClassName = useTableStore.use.headerClassName();
@@ -9418,7 +9457,7 @@ function NTableLoadingSkeleton({ rows = DEFAULT_ROWS }) {
9418
9457
  )
9419
9458
  ] });
9420
9459
  }
9421
- function NTableCardsLoadingSkeleton({ rows = 8 }) {
9460
+ function NTableCardsLoadingSkeleton({ rows }) {
9422
9461
  const filters = useTableStore.use.filters();
9423
9462
  const showViewToggle = useTableStore.use.showViewToggle();
9424
9463
  const showColumnVisibility = useTableStore.use.showColumnVisibility();
@@ -9430,18 +9469,21 @@ function NTableCardsLoadingSkeleton({ rows = 8 }) {
9430
9469
  );
9431
9470
  const classNames = useTableStore.use.classNames();
9432
9471
  const bordered = useTableStore.use.bordered();
9472
+ const calculatedPageSize = useTableStore.use.calculatedPageSize();
9473
+ const pagination = useTableStore.use.pagination();
9474
+ const cardCount = rows ?? Math.max(1, calculatedPageSize || pagination?.pageSize || 10);
9433
9475
  return /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col gap-2", children: [
9434
9476
  hasHeaderSkeleton && /* @__PURE__ */ jsx(NTableHeaderSkeleton, {}),
9435
- /* @__PURE__ */ jsx(
9477
+ /* @__PURE__ */ jsx(NajmScroll, { axis: "y", className: "min-h-0 flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
9436
9478
  "div",
9437
9479
  {
9438
9480
  "data-testid": "ntable-cards-loading-skeleton",
9439
9481
  "aria-busy": "true",
9440
9482
  className: cn("grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4", classNames?.cards),
9441
- children: Array.from({ length: rows }).map((_, index) => /* @__PURE__ */ jsx(
9483
+ children: Array.from({ length: cardCount }).map((_, index) => /* @__PURE__ */ jsx(
9442
9484
  Card,
9443
9485
  {
9444
- className: cn("rounded-lg bg-card p-4 shadow-none", bordered ? "border" : "border border-border"),
9486
+ className: cn("rounded-lg bg-card p-4 shadow-none", surfaceBorderClasses(bordered)),
9445
9487
  children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4", children: [
9446
9488
  /* @__PURE__ */ jsx(NSkeleton, { className: "h-12 w-12 shrink-0 rounded-full" }),
9447
9489
  /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-3", children: [
@@ -9460,7 +9502,7 @@ function NTableCardsLoadingSkeleton({ rows = 8 }) {
9460
9502
  index
9461
9503
  ))
9462
9504
  }
9463
- )
9505
+ ) })
9464
9506
  ] });
9465
9507
  }
9466
9508
  function TableStateSlot({ children }) {
@@ -9546,7 +9588,7 @@ function TableLayout(props) {
9546
9588
  /* @__PURE__ */ jsx(NTableCards, { effectiveMode }),
9547
9589
  /* @__PURE__ */ jsx(NTableJson, {})
9548
9590
  ] }) }),
9549
- /* @__PURE__ */ jsx("div", { "data-ntable-pagination": true, className: "shrink-0", children: /* @__PURE__ */ jsx(NTablePagination, {}) })
9591
+ /* @__PURE__ */ jsx("div", { "data-ntable-pagination": true, className: "min-w-0 shrink-0 bg-background text-foreground", children: /* @__PURE__ */ jsx(NTablePagination, {}) })
9550
9592
  ] });
9551
9593
  }
9552
9594
  function NTable(props) {
@@ -9629,8 +9671,7 @@ function NTable(props) {
9629
9671
  [onRowContextMenu]
9630
9672
  );
9631
9673
  const autoOpenRowMenu = effectiveRowMenu ? handleOpenRowMenu : onRowContextMenu ? handleManualRowMenu : null;
9632
- const shouldCollapseActions = props.columns.length > 5;
9633
- const effectiveMenuButton = Boolean(autoOpenRowMenu) && (menuButtonProp ?? shouldCollapseActions);
9674
+ const effectiveMenuButton = Boolean(autoOpenRowMenu) && (menuButtonProp ?? true);
9634
9675
  const store = useStoreSync({
9635
9676
  data: props.data ?? [],
9636
9677
  columns: props.columns ?? [],
package/dist/json.mjs CHANGED
@@ -368,7 +368,7 @@ var buttonVariants = cva(
368
368
  variant: {
369
369
  default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
370
370
  destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
371
- outline: "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:hover:bg-input/50",
371
+ outline: "border border-input shadow-xs hover:bg-accent hover:text-accent-foreground",
372
372
  secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
373
373
  tertiary: "bg-tertiary text-tertiary-foreground shadow-xs hover:bg-tertiary/80",
374
374
  ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
package/dist/theme.css CHANGED
@@ -289,17 +289,19 @@
289
289
  /* OverlayScrollbars theme used by the <NajmScroll> component — a thin,
290
290
  translucent slate bar that floats over content with no reserved space. */
291
291
  .os-theme-najm {
292
- --os-size: 10px;
292
+ --os-size: 8px;
293
293
  --os-padding-perpendicular: 2px;
294
294
  --os-padding-axis: 2px;
295
+ --os-track-bg: transparent;
295
296
  --os-track-border-radius: 9999px;
296
297
  --os-handle-border-radius: 9999px;
297
- --os-handle-bg: rgba(148, 163, 184, 0.3);
298
- --os-handle-bg-hover: rgba(148, 163, 184, 0.45);
299
- --os-handle-bg-active: rgba(148, 163, 184, 0.6);
298
+ --os-handle-bg: rgba(203, 213, 225, 0.08);
299
+ --os-handle-bg-hover: rgba(100, 116, 139, 0.32);
300
+ --os-handle-bg-active: rgba(71, 85, 105, 0.42);
300
301
  --os-handle-min-size: 33px;
301
- --os-handle-perpendicular-size: 60%;
302
- --os-handle-perpendicular-size-hover: 90%;
302
+ --os-handle-perpendicular-size: 3px;
303
+ --os-handle-perpendicular-size-hover: 5px;
304
+ --os-handle-perpendicular-size-active: 5px;
303
305
  }
304
306
 
305
307
  /* Darker, more subtle handle in dark mode */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "najm-kit",
3
- "version": "0.0.29",
3
+ "version": "0.0.31",
4
4
  "type": "module",
5
5
  "description": "Reusable React UI component package for Najm framework",
6
6
  "main": "./dist/index.mjs",