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/index.d.ts +474 -102
- package/dist/index.mjs +2605 -1038
- package/dist/json.mjs +131 -11
- package/dist/styles.css +1374 -62
- package/package.json +8 -3
package/dist/json.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import
|
|
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 (
|
|
199
|
-
return
|
|
200
|
-
className: cn(icon.props.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 =
|
|
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] =
|
|
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
|
|
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(
|
|
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
|
|
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("
|
|
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 };
|