najm-kit 0.0.7 → 0.0.9

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/json.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import * as React3 from 'react';
2
- import React3__default, { createContext, useContext, useMemo, useRef, useCallback } from 'react';
1
+ import * as React2 from 'react';
2
+ import React2__default, { createContext, useContext, useMemo, useRef, useCallback } from 'react';
3
3
  import CodeMirror from '@uiw/react-codemirror';
4
4
  import { json } from '@codemirror/lang-json';
5
5
  import { keymap, EditorView, Decoration, ViewPlugin } from '@codemirror/view';
@@ -13,6 +13,7 @@ import { Slot } from '@radix-ui/react-slot';
13
13
  import * as LucideIcons from 'lucide-react';
14
14
  import { LoaderCircleIcon, Loader2, AlertCircle, ClipboardPaste, Copy, RotateCcw } from 'lucide-react';
15
15
  import { cva } from 'class-variance-authority';
16
+ import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
16
17
 
17
18
  // src/json/JsonViewer.tsx
18
19
  function cn(...inputs) {
@@ -172,6 +173,44 @@ function JsonViewer({ value, colors = defaultJsonViewColors, className, maxHeigh
172
173
  }
173
174
  );
174
175
  }
176
+ React2.createContext(0);
177
+ React2.createContext(null);
178
+ var DEFAULT_APPEARANCE = {
179
+ borderDegree: "default"
180
+ };
181
+ var NajmAppearanceContext = React2.createContext(DEFAULT_APPEARANCE);
182
+ function useNajmAppearance() {
183
+ return React2.useContext(NajmAppearanceContext);
184
+ }
185
+
186
+ // src/theme/borders.ts
187
+ function resolveBorderDegree(borderDegree, bordered, globalBorderDegree, fallback = "default") {
188
+ if (borderDegree) return borderDegree;
189
+ if (bordered === true) return "strong";
190
+ if (bordered === false) return fallback;
191
+ return globalBorderDegree ?? fallback;
192
+ }
193
+ function borderColorClassForDegree(degree) {
194
+ switch (degree) {
195
+ case "none":
196
+ return "border-transparent";
197
+ case "subtle":
198
+ return "border-border-subtle";
199
+ case "strong":
200
+ return "border-border-strong";
201
+ default:
202
+ return "border-border";
203
+ }
204
+ }
205
+ function useResolvedBorderDegree(options = {}) {
206
+ const appearance = useNajmAppearance();
207
+ return resolveBorderDegree(
208
+ options.borderDegree,
209
+ options.bordered,
210
+ appearance.borderDegree,
211
+ options.fallback
212
+ );
213
+ }
175
214
  function toPascalCase(value) {
176
215
  return value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[\s_-]+/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
177
216
  }
@@ -195,9 +234,9 @@ var NIcon = ({
195
234
  height: size,
196
235
  ...style
197
236
  };
198
- if (React3__default.isValidElement(icon)) {
199
- return React3__default.cloneElement(icon, {
200
- className: cn(icon.props.className, className),
237
+ if (React2__default.isValidElement(icon)) {
238
+ return React2__default.cloneElement(icon, {
239
+ className: cn(className, icon.props.className),
201
240
  onClick,
202
241
  ...rest
203
242
  });
@@ -314,7 +353,7 @@ function renderIcon(icon) {
314
353
  if (!icon) return null;
315
354
  return /* @__PURE__ */ jsx(NIcon, { "aria-hidden": "true", icon, className: "shrink-0" });
316
355
  }
317
- var Button = React3.forwardRef(
356
+ var Button = React2.forwardRef(
318
357
  ({
319
358
  className,
320
359
  variant,
@@ -330,16 +369,23 @@ var Button = React3.forwardRef(
330
369
  loaderPosition = "left",
331
370
  leftIcon,
332
371
  rightIcon,
372
+ bordered,
373
+ borderDegree,
333
374
  disabled,
334
375
  children,
335
376
  onClick,
336
377
  ...props
337
378
  }, ref) => {
338
- const [pending, setPending] = React3.useState(false);
379
+ const [pending, setPending] = React2.useState(false);
339
380
  const isLoading = loading || pending;
340
381
  const isDisabled = disabled || disabledWhileLoading && isLoading;
341
382
  const Comp = asChild ? Slot : "button";
342
- const handleClick = React3.useCallback(
383
+ const resolvedBorderDegree = useResolvedBorderDegree({
384
+ borderDegree,
385
+ bordered,
386
+ fallback: "default"
387
+ });
388
+ const handleClick = React2.useCallback(
343
389
  (event) => {
344
390
  if (isDisabled) {
345
391
  event.preventDefault();
@@ -368,10 +414,24 @@ var Button = React3.forwardRef(
368
414
  "data-slot": "button",
369
415
  "data-loading": isLoading || void 0,
370
416
  "data-disabled": isDisabled || void 0,
417
+ "data-border-degree": variant === "outline" || bordered || borderDegree ? resolvedBorderDegree : void 0,
371
418
  "aria-busy": isLoading || void 0,
372
419
  "aria-disabled": asChild && isDisabled ? true : void 0,
373
420
  disabled: !asChild ? isDisabled : void 0,
374
- className: cn(buttonVariants({ variant, size, rounded, fullWidth, className })),
421
+ className: cn(
422
+ buttonVariants({ variant, size, rounded, fullWidth }),
423
+ // Outline buttons always have a border; let the resolved degree drive its color.
424
+ variant === "outline" && borderColorClassForDegree(resolvedBorderDegree),
425
+ // Filled/ghost/plain/link/success/warning/info/soft/subtle buttons only get a
426
+ // border when the consumer explicitly opts in via `bordered` or `borderDegree`.
427
+ // We do NOT honor the global strong mode for these, because it would make every
428
+ // filled button look outlined.
429
+ variant !== "outline" && (bordered || borderDegree) && cn(
430
+ "border",
431
+ borderDegree ? borderColorClassForDegree(resolvedBorderDegree) : "border-muted-foreground"
432
+ ),
433
+ className
434
+ ),
375
435
  onClick: handleClick,
376
436
  ...props,
377
437
  children: showCenteredLoader ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -734,7 +794,7 @@ function JsonEditor({
734
794
  statusAddon && /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: statusAddon })
735
795
  ] }),
736
796
  headerMiddle && /* @__PURE__ */ jsx("div", { className: "hidden shrink-0 items-center gap-1.5 md:flex", children: headerMiddle }),
737
- showActions && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1.5 overflow-x-auto", children: [
797
+ showActions && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1.5 najm-overlay-scroll-x", children: [
738
798
  onSmartPaste && /* @__PURE__ */ jsxs(Button, { variant: "secondary", disabled: saving || loading, onClick: onSmartPaste, title: "Paste & merge JSON from clipboard", className: "gap-1.5 whitespace-nowrap px-2 sm:px-3", children: [
739
799
  /* @__PURE__ */ jsx(ClipboardPaste, { className: "h-3.5 w-3.5 mr-1" }),
740
800
  /* @__PURE__ */ jsx("span", { children: smartPasteLabel ?? "Paste" })
@@ -820,6 +880,66 @@ var handler = {
820
880
  }
821
881
  };
822
882
  useTableStore.use = new Proxy({}, handler);
883
+ function assignRef(ref, node) {
884
+ if (!ref) return;
885
+ if (typeof ref === "function") ref(node);
886
+ else ref.current = node;
887
+ }
888
+ function applyViewportLayout(node, axis) {
889
+ node.style.width = "100%";
890
+ node.style.height = "100%";
891
+ node.style.minWidth = "0";
892
+ node.style.minHeight = "0";
893
+ node.style.overflowX = axis === "x" || axis === "both" ? "auto" : "hidden";
894
+ node.style.overflowY = axis === "y" || axis === "both" ? "auto" : "hidden";
895
+ }
896
+ function NajmScroll({ className, axis = "y", autoHide = "never", viewportRef, events, options, element, children, style, ...props }) {
897
+ return /* @__PURE__ */ jsx(
898
+ OverlayScrollbarsComponent,
899
+ {
900
+ className: cn(className),
901
+ style: {
902
+ ...style,
903
+ display: "flex",
904
+ alignItems: "stretch",
905
+ flexDirection: "row",
906
+ flexWrap: "nowrap",
907
+ overflow: "hidden",
908
+ minHeight: 0,
909
+ minWidth: 0
910
+ },
911
+ element,
912
+ defer: true,
913
+ options: {
914
+ scrollbars: { theme: "os-theme-najm", autoHide, autoHideDelay: 500, clickScroll: true },
915
+ overflow: {
916
+ x: axis === "x" || axis === "both" ? "scroll" : "hidden",
917
+ y: axis === "y" || axis === "both" ? "scroll" : "hidden"
918
+ },
919
+ ...options
920
+ },
921
+ events: {
922
+ ...events,
923
+ initialized: (instance, ...rest) => {
924
+ const viewport = instance.elements().viewport;
925
+ applyViewportLayout(viewport, axis);
926
+ assignRef(viewportRef, viewport);
927
+ events?.initialized?.(instance, ...rest);
928
+ },
929
+ updated: (instance, ...rest) => {
930
+ applyViewportLayout(instance.elements().viewport, axis);
931
+ events?.updated?.(instance, ...rest);
932
+ },
933
+ destroyed: (instance, ...rest) => {
934
+ assignRef(viewportRef, null);
935
+ events?.destroyed?.(instance, ...rest);
936
+ }
937
+ },
938
+ ...props,
939
+ children
940
+ }
941
+ );
942
+ }
823
943
  function formatJsonValue(value) {
824
944
  if (typeof value === "string") return value;
825
945
  try {
@@ -833,7 +953,7 @@ function NTableJson() {
833
953
  const renderJson = useTableStore.use.renderJson();
834
954
  const jsonValue = useTableStore.use.jsonValue();
835
955
  if (viewMode !== "json") return null;
836
- 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) }) });
956
+ 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) }) }) });
837
957
  }
838
958
 
839
959
  export { JsonEditor, JsonViewer, NTableJson };