najm-kit 2.10.0 → 2.11.1

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.
@@ -1,4 +1,4 @@
1
- import { NajmDesignProvider, cn } from './chunk-KVZACF4G.mjs';
1
+ import { NajmDesignProvider, cn } from './chunk-LK3SMYUP.mjs';
2
2
  import * as React2 from 'react';
3
3
  import React2__default from 'react';
4
4
  import { jsx } from 'react/jsx-runtime';
@@ -230,7 +230,9 @@ function NajmDesignEditorProvider({
230
230
  );
231
231
  }, []);
232
232
  const setCommitted = React2.useCallback((next) => {
233
- setState({ committed: next, draft: null });
233
+ setState(
234
+ (current) => current.committed === next && current.draft === null ? current : { committed: next, draft: null }
235
+ );
234
236
  }, []);
235
237
  const value = React2.useMemo(() => {
236
238
  if (design) {
@@ -288,13 +290,68 @@ function mergeBadgeMaps(base, overrides) {
288
290
  if (!overrides) return base;
289
291
  return { ...base, ...overrides };
290
292
  }
293
+ var ENGLISH_FEEDBACK_LABELS = {
294
+ loadingLabel: "Loading...",
295
+ emptyTitle: "No data",
296
+ errorTitle: "Something went wrong",
297
+ retryLabel: "Try again",
298
+ forbiddenTitle: "Access denied",
299
+ forbiddenDescription: "You do not have permission to view this page.",
300
+ notFoundTitle: "Page not found",
301
+ notFoundDescription: "The requested page could not be found."
302
+ };
303
+ var NFeedbackDefaultsContext = React2.createContext(null);
304
+ function NFeedbackDefaultsProvider({
305
+ value,
306
+ children
307
+ }) {
308
+ return /* @__PURE__ */ jsx(NFeedbackDefaultsContext.Provider, { value, children });
309
+ }
310
+ function useNFeedbackDefaults() {
311
+ return React2.useContext(NFeedbackDefaultsContext);
312
+ }
313
+ var DEFAULT_FEEDBACK_KEY_PREFIX = "common.feedback";
314
+ function useResolvedFeedbackLabels() {
315
+ const ctx = useNFeedbackDefaults();
316
+ return React2.useMemo(() => resolveFeedbackLabels(ctx), [ctx]);
317
+ }
318
+ function resolveFeedbackLabels(ctx) {
319
+ const defaults = ctx?.defaults;
320
+ const t = ctx?.t;
321
+ const labels = defaults?.labels;
322
+ const labelKeys = defaults?.labelKeys;
323
+ defaults?.prefix ?? DEFAULT_FEEDBACK_KEY_PREFIX;
324
+ const pick = (field, hasFallback) => {
325
+ const literal = labels?.[field];
326
+ if (literal !== void 0) return literal;
327
+ const key = labelKeys?.[field];
328
+ if (key && t) return t(key);
329
+ if (hasFallback) return ENGLISH_FEEDBACK_LABELS[field];
330
+ return void 0;
331
+ };
332
+ return {
333
+ loadingLabel: pick("loadingLabel", true) ?? ENGLISH_FEEDBACK_LABELS.loadingLabel,
334
+ emptyTitle: pick("emptyTitle", true) ?? ENGLISH_FEEDBACK_LABELS.emptyTitle,
335
+ errorTitle: pick("errorTitle", true) ?? ENGLISH_FEEDBACK_LABELS.errorTitle,
336
+ errorMessage: pick("errorMessage", false),
337
+ retryLabel: pick("retryLabel", true) ?? ENGLISH_FEEDBACK_LABELS.retryLabel,
338
+ forbiddenTitle: pick("forbiddenTitle", true) ?? ENGLISH_FEEDBACK_LABELS.forbiddenTitle,
339
+ forbiddenDescription: pick("forbiddenDescription", true) ?? ENGLISH_FEEDBACK_LABELS.forbiddenDescription,
340
+ notFoundTitle: pick("notFoundTitle", true) ?? ENGLISH_FEEDBACK_LABELS.notFoundTitle,
341
+ notFoundDescription: pick("notFoundDescription", true) ?? ENGLISH_FEEDBACK_LABELS.notFoundDescription
342
+ };
343
+ }
344
+ function resolveFeedbackDefaultsValue(defaults, t) {
345
+ return { defaults: defaults ?? {}, t };
346
+ }
291
347
  function NajmUICore({
292
348
  children,
293
349
  className,
294
350
  t,
295
351
  paginationKeyPrefix = DEFAULT_PAGINATION_KEY_PREFIX,
296
352
  tableDefaults,
297
- badgeDefaults
353
+ badgeDefaults,
354
+ feedbackDefaults
298
355
  }) {
299
356
  const { theme } = useNajmTheme();
300
357
  const design = useNajmDesignEditor()?.design ?? EMPTY_DESIGN;
@@ -304,13 +361,17 @@ function NajmUICore({
304
361
  const paginationLabels = translated || overrides ? { ...translated, ...overrides } : void 0;
305
362
  return { ...tableDefaults, paginationLabels };
306
363
  }, [t, paginationKeyPrefix, tableDefaults]);
364
+ const feedbackValue = React2.useMemo(
365
+ () => resolveFeedbackDefaultsValue(feedbackDefaults, t),
366
+ [feedbackDefaults, t]
367
+ );
307
368
  return /* @__PURE__ */ jsx(
308
369
  NajmDesignProvider,
309
370
  {
310
371
  config: design,
311
372
  mode: theme,
312
373
  className: cn("min-h-full", className),
313
- children: /* @__PURE__ */ jsx(NTableDefaultsProvider, { value: defaults, children: /* @__PURE__ */ jsx(NBadgeDefaultsProvider, { defaults: badgeDefaults, t, children }) })
374
+ children: /* @__PURE__ */ jsx(NTableDefaultsProvider, { value: defaults, children: /* @__PURE__ */ jsx(NBadgeDefaultsProvider, { defaults: badgeDefaults, t, children: /* @__PURE__ */ jsx(NFeedbackDefaultsProvider, { value: feedbackValue, children }) }) })
314
375
  }
315
376
  );
316
377
  }
@@ -323,6 +384,7 @@ function NajmUIProvider({
323
384
  paginationKeyPrefix,
324
385
  tableDefaults,
325
386
  badgeDefaults,
387
+ feedbackDefaults,
326
388
  initialTheme,
327
389
  initialTimeZone,
328
390
  onThemeChange,
@@ -338,6 +400,7 @@ function NajmUIProvider({
338
400
  paginationKeyPrefix,
339
401
  tableDefaults,
340
402
  badgeDefaults,
403
+ feedbackDefaults,
341
404
  children
342
405
  }
343
406
  ) });
@@ -414,4 +477,4 @@ function useImageChain(sources) {
414
477
  };
415
478
  }
416
479
 
417
- export { DEFAULT_PAGINATION_KEY_PREFIX, DEFAULT_TIME_ZONE, EMPTY_DESIGN, NAJM_COLOR_TEXT_CLASSES, NAJM_STATUS_COLORS, NTableDefaultsProvider, NajmDesignEditorProvider, NajmPreferencesProvider, NajmUIProvider, buildPaginationLabels, colorTextClass, findStatusColor, mergeBadgeMaps, normalizeImageSources, normalizeStatusToken, resolveBadgeStatusLabel, resolveStatusColor, statusTextClass, useImageChain, useNBadgeDefaults, useNTableDefaults, useNajmDesignEditor, useNajmPreferencesContext, useNajmTheme, useNajmTimeZone, useResolvedPaginationLabels };
480
+ export { DEFAULT_PAGINATION_KEY_PREFIX, DEFAULT_TIME_ZONE, EMPTY_DESIGN, NAJM_COLOR_TEXT_CLASSES, NAJM_STATUS_COLORS, NTableDefaultsProvider, NajmDesignEditorProvider, NajmPreferencesProvider, NajmUIProvider, buildPaginationLabels, colorTextClass, findStatusColor, mergeBadgeMaps, normalizeImageSources, normalizeStatusToken, resolveBadgeStatusLabel, resolveStatusColor, statusTextClass, useImageChain, useNBadgeDefaults, useNTableDefaults, useNajmDesignEditor, useNajmPreferencesContext, useNajmTheme, useNajmTimeZone, useResolvedFeedbackLabels, useResolvedPaginationLabels };
@@ -244,7 +244,7 @@ function NajmThemeProvider({
244
244
  const depth = React.useContext(NajmThemeDepthContext);
245
245
  const parentMode = React.useContext(NajmThemeModeContext);
246
246
  const parentAppearance = React.useContext(NajmAppearanceContext);
247
- const effectivePreset = preset ?? config?.preset;
247
+ const effectivePreset = preset ?? (mode === void 0 ? config?.preset : void 0);
248
248
  const effectiveMode = mode ?? config?.mode;
249
249
  const effectiveAccent = accent ?? config?.accent;
250
250
  const effectiveAccentOnly = accentOnly ?? config?.accentOnly;
@@ -1,14 +1,12 @@
1
- import { useNajmComponentStyle, cn } from './chunk-KVZACF4G.mjs';
1
+ import { useNajmComponentStyle, cn } from './chunk-LK3SMYUP.mjs';
2
2
  import { resolveVariantAlias, resolveRadiusValue } from './chunk-TFHWLE7N.mjs';
3
3
  import * as React2 from 'react';
4
- import React2__default, { createContext, useContext } from 'react';
4
+ import React2__default from 'react';
5
5
  import * as LucideIcons from 'lucide-react';
6
6
  import { LoaderCircleIcon } from 'lucide-react';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
8
  import { Slot } from '@radix-ui/react-slot';
9
9
  import { cva } from 'class-variance-authority';
10
- import { OverlayScrollbars } from 'overlayscrollbars';
11
- import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
12
10
 
13
11
  function toPascalCase(value) {
14
12
  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("");
@@ -292,113 +290,5 @@ var Button = React2.forwardRef(
292
290
  );
293
291
  Button.displayName = "Button";
294
292
  var NButton = Button;
295
- function assignRef(ref, node) {
296
- if (!ref) return;
297
- if (typeof ref === "function") ref(node);
298
- else ref.current = node;
299
- }
300
- function applyViewportLayout(node, axis) {
301
- node.style.width = "100%";
302
- node.style.height = "100%";
303
- node.style.minWidth = "0";
304
- node.style.minHeight = "0";
305
- node.style.overflowX = axis === "x" || axis === "both" ? "auto" : "hidden";
306
- node.style.overflowY = axis === "y" || axis === "both" ? "auto" : "hidden";
307
- }
308
- function najmScrollOptions(axis, autoHide, options) {
309
- return {
310
- scrollbars: { theme: "os-theme-najm", autoHide, autoHideDelay: 500, clickScroll: true },
311
- overflow: {
312
- x: axis === "x" || axis === "both" ? "scroll" : "hidden",
313
- y: axis === "y" || axis === "both" ? "scroll" : "hidden"
314
- },
315
- ...options
316
- };
317
- }
318
- function useNajmScrollViewport({
319
- axis = "y",
320
- autoHide = "never",
321
- options
322
- } = {}) {
323
- const hostRef = React2.useRef(null);
324
- const viewportRef = React2.useRef(null);
325
- React2.useEffect(() => {
326
- const target = hostRef.current;
327
- const viewport = viewportRef.current;
328
- if (!target || !viewport) return;
329
- const instance = OverlayScrollbars(
330
- { target, elements: { viewport } },
331
- najmScrollOptions(axis, autoHide, options)
332
- );
333
- const containWheel = (event) => event.stopPropagation();
334
- viewport.addEventListener("wheel", containWheel, { passive: true });
335
- return () => {
336
- viewport.removeEventListener("wheel", containWheel);
337
- instance.destroy();
338
- };
339
- }, [axis, autoHide, options]);
340
- return { hostRef, viewportRef };
341
- }
342
- function NajmScroll({ className, axis = "y", autoHide = "never", viewportRef, events, options, element, children, style, ...props }) {
343
- return /* @__PURE__ */ jsx(
344
- OverlayScrollbarsComponent,
345
- {
346
- className: cn(className),
347
- style: {
348
- ...style,
349
- overflow: "hidden",
350
- minHeight: 0,
351
- minWidth: 0
352
- },
353
- element,
354
- defer: true,
355
- options: najmScrollOptions(axis, autoHide, options || void 0),
356
- events: {
357
- ...events,
358
- initialized: (instance, ...rest) => {
359
- const viewport = instance.elements().viewport;
360
- applyViewportLayout(viewport, axis);
361
- assignRef(viewportRef, viewport);
362
- events?.initialized?.(instance, ...rest);
363
- },
364
- updated: (instance, ...rest) => {
365
- applyViewportLayout(instance.elements().viewport, axis);
366
- events?.updated?.(instance, ...rest);
367
- },
368
- destroyed: (instance, ...rest) => {
369
- assignRef(viewportRef, null);
370
- events?.destroyed?.(instance, ...rest);
371
- }
372
- },
373
- ...props,
374
- children
375
- }
376
- );
377
- }
378
- var TableStoreContext = createContext(null);
379
- var useTableStore = { use: {} };
380
- var handler = {
381
- get: (_, prop) => () => {
382
- const store = useContext(TableStoreContext);
383
- if (!store) throw new Error("useTableStore must be used within NTable");
384
- return store.use[prop]();
385
- }
386
- };
387
- useTableStore.use = new Proxy({}, handler);
388
- function formatJsonValue(value) {
389
- if (typeof value === "string") return value;
390
- try {
391
- return JSON.stringify(value ?? null, null, 2) ?? String(value);
392
- } catch {
393
- return String(value);
394
- }
395
- }
396
- function NTableJson() {
397
- const viewMode = useTableStore.use.viewMode();
398
- const renderJson = useTableStore.use.renderJson();
399
- const jsonValue = useTableStore.use.jsonValue();
400
- if (viewMode !== "json") return null;
401
- 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) }) }) });
402
- }
403
293
 
404
- export { Button, NButton, NIcon, NTableJson, NajmScroll, TableStoreContext, buttonVariants, inputBorderClasses, sidebarBorderClasses, surfaceBorderClasses, useNajmScrollViewport, useTableStore };
294
+ export { Button, NButton, NIcon, buttonVariants, inputBorderClasses, sidebarBorderClasses, surfaceBorderClasses };
@@ -1,4 +1,4 @@
1
- import { useImageChain, normalizeImageSources, NajmUIProvider } from './chunk-FDONJASN.mjs';
1
+ import { useImageChain, normalizeImageSources, NajmUIProvider } from './chunk-6UDJNTJ6.mjs';
2
2
  import React from 'react';
3
3
  import { useRouter } from 'next/navigation';
4
4
  import NextImage from 'next/image';