najm-kit 2.7.0 → 2.7.2
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/CHANGELOG.md +112 -112
- package/dist/NBrandingContext-dkADu8JS.d.ts +82 -0
- package/dist/{NajmUIProvider-BsCoDjHH.d.ts → NajmUIProvider-ClpHD-55.d.ts} +33 -146
- package/dist/adapters/app.d.ts +58 -5
- package/dist/adapters/app.mjs +55 -19
- package/dist/adapters/next.d.ts +2 -1
- package/dist/adapters/next.mjs +3 -3
- package/dist/{chunk-4DLRXB2W.mjs → chunk-6OOBAEH2.mjs} +2 -7
- package/dist/chunk-7J7DWGKB.mjs +93 -0
- package/dist/{chunk-4MRUJ2ZO.mjs → chunk-IRFFSAO2.mjs} +1 -1
- package/dist/{chunk-YBM5CTE6.mjs → chunk-KVZACF4G.mjs} +6 -1
- package/dist/chunk-QOP7L6RD.mjs +218 -0
- package/dist/{chunk-7F65QM43.mjs → chunk-USZUOJMK.mjs} +89 -10
- package/dist/index.d.ts +193 -28
- package/dist/index.mjs +9 -8
- package/dist/json.mjs +3 -3
- package/dist/pagination-BvukSZir.d.ts +130 -0
- package/dist/paginationLabels-CY2PvbMj.d.ts +143 -0
- package/dist/query.d.ts +299 -0
- package/dist/query.mjs +131 -0
- package/package.json +11 -1
- package/dist/chunk-IGUQGT3G.mjs +0 -24
package/dist/adapters/app.mjs
CHANGED
|
@@ -1,33 +1,66 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import {
|
|
3
|
-
import { NajmNextUIProvider } from '../chunk-
|
|
4
|
-
import '../chunk-
|
|
5
|
-
import '../chunk-
|
|
2
|
+
import { NBrandingStateProvider, NajmFormatProvider } from '../chunk-QOP7L6RD.mjs';
|
|
3
|
+
import { NajmNextUIProvider } from '../chunk-IRFFSAO2.mjs';
|
|
4
|
+
import '../chunk-USZUOJMK.mjs';
|
|
5
|
+
import '../chunk-KVZACF4G.mjs';
|
|
6
6
|
import * as React from 'react';
|
|
7
7
|
import { I18nProvider, useTranslation } from 'najm-i18n/react';
|
|
8
8
|
import { jsx } from 'react/jsx-runtime';
|
|
9
9
|
|
|
10
10
|
var DEFAULT_LANGUAGE_ENDPOINT = "/api/ui-language";
|
|
11
|
-
function NajmAppUI({
|
|
12
|
-
|
|
11
|
+
function NajmAppUI({
|
|
12
|
+
children,
|
|
13
|
+
branding,
|
|
14
|
+
initialBranding,
|
|
15
|
+
currency,
|
|
16
|
+
locale,
|
|
17
|
+
locales,
|
|
18
|
+
formatPlaceholder,
|
|
19
|
+
...props
|
|
20
|
+
}) {
|
|
21
|
+
const { t, language } = useTranslation();
|
|
22
|
+
const resolved = locale ?? locales?.[language] ?? language;
|
|
13
23
|
return /* @__PURE__ */ jsx(NajmNextUIProvider, { t, ...props, children: /* @__PURE__ */ jsx(
|
|
14
|
-
|
|
24
|
+
NBrandingStateProvider,
|
|
15
25
|
{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
26
|
+
branding,
|
|
27
|
+
initialBranding,
|
|
28
|
+
children: /* @__PURE__ */ jsx(
|
|
29
|
+
NajmFormatProvider,
|
|
30
|
+
{
|
|
31
|
+
locale: resolved,
|
|
32
|
+
currency,
|
|
33
|
+
placeholder: formatPlaceholder,
|
|
34
|
+
children
|
|
35
|
+
}
|
|
36
|
+
)
|
|
20
37
|
}
|
|
21
38
|
) });
|
|
22
39
|
}
|
|
23
|
-
function NajmAppNoI18n({
|
|
40
|
+
function NajmAppNoI18n({
|
|
41
|
+
children,
|
|
42
|
+
branding,
|
|
43
|
+
initialBranding,
|
|
44
|
+
currency,
|
|
45
|
+
locale,
|
|
46
|
+
locales,
|
|
47
|
+
formatPlaceholder,
|
|
48
|
+
...props
|
|
49
|
+
}) {
|
|
24
50
|
return /* @__PURE__ */ jsx(NajmNextUIProvider, { ...props, children: /* @__PURE__ */ jsx(
|
|
25
|
-
|
|
51
|
+
NBrandingStateProvider,
|
|
26
52
|
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
53
|
+
branding,
|
|
54
|
+
initialBranding,
|
|
55
|
+
children: /* @__PURE__ */ jsx(
|
|
56
|
+
NajmFormatProvider,
|
|
57
|
+
{
|
|
58
|
+
locale: locale ?? "en",
|
|
59
|
+
currency,
|
|
60
|
+
placeholder: formatPlaceholder,
|
|
61
|
+
children
|
|
62
|
+
}
|
|
63
|
+
)
|
|
31
64
|
}
|
|
32
65
|
) });
|
|
33
66
|
}
|
|
@@ -36,6 +69,8 @@ function NajmAppProvider({
|
|
|
36
69
|
initialLanguage,
|
|
37
70
|
defaultLanguage,
|
|
38
71
|
languageEndpoint = DEFAULT_LANGUAGE_ENDPOINT,
|
|
72
|
+
appName,
|
|
73
|
+
initialBranding,
|
|
39
74
|
...props
|
|
40
75
|
}) {
|
|
41
76
|
const persistLanguage = React.useCallback(
|
|
@@ -54,7 +89,8 @@ function NajmAppProvider({
|
|
|
54
89
|
},
|
|
55
90
|
[languageEndpoint]
|
|
56
91
|
);
|
|
57
|
-
|
|
92
|
+
const seeded = appName ? { appName, ...initialBranding } : initialBranding;
|
|
93
|
+
if (!translations) return /* @__PURE__ */ jsx(NajmAppNoI18n, { ...props, initialBranding: seeded });
|
|
58
94
|
return /* @__PURE__ */ jsx(
|
|
59
95
|
I18nProvider,
|
|
60
96
|
{
|
|
@@ -62,7 +98,7 @@ function NajmAppProvider({
|
|
|
62
98
|
initialLanguage: initialLanguage ?? defaultLanguage ?? "en",
|
|
63
99
|
defaultLanguage,
|
|
64
100
|
onLanguageChange: persistLanguage,
|
|
65
|
-
children: /* @__PURE__ */ jsx(NajmAppUI, { ...props })
|
|
101
|
+
children: /* @__PURE__ */ jsx(NajmAppUI, { ...props, initialBranding: seeded })
|
|
66
102
|
}
|
|
67
103
|
);
|
|
68
104
|
}
|
package/dist/adapters/next.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React__default from 'react';
|
|
3
|
-
import { N as NajmUIProviderProps } from '../NajmUIProvider-
|
|
3
|
+
import { N as NajmUIProviderProps } from '../NajmUIProvider-ClpHD-55.js';
|
|
4
|
+
import '../paginationLabels-CY2PvbMj.js';
|
|
4
5
|
|
|
5
6
|
interface NextLinkAdapterProps extends Record<string, any> {
|
|
6
7
|
href: string;
|
package/dist/adapters/next.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { NajmNextUIProvider, NextLinkAdapter, useNextNavigationAdapter } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { NajmNextUIProvider, NextLinkAdapter, useNextNavigationAdapter } from '../chunk-IRFFSAO2.mjs';
|
|
2
|
+
import '../chunk-USZUOJMK.mjs';
|
|
3
|
+
import '../chunk-KVZACF4G.mjs';
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { useNajmComponentStyle } from './chunk-
|
|
2
|
-
import { clsx } from 'clsx';
|
|
3
|
-
import { twMerge } from 'tailwind-merge';
|
|
1
|
+
import { useNajmComponentStyle, cn } from './chunk-KVZACF4G.mjs';
|
|
4
2
|
import * as React2 from 'react';
|
|
5
3
|
import React2__default, { createContext, useContext } from 'react';
|
|
6
4
|
import * as LucideIcons from 'lucide-react';
|
|
@@ -11,9 +9,6 @@ import { cva } from 'class-variance-authority';
|
|
|
11
9
|
import { OverlayScrollbars } from 'overlayscrollbars';
|
|
12
10
|
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
|
13
11
|
|
|
14
|
-
function cn(...inputs) {
|
|
15
|
-
return twMerge(clsx(inputs));
|
|
16
|
-
}
|
|
17
12
|
function toPascalCase(value) {
|
|
18
13
|
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("");
|
|
19
14
|
}
|
|
@@ -829,4 +824,4 @@ function NTableJson() {
|
|
|
829
824
|
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) }) }) });
|
|
830
825
|
}
|
|
831
826
|
|
|
832
|
-
export { Button, NAJM_COMPONENT_NAMES, NButton, NIcon, NTableJson, NajmScroll, RADIUS_VALUE_MAP, TableStoreContext, buttonVariants,
|
|
827
|
+
export { Button, NAJM_COMPONENT_NAMES, NButton, NIcon, NTableJson, NajmScroll, RADIUS_VALUE_MAP, TableStoreContext, buttonVariants, defineNajmDesignConfig, defineNajmThemeConfig, inputBorderClasses, parseNajmDesignConfig, parseNajmThemeConfig, resolveRadiusValue, resolveVariantAlias, sidebarBorderClasses, stringifyNajmDesignConfig, stringifyNajmThemeConfig, surfaceBorderClasses, useNajmScrollViewport, useTableStore };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { useCallback, useSyncExternalStore } from 'react';
|
|
2
|
+
|
|
3
|
+
// src/hooks/useMediaQuery.ts
|
|
4
|
+
function useMediaQuery(query, serverSnapshot = false) {
|
|
5
|
+
const subscribe = useCallback(
|
|
6
|
+
(onStoreChange) => {
|
|
7
|
+
const media = window.matchMedia(query);
|
|
8
|
+
media.addEventListener("change", onStoreChange);
|
|
9
|
+
return () => media.removeEventListener("change", onStoreChange);
|
|
10
|
+
},
|
|
11
|
+
[query]
|
|
12
|
+
);
|
|
13
|
+
return useSyncExternalStore(
|
|
14
|
+
subscribe,
|
|
15
|
+
() => window.matchMedia(query).matches,
|
|
16
|
+
() => serverSnapshot
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
var DEFAULT_CARD_BREAKPOINT = 1024;
|
|
20
|
+
function useCardViewport(breakpoint = DEFAULT_CARD_BREAKPOINT) {
|
|
21
|
+
return useMediaQuery(`(max-width: ${breakpoint - 1}px)`);
|
|
22
|
+
}
|
|
23
|
+
function useDesktopTableMode(breakpoint = DEFAULT_CARD_BREAKPOINT) {
|
|
24
|
+
return useMediaQuery(`(min-width: ${breakpoint}px)`) ? "table" : "cards";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/components/table/cardPagination.ts
|
|
28
|
+
var DEFAULT_CARD_PAGINATION_KEY_PREFIX = "common.pagination";
|
|
29
|
+
function buildCardPaginationLabels(t, prefix = DEFAULT_CARD_PAGINATION_KEY_PREFIX) {
|
|
30
|
+
return {
|
|
31
|
+
loadMoreError: t(`${prefix}.loadMoreError`),
|
|
32
|
+
retryLabel: t(`${prefix}.retryLoadMore`),
|
|
33
|
+
itemsLoaded: (count) => t(`${prefix}.itemsLoaded`, { count })
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function createCardPagination(state, labels = {}) {
|
|
37
|
+
const mode = state.mode ?? (state.cardViewport ? "infinite" : "paged");
|
|
38
|
+
if (mode === "paged") return { mode: "paged" };
|
|
39
|
+
if (mode === "all") return { mode: "all" };
|
|
40
|
+
return {
|
|
41
|
+
mode: "infinite",
|
|
42
|
+
hasNextPage: state.hasNextPage,
|
|
43
|
+
loadingMore: state.loadingMore,
|
|
44
|
+
loadMoreError: state.loadMoreError ? labels.loadMoreError : void 0,
|
|
45
|
+
onLoadMore: state.onLoadMore,
|
|
46
|
+
retryLabel: labels.retryLabel,
|
|
47
|
+
loadMoreErrorLabel: labels.loadMoreError,
|
|
48
|
+
itemsLoadedLabel: labels.itemsLoaded
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/lib/pagination.ts
|
|
53
|
+
var DEFAULT_PAGE_SIZE = 25;
|
|
54
|
+
var DEFAULT_MAX_PAGE_SIZE = 100;
|
|
55
|
+
function toApiPage(result) {
|
|
56
|
+
return Array.isArray(result) ? { rows: result, total: null } : result;
|
|
57
|
+
}
|
|
58
|
+
function createOffsetPagination(pageIndex = 0, pageSize = DEFAULT_PAGE_SIZE, { maxLimit = DEFAULT_MAX_PAGE_SIZE } = {}) {
|
|
59
|
+
const safePageIndex = Math.max(0, Math.trunc(pageIndex));
|
|
60
|
+
const safePageSize = Math.min(maxLimit, Math.max(1, Math.trunc(pageSize)));
|
|
61
|
+
return { limit: safePageSize, offset: safePageIndex * safePageSize };
|
|
62
|
+
}
|
|
63
|
+
function getPageIndex({ limit, offset }) {
|
|
64
|
+
return Math.floor(Math.max(0, offset) / Math.max(1, limit));
|
|
65
|
+
}
|
|
66
|
+
async function fetchOffsetPage(fetchPage, pagination, { maxLimit = DEFAULT_MAX_PAGE_SIZE } = {}) {
|
|
67
|
+
const requestedLimit = Math.min(maxLimit, Math.max(1, pagination.limit));
|
|
68
|
+
const probeLimit = requestedLimit < maxLimit ? requestedLimit + 1 : requestedLimit;
|
|
69
|
+
const page = toApiPage(
|
|
70
|
+
await fetchPage({ limit: probeLimit, offset: pagination.offset })
|
|
71
|
+
);
|
|
72
|
+
const rows = page.rows.slice(0, requestedLimit);
|
|
73
|
+
const nextOffset = pagination.offset + rows.length;
|
|
74
|
+
if (page.total !== null) {
|
|
75
|
+
return {
|
|
76
|
+
rows,
|
|
77
|
+
hasNextPage: nextOffset < page.total,
|
|
78
|
+
nextOffset,
|
|
79
|
+
total: page.total
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const hasNextPage = page.rows.length > requestedLimit || probeLimit === requestedLimit && page.rows.length === requestedLimit && toApiPage(await fetchPage({ limit: 1, offset: nextOffset })).rows.length > 0;
|
|
83
|
+
return { rows, hasNextPage, nextOffset, total: null };
|
|
84
|
+
}
|
|
85
|
+
function cleanQuery(query) {
|
|
86
|
+
return Object.fromEntries(
|
|
87
|
+
Object.entries(query).filter(
|
|
88
|
+
([, value]) => value !== void 0 && value !== null && value !== ""
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export { DEFAULT_CARD_BREAKPOINT, DEFAULT_CARD_PAGINATION_KEY_PREFIX, DEFAULT_MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, buildCardPaginationLabels, cleanQuery, createCardPagination, createOffsetPagination, fetchOffsetPage, getPageIndex, useCardViewport, useDesktopTableMode, useMediaQuery };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { Slot } from '@radix-ui/react-slot';
|
|
3
3
|
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
import { clsx } from 'clsx';
|
|
5
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
6
|
|
|
5
7
|
// src/theme/presets/modes.ts
|
|
6
8
|
var lightMode = {
|
|
@@ -301,6 +303,9 @@ function NajmThemeProvider({
|
|
|
301
303
|
}
|
|
302
304
|
) }) }) }) });
|
|
303
305
|
}
|
|
306
|
+
function cn(...inputs) {
|
|
307
|
+
return twMerge(clsx(inputs));
|
|
308
|
+
}
|
|
304
309
|
var NajmDesignContext = React.createContext({
|
|
305
310
|
components: {}
|
|
306
311
|
});
|
|
@@ -363,4 +368,4 @@ function NajmDesignProvider({
|
|
|
363
368
|
) : children }) });
|
|
364
369
|
}
|
|
365
370
|
|
|
366
|
-
export { NajmDesignProvider, NajmThemeContainerCtx, NajmThemeProvider, composePreset, resolvePreset, useNajmAppearance, useNajmComponentStyle, useNajmDesign, useNajmThemeMode };
|
|
371
|
+
export { NajmDesignProvider, NajmThemeContainerCtx, NajmThemeProvider, cn, composePreset, resolvePreset, useNajmAppearance, useNajmComponentStyle, useNajmDesign, useNajmThemeMode };
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { useNajmPreferencesContext } from './chunk-USZUOJMK.mjs';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { createContext, useContext, useMemo, useState, useCallback } from 'react';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
function normalizeBranding(input) {
|
|
7
|
+
if (!input) return {};
|
|
8
|
+
const value = {};
|
|
9
|
+
const expanded = input.logoExpanded ?? input.sidebarLogoExpandedPath;
|
|
10
|
+
const collapsed = input.logoCollapsed ?? input.sidebarLogoCollapsedPath;
|
|
11
|
+
if (input.appName !== void 0) value.appName = input.appName;
|
|
12
|
+
if (input.logoFallback !== void 0) value.logoFallback = input.logoFallback;
|
|
13
|
+
if (input.logoHref !== void 0) value.logoHref = input.logoHref;
|
|
14
|
+
if (expanded !== void 0) value.logoExpanded = expanded;
|
|
15
|
+
if (collapsed !== void 0) value.logoCollapsed = collapsed;
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
var NBrandingContext = createContext(null);
|
|
19
|
+
function useNBranding() {
|
|
20
|
+
return useContext(NBrandingContext);
|
|
21
|
+
}
|
|
22
|
+
function NBrandingProvider({
|
|
23
|
+
children,
|
|
24
|
+
appName,
|
|
25
|
+
logoExpanded,
|
|
26
|
+
logoCollapsed,
|
|
27
|
+
logoFallback,
|
|
28
|
+
logoHref
|
|
29
|
+
}) {
|
|
30
|
+
const value = useMemo(
|
|
31
|
+
() => ({ appName, logoExpanded, logoCollapsed, logoFallback, logoHref }),
|
|
32
|
+
[appName, logoExpanded, logoCollapsed, logoFallback, logoHref]
|
|
33
|
+
);
|
|
34
|
+
return /* @__PURE__ */ jsx(NBrandingContext.Provider, { value, children });
|
|
35
|
+
}
|
|
36
|
+
var NBrandingEditorContext = createContext(null);
|
|
37
|
+
function useNBrandingEditor() {
|
|
38
|
+
return useContext(NBrandingEditorContext);
|
|
39
|
+
}
|
|
40
|
+
function NBrandingStateProvider({
|
|
41
|
+
children,
|
|
42
|
+
branding,
|
|
43
|
+
initialBranding
|
|
44
|
+
}) {
|
|
45
|
+
const [state, setState] = useState(
|
|
46
|
+
() => normalizeBranding(initialBranding ?? branding)
|
|
47
|
+
);
|
|
48
|
+
const setBranding = useCallback((patch) => {
|
|
49
|
+
const marks = normalizeBranding(patch);
|
|
50
|
+
setState((current) => ({ ...current, ...marks }));
|
|
51
|
+
}, []);
|
|
52
|
+
const controlled = useMemo(
|
|
53
|
+
() => branding ? normalizeBranding(branding) : void 0,
|
|
54
|
+
[branding]
|
|
55
|
+
);
|
|
56
|
+
const resolved = controlled ?? state;
|
|
57
|
+
const editor = useMemo(
|
|
58
|
+
() => ({ branding: resolved, setBranding: branding ? noop : setBranding }),
|
|
59
|
+
[resolved, branding, setBranding]
|
|
60
|
+
);
|
|
61
|
+
return /* @__PURE__ */ jsx(NBrandingEditorContext.Provider, { value: editor, children: /* @__PURE__ */ jsx(NBrandingProvider, { ...resolved, children }) });
|
|
62
|
+
}
|
|
63
|
+
function noop() {
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/format/format.ts
|
|
67
|
+
var DEFAULT_PLACEHOLDER = "\u2014";
|
|
68
|
+
var numberFormats = /* @__PURE__ */ new Map();
|
|
69
|
+
var dateFormats = /* @__PURE__ */ new Map();
|
|
70
|
+
function numberFormat(locale, options) {
|
|
71
|
+
const key = `${locale}|${options ? JSON.stringify(options) : ""}`;
|
|
72
|
+
let format = numberFormats.get(key);
|
|
73
|
+
if (!format) {
|
|
74
|
+
format = new Intl.NumberFormat(locale, options);
|
|
75
|
+
numberFormats.set(key, format);
|
|
76
|
+
}
|
|
77
|
+
return format;
|
|
78
|
+
}
|
|
79
|
+
function dateFormat(locale, options) {
|
|
80
|
+
const key = `${locale}|${JSON.stringify(options)}`;
|
|
81
|
+
let format = dateFormats.get(key);
|
|
82
|
+
if (!format) {
|
|
83
|
+
format = new Intl.DateTimeFormat(locale, options);
|
|
84
|
+
dateFormats.set(key, format);
|
|
85
|
+
}
|
|
86
|
+
return format;
|
|
87
|
+
}
|
|
88
|
+
function minorUnitScale(locale, currency) {
|
|
89
|
+
const digits = numberFormat(locale, { style: "currency", currency }).resolvedOptions().maximumFractionDigits ?? 2;
|
|
90
|
+
return 10 ** digits;
|
|
91
|
+
}
|
|
92
|
+
function toDate(value) {
|
|
93
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
94
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
95
|
+
}
|
|
96
|
+
function isBlank(value) {
|
|
97
|
+
return value === null || value === void 0 || value === "";
|
|
98
|
+
}
|
|
99
|
+
function formatCurrency(minorUnits, { locale, currency, placeholder = DEFAULT_PLACEHOLDER }) {
|
|
100
|
+
if (!currency) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
"formatCurrency requires a `currency`. Set it on NajmFormatProvider or pass it here."
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
if (minorUnits === null || minorUnits === void 0) return placeholder;
|
|
106
|
+
if (!Number.isSafeInteger(minorUnits)) return placeholder;
|
|
107
|
+
return numberFormat(locale, {
|
|
108
|
+
style: "currency",
|
|
109
|
+
currency
|
|
110
|
+
}).format(minorUnits / minorUnitScale(locale, currency));
|
|
111
|
+
}
|
|
112
|
+
function formatNumber(value, { locale, placeholder = DEFAULT_PLACEHOLDER }, options) {
|
|
113
|
+
if (value === null || value === void 0 || !Number.isFinite(value)) {
|
|
114
|
+
return placeholder;
|
|
115
|
+
}
|
|
116
|
+
return numberFormat(locale, options).format(value);
|
|
117
|
+
}
|
|
118
|
+
function formatPercent(value, config, fractionDigits = 0) {
|
|
119
|
+
return formatNumber(value, config, {
|
|
120
|
+
style: "percent",
|
|
121
|
+
minimumFractionDigits: fractionDigits,
|
|
122
|
+
maximumFractionDigits: fractionDigits
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function formatDate(value, {
|
|
126
|
+
locale,
|
|
127
|
+
timeZone,
|
|
128
|
+
placeholder = DEFAULT_PLACEHOLDER
|
|
129
|
+
}, options = { dateStyle: "medium" }) {
|
|
130
|
+
if (isBlank(value)) return placeholder;
|
|
131
|
+
const date = toDate(value);
|
|
132
|
+
if (!date) return placeholder;
|
|
133
|
+
return dateFormat(locale, { ...options, timeZone }).format(date);
|
|
134
|
+
}
|
|
135
|
+
function formatDateTime(value, config, options = {
|
|
136
|
+
dateStyle: "short",
|
|
137
|
+
timeStyle: "short"
|
|
138
|
+
}) {
|
|
139
|
+
return formatDate(value, config, options);
|
|
140
|
+
}
|
|
141
|
+
function formatTime(value, config) {
|
|
142
|
+
return formatDate(value, config, { timeStyle: "short" });
|
|
143
|
+
}
|
|
144
|
+
var RELATIVE_UNITS = [
|
|
145
|
+
["year", 31536e6],
|
|
146
|
+
["month", 2592e6],
|
|
147
|
+
["day", 864e5],
|
|
148
|
+
["hour", 36e5],
|
|
149
|
+
["minute", 6e4],
|
|
150
|
+
["second", 1e3]
|
|
151
|
+
];
|
|
152
|
+
function formatRelativeTime(value, { locale, placeholder = DEFAULT_PLACEHOLDER }, now = Date.now()) {
|
|
153
|
+
if (isBlank(value)) return placeholder;
|
|
154
|
+
const date = toDate(value);
|
|
155
|
+
if (!date) return placeholder;
|
|
156
|
+
const elapsed = date.getTime() - (now instanceof Date ? now.getTime() : now);
|
|
157
|
+
const format = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
|
|
158
|
+
for (const [unit, ms] of RELATIVE_UNITS) {
|
|
159
|
+
if (Math.abs(elapsed) >= ms) {
|
|
160
|
+
return format.format(Math.trunc(elapsed / ms), unit);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return format.format(0, "second");
|
|
164
|
+
}
|
|
165
|
+
function humanizeToken(value) {
|
|
166
|
+
return value.trim().replace(/[_-]+/g, " ").replace(/\s+/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
|
|
167
|
+
}
|
|
168
|
+
var NajmFormatContext = React.createContext(
|
|
169
|
+
null
|
|
170
|
+
);
|
|
171
|
+
function NajmFormatProvider({
|
|
172
|
+
children,
|
|
173
|
+
locale,
|
|
174
|
+
currency,
|
|
175
|
+
timeZone,
|
|
176
|
+
placeholder = DEFAULT_PLACEHOLDER
|
|
177
|
+
}) {
|
|
178
|
+
const preferences = useNajmPreferencesContext();
|
|
179
|
+
const resolvedTimeZone = timeZone ?? preferences?.timeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
180
|
+
const value = React.useMemo(() => {
|
|
181
|
+
const config = {
|
|
182
|
+
locale,
|
|
183
|
+
timeZone: resolvedTimeZone,
|
|
184
|
+
currency,
|
|
185
|
+
placeholder
|
|
186
|
+
};
|
|
187
|
+
return {
|
|
188
|
+
locale,
|
|
189
|
+
timeZone: resolvedTimeZone,
|
|
190
|
+
currency,
|
|
191
|
+
placeholder,
|
|
192
|
+
config,
|
|
193
|
+
money: (minorUnits) => formatCurrency(minorUnits, config),
|
|
194
|
+
number: (value_, options) => formatNumber(value_, config, options),
|
|
195
|
+
percent: (value_, digits) => formatPercent(value_, config, digits),
|
|
196
|
+
date: (value_, options) => formatDate(value_, config, options),
|
|
197
|
+
dateTime: (value_) => formatDateTime(value_, config),
|
|
198
|
+
time: (value_) => formatTime(value_, config),
|
|
199
|
+
relativeTime: (value_) => formatRelativeTime(value_, config),
|
|
200
|
+
humanize: humanizeToken
|
|
201
|
+
};
|
|
202
|
+
}, [locale, resolvedTimeZone, currency, placeholder]);
|
|
203
|
+
return /* @__PURE__ */ jsx(NajmFormatContext.Provider, { value, children });
|
|
204
|
+
}
|
|
205
|
+
function useNajmFormatContext() {
|
|
206
|
+
return React.useContext(NajmFormatContext);
|
|
207
|
+
}
|
|
208
|
+
function useNajmFormat() {
|
|
209
|
+
const value = React.useContext(NajmFormatContext);
|
|
210
|
+
if (!value) {
|
|
211
|
+
throw new Error(
|
|
212
|
+
"useNajmFormat must be rendered under a NajmFormatProvider or NajmAppProvider."
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
return value;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export { DEFAULT_PLACEHOLDER, NBrandingProvider, NBrandingStateProvider, NajmFormatProvider, formatCurrency, formatDate, formatDateTime, formatNumber, formatPercent, formatRelativeTime, formatTime, humanizeToken, normalizeBranding, useNBranding, useNBrandingEditor, useNajmFormat, useNajmFormatContext };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NajmDesignProvider } from './chunk-
|
|
1
|
+
import { NajmDesignProvider, cn } from './chunk-KVZACF4G.mjs';
|
|
2
2
|
import * as React2 from 'react';
|
|
3
3
|
import React2__default from 'react';
|
|
4
4
|
import { jsx } from 'react/jsx-runtime';
|
|
@@ -23,6 +23,17 @@ function useResolvedPaginationLabels(own) {
|
|
|
23
23
|
}
|
|
24
24
|
var NajmPreferencesContext = React2.createContext(null);
|
|
25
25
|
var DEFAULT_TIME_ZONE = "UTC";
|
|
26
|
+
function isValidTimeZone(value) {
|
|
27
|
+
try {
|
|
28
|
+
new Intl.DateTimeFormat(void 0, { timeZone: value });
|
|
29
|
+
return true;
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function defaultNormalizeTimeZone(value) {
|
|
35
|
+
return isValidTimeZone(value) ? value : DEFAULT_TIME_ZONE;
|
|
36
|
+
}
|
|
26
37
|
function applyTheme(theme) {
|
|
27
38
|
if (typeof document === "undefined") return;
|
|
28
39
|
document.documentElement.classList.toggle("dark", theme === "dark");
|
|
@@ -37,11 +48,11 @@ function NajmPreferencesProvider({
|
|
|
37
48
|
initialTimeZone = DEFAULT_TIME_ZONE,
|
|
38
49
|
onThemeChange,
|
|
39
50
|
onTimeZoneChange,
|
|
40
|
-
normalizeTimeZone
|
|
51
|
+
normalizeTimeZone = defaultNormalizeTimeZone
|
|
41
52
|
}) {
|
|
42
53
|
const [theme, setThemeState] = React2.useState(initialTheme);
|
|
43
54
|
const [timeZone, setTimeZoneState] = React2.useState(
|
|
44
|
-
() => normalizeTimeZone
|
|
55
|
+
() => normalizeTimeZone(initialTimeZone)
|
|
45
56
|
);
|
|
46
57
|
const onThemeChangeRef = React2.useRef(onThemeChange);
|
|
47
58
|
const onTimeZoneChangeRef = React2.useRef(onTimeZoneChange);
|
|
@@ -61,7 +72,7 @@ function NajmPreferencesProvider({
|
|
|
61
72
|
await onThemeChangeRef.current?.(next);
|
|
62
73
|
}, []);
|
|
63
74
|
const setTimeZone = React2.useCallback(async (next) => {
|
|
64
|
-
const normalized = normalizeRef.current
|
|
75
|
+
const normalized = normalizeRef.current(next);
|
|
65
76
|
setTimeZoneState(normalized);
|
|
66
77
|
applyTimeZone(normalized);
|
|
67
78
|
await onTimeZoneChangeRef.current?.(normalized);
|
|
@@ -119,26 +130,95 @@ var EMPTY_DESIGN = Object.freeze({
|
|
|
119
130
|
theme: {},
|
|
120
131
|
components: {}
|
|
121
132
|
});
|
|
133
|
+
var NajmDesignEditorContext = React2.createContext(null);
|
|
134
|
+
function useNajmDesignEditor() {
|
|
135
|
+
return React2.useContext(NajmDesignEditorContext);
|
|
136
|
+
}
|
|
137
|
+
function cloneDesign(design) {
|
|
138
|
+
return structuredClone(design);
|
|
139
|
+
}
|
|
140
|
+
function NajmDesignEditorProvider({
|
|
141
|
+
children,
|
|
142
|
+
design,
|
|
143
|
+
initialDesign
|
|
144
|
+
}) {
|
|
145
|
+
const [state, setState] = React2.useState(() => ({
|
|
146
|
+
committed: initialDesign ?? design ?? EMPTY_DESIGN,
|
|
147
|
+
draft: null
|
|
148
|
+
}));
|
|
149
|
+
const beginDraft = React2.useCallback(() => {
|
|
150
|
+
setState(
|
|
151
|
+
(current) => current.draft ? current : { ...current, draft: cloneDesign(current.committed) }
|
|
152
|
+
);
|
|
153
|
+
}, []);
|
|
154
|
+
const setDraft = React2.useCallback((next) => {
|
|
155
|
+
setState((current) => ({ ...current, draft: cloneDesign(next) }));
|
|
156
|
+
}, []);
|
|
157
|
+
const cancelDraft = React2.useCallback(() => {
|
|
158
|
+
setState(
|
|
159
|
+
(current) => current.draft === null ? current : { ...current, draft: null }
|
|
160
|
+
);
|
|
161
|
+
}, []);
|
|
162
|
+
const setCommitted = React2.useCallback((next) => {
|
|
163
|
+
setState({ committed: next, draft: null });
|
|
164
|
+
}, []);
|
|
165
|
+
const value = React2.useMemo(() => {
|
|
166
|
+
if (design) {
|
|
167
|
+
return {
|
|
168
|
+
design,
|
|
169
|
+
committed: design,
|
|
170
|
+
draft: null,
|
|
171
|
+
hasDraft: false,
|
|
172
|
+
beginDraft: noop,
|
|
173
|
+
setDraft: noop,
|
|
174
|
+
cancelDraft: noop,
|
|
175
|
+
setCommitted: noop
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
design: state.draft ?? state.committed,
|
|
180
|
+
committed: state.committed,
|
|
181
|
+
draft: state.draft,
|
|
182
|
+
hasDraft: state.draft !== null,
|
|
183
|
+
beginDraft,
|
|
184
|
+
setDraft,
|
|
185
|
+
cancelDraft,
|
|
186
|
+
setCommitted
|
|
187
|
+
};
|
|
188
|
+
}, [design, state, beginDraft, setDraft, cancelDraft, setCommitted]);
|
|
189
|
+
return /* @__PURE__ */ jsx(NajmDesignEditorContext.Provider, { value, children });
|
|
190
|
+
}
|
|
191
|
+
function noop() {
|
|
192
|
+
}
|
|
122
193
|
function NajmUICore({
|
|
123
194
|
children,
|
|
124
|
-
design = EMPTY_DESIGN,
|
|
125
195
|
className,
|
|
126
196
|
t,
|
|
127
197
|
paginationKeyPrefix = DEFAULT_PAGINATION_KEY_PREFIX,
|
|
128
198
|
tableDefaults
|
|
129
199
|
}) {
|
|
130
200
|
const { theme } = useNajmTheme();
|
|
201
|
+
const design = useNajmDesignEditor()?.design ?? EMPTY_DESIGN;
|
|
131
202
|
const defaults = React2.useMemo(() => {
|
|
132
203
|
const translated = t ? buildPaginationLabels(t, paginationKeyPrefix) : void 0;
|
|
133
204
|
const overrides = tableDefaults?.paginationLabels;
|
|
134
205
|
const paginationLabels = translated || overrides ? { ...translated, ...overrides } : void 0;
|
|
135
206
|
return { ...tableDefaults, paginationLabels };
|
|
136
207
|
}, [t, paginationKeyPrefix, tableDefaults]);
|
|
137
|
-
return /* @__PURE__ */ jsx(
|
|
208
|
+
return /* @__PURE__ */ jsx(
|
|
209
|
+
NajmDesignProvider,
|
|
210
|
+
{
|
|
211
|
+
config: design,
|
|
212
|
+
mode: theme,
|
|
213
|
+
className: cn("min-h-full", className),
|
|
214
|
+
children: /* @__PURE__ */ jsx(NTableDefaultsProvider, { value: defaults, children })
|
|
215
|
+
}
|
|
216
|
+
);
|
|
138
217
|
}
|
|
139
218
|
function NajmUIProvider({
|
|
140
219
|
children,
|
|
141
220
|
design,
|
|
221
|
+
initialDesign,
|
|
142
222
|
className,
|
|
143
223
|
t,
|
|
144
224
|
paginationKeyPrefix,
|
|
@@ -150,17 +230,16 @@ function NajmUIProvider({
|
|
|
150
230
|
normalizeTimeZone
|
|
151
231
|
}) {
|
|
152
232
|
const outerPreferences = useNajmPreferencesContext();
|
|
153
|
-
const core = /* @__PURE__ */ jsx(
|
|
233
|
+
const core = /* @__PURE__ */ jsx(NajmDesignEditorProvider, { design, initialDesign, children: /* @__PURE__ */ jsx(
|
|
154
234
|
NajmUICore,
|
|
155
235
|
{
|
|
156
|
-
design,
|
|
157
236
|
className,
|
|
158
237
|
t,
|
|
159
238
|
paginationKeyPrefix,
|
|
160
239
|
tableDefaults,
|
|
161
240
|
children
|
|
162
241
|
}
|
|
163
|
-
);
|
|
242
|
+
) });
|
|
164
243
|
if (outerPreferences) return core;
|
|
165
244
|
return /* @__PURE__ */ jsx(
|
|
166
245
|
NajmPreferencesProvider,
|
|
@@ -175,4 +254,4 @@ function NajmUIProvider({
|
|
|
175
254
|
);
|
|
176
255
|
}
|
|
177
256
|
|
|
178
|
-
export { DEFAULT_PAGINATION_KEY_PREFIX, DEFAULT_TIME_ZONE, NTableDefaultsProvider, NajmPreferencesProvider, NajmUIProvider, buildPaginationLabels, useNTableDefaults, useNajmPreferencesContext, useNajmTheme, useNajmTimeZone, useResolvedPaginationLabels };
|
|
257
|
+
export { DEFAULT_PAGINATION_KEY_PREFIX, DEFAULT_TIME_ZONE, EMPTY_DESIGN, NTableDefaultsProvider, NajmDesignEditorProvider, NajmPreferencesProvider, NajmUIProvider, buildPaginationLabels, useNTableDefaults, useNajmDesignEditor, useNajmPreferencesContext, useNajmTheme, useNajmTimeZone, useResolvedPaginationLabels };
|