najm-kit 2.9.0 → 2.11.0
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 +263 -174
- package/README.md +665 -351
- package/dist/{formFill-BcH-m9Kf.d.ts → NNotFoundState-D1CLLLxc.d.ts} +84 -2
- package/dist/NajmUIProvider-cNCb8Tpn.d.ts +327 -0
- package/dist/adapters/app.d.ts +7 -2
- package/dist/adapters/app.mjs +6 -3
- package/dist/adapters/next.d.ts +27 -2
- package/dist/adapters/next.mjs +2 -2
- package/dist/chunk-2GFWF46W.mjs +650 -0
- package/dist/{chunk-IRFFSAO2.mjs → chunk-CE7MVEJ2.mjs} +26 -2
- package/dist/chunk-EEBLEDNI.mjs +480 -0
- package/dist/chunk-K7T7X6PX.mjs +117 -0
- package/dist/{chunk-JUYT2ISO.mjs → chunk-XZL32HFR.mjs} +2 -112
- package/dist/index.d.ts +134 -94
- package/dist/index.mjs +480 -365
- package/dist/json.mjs +2 -2
- package/dist/theme.css +5 -5
- package/package.json +3 -1
- package/dist/NajmUIProvider-CI_73GEp.d.ts +0 -161
- package/dist/chunk-GHMR45H3.mjs +0 -333
- package/dist/chunk-USZUOJMK.mjs +0 -257
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import { NajmDesignProvider, cn } from './chunk-KVZACF4G.mjs';
|
|
2
|
+
import * as React2 from 'react';
|
|
3
|
+
import React2__default from 'react';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
// src/components/Badge/status.ts
|
|
7
|
+
var NAJM_STATUS_COLORS = {
|
|
8
|
+
active: "success",
|
|
9
|
+
approved: "success",
|
|
10
|
+
completed: "success",
|
|
11
|
+
confirmed: "success",
|
|
12
|
+
delivered: "success",
|
|
13
|
+
paid: "success",
|
|
14
|
+
published: "success",
|
|
15
|
+
succeeded: "success",
|
|
16
|
+
validated: "success",
|
|
17
|
+
verified: "success",
|
|
18
|
+
in_preparation: "warning",
|
|
19
|
+
in_progress: "warning",
|
|
20
|
+
out_for_delivery: "warning",
|
|
21
|
+
pending: "warning",
|
|
22
|
+
pending_email_verification: "warning",
|
|
23
|
+
pending_review: "warning",
|
|
24
|
+
processing: "warning",
|
|
25
|
+
submitted: "warning",
|
|
26
|
+
paused: "info",
|
|
27
|
+
purchased: "info",
|
|
28
|
+
scheduled: "info",
|
|
29
|
+
archived: "neutral",
|
|
30
|
+
cancelled: "neutral",
|
|
31
|
+
canceled: "neutral",
|
|
32
|
+
closed: "neutral",
|
|
33
|
+
draft: "neutral",
|
|
34
|
+
inactive: "neutral",
|
|
35
|
+
stopped: "neutral",
|
|
36
|
+
unknown: "neutral",
|
|
37
|
+
blocked: "destructive",
|
|
38
|
+
expired: "destructive",
|
|
39
|
+
failed: "destructive",
|
|
40
|
+
refunded: "destructive",
|
|
41
|
+
rejected: "destructive",
|
|
42
|
+
suspended: "destructive"
|
|
43
|
+
};
|
|
44
|
+
var NAJM_COLOR_TEXT_CLASSES = {
|
|
45
|
+
primary: "text-primary",
|
|
46
|
+
secondary: "text-secondary-foreground",
|
|
47
|
+
accent: "text-accent-foreground",
|
|
48
|
+
neutral: "text-muted-foreground",
|
|
49
|
+
info: "text-info",
|
|
50
|
+
success: "text-success",
|
|
51
|
+
warning: "text-warning",
|
|
52
|
+
destructive: "text-destructive"
|
|
53
|
+
};
|
|
54
|
+
function normalizeStatusToken(status) {
|
|
55
|
+
return status.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
56
|
+
}
|
|
57
|
+
function lookup(map, status, normalized) {
|
|
58
|
+
if (!map) return void 0;
|
|
59
|
+
return map[status] ?? map[normalized];
|
|
60
|
+
}
|
|
61
|
+
function findStatusColor(status, statusMap) {
|
|
62
|
+
if (!status) return void 0;
|
|
63
|
+
const normalized = normalizeStatusToken(status);
|
|
64
|
+
return lookup(statusMap, status, normalized) ?? lookup(NAJM_STATUS_COLORS, status, normalized);
|
|
65
|
+
}
|
|
66
|
+
function resolveStatusColor(status, statusMap, fallback = "neutral") {
|
|
67
|
+
return findStatusColor(status, statusMap) ?? fallback;
|
|
68
|
+
}
|
|
69
|
+
function colorTextClass(color) {
|
|
70
|
+
return NAJM_COLOR_TEXT_CLASSES[color] ?? "text-foreground";
|
|
71
|
+
}
|
|
72
|
+
function statusTextClass(status, statusMap, fallback) {
|
|
73
|
+
const color = findStatusColor(status, statusMap) ?? fallback;
|
|
74
|
+
return color ? colorTextClass(color) : "";
|
|
75
|
+
}
|
|
76
|
+
var NTableDefaultsContext = React2__default.createContext({});
|
|
77
|
+
function NTableDefaultsProvider({
|
|
78
|
+
children,
|
|
79
|
+
value
|
|
80
|
+
}) {
|
|
81
|
+
return /* @__PURE__ */ jsx(NTableDefaultsContext.Provider, { value, children });
|
|
82
|
+
}
|
|
83
|
+
function useNTableDefaults() {
|
|
84
|
+
return React2__default.useContext(NTableDefaultsContext);
|
|
85
|
+
}
|
|
86
|
+
function useResolvedPaginationLabels(own) {
|
|
87
|
+
const defaults = useNTableDefaults();
|
|
88
|
+
const inherited = defaults.paginationLabels;
|
|
89
|
+
return React2__default.useMemo(
|
|
90
|
+
() => ({ ...inherited, ...own }),
|
|
91
|
+
[inherited, own]
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
var NajmPreferencesContext = React2.createContext(null);
|
|
95
|
+
var DEFAULT_TIME_ZONE = "UTC";
|
|
96
|
+
function isValidTimeZone(value) {
|
|
97
|
+
try {
|
|
98
|
+
new Intl.DateTimeFormat(void 0, { timeZone: value });
|
|
99
|
+
return true;
|
|
100
|
+
} catch {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function defaultNormalizeTimeZone(value) {
|
|
105
|
+
return isValidTimeZone(value) ? value : DEFAULT_TIME_ZONE;
|
|
106
|
+
}
|
|
107
|
+
function applyTheme(theme) {
|
|
108
|
+
if (typeof document === "undefined") return;
|
|
109
|
+
document.documentElement.classList.toggle("dark", theme === "dark");
|
|
110
|
+
}
|
|
111
|
+
function applyTimeZone(timeZone) {
|
|
112
|
+
if (typeof document === "undefined") return;
|
|
113
|
+
document.documentElement.dataset.timeZone = timeZone;
|
|
114
|
+
}
|
|
115
|
+
function NajmPreferencesProvider({
|
|
116
|
+
children,
|
|
117
|
+
initialTheme = "light",
|
|
118
|
+
initialTimeZone = DEFAULT_TIME_ZONE,
|
|
119
|
+
onThemeChange,
|
|
120
|
+
onTimeZoneChange,
|
|
121
|
+
normalizeTimeZone = defaultNormalizeTimeZone
|
|
122
|
+
}) {
|
|
123
|
+
const [theme, setThemeState] = React2.useState(initialTheme);
|
|
124
|
+
const [timeZone, setTimeZoneState] = React2.useState(
|
|
125
|
+
() => normalizeTimeZone(initialTimeZone)
|
|
126
|
+
);
|
|
127
|
+
const onThemeChangeRef = React2.useRef(onThemeChange);
|
|
128
|
+
const onTimeZoneChangeRef = React2.useRef(onTimeZoneChange);
|
|
129
|
+
const normalizeRef = React2.useRef(normalizeTimeZone);
|
|
130
|
+
React2.useEffect(() => {
|
|
131
|
+
onThemeChangeRef.current = onThemeChange;
|
|
132
|
+
onTimeZoneChangeRef.current = onTimeZoneChange;
|
|
133
|
+
normalizeRef.current = normalizeTimeZone;
|
|
134
|
+
});
|
|
135
|
+
React2.useEffect(() => {
|
|
136
|
+
applyTheme(theme);
|
|
137
|
+
applyTimeZone(timeZone);
|
|
138
|
+
}, []);
|
|
139
|
+
const setTheme = React2.useCallback(async (next) => {
|
|
140
|
+
setThemeState(next);
|
|
141
|
+
applyTheme(next);
|
|
142
|
+
await onThemeChangeRef.current?.(next);
|
|
143
|
+
}, []);
|
|
144
|
+
const setTimeZone = React2.useCallback(async (next) => {
|
|
145
|
+
const normalized = normalizeRef.current(next);
|
|
146
|
+
setTimeZoneState(normalized);
|
|
147
|
+
applyTimeZone(normalized);
|
|
148
|
+
await onTimeZoneChangeRef.current?.(normalized);
|
|
149
|
+
}, []);
|
|
150
|
+
const value = React2.useMemo(
|
|
151
|
+
() => ({ theme, setTheme, timeZone, setTimeZone }),
|
|
152
|
+
[theme, setTheme, timeZone, setTimeZone]
|
|
153
|
+
);
|
|
154
|
+
return /* @__PURE__ */ jsx(NajmPreferencesContext.Provider, { value, children });
|
|
155
|
+
}
|
|
156
|
+
function useNajmPreferencesContext() {
|
|
157
|
+
return React2.useContext(NajmPreferencesContext);
|
|
158
|
+
}
|
|
159
|
+
function usePreferencesOrThrow(hook) {
|
|
160
|
+
const value = React2.useContext(NajmPreferencesContext);
|
|
161
|
+
if (!value) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
`${hook} must be rendered under a NajmUIProvider or NajmPreferencesProvider.`
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
function useNajmTheme() {
|
|
169
|
+
const { theme, setTheme } = usePreferencesOrThrow("useNajmTheme");
|
|
170
|
+
return React2.useMemo(() => ({ theme, setTheme }), [theme, setTheme]);
|
|
171
|
+
}
|
|
172
|
+
function useNajmTimeZone() {
|
|
173
|
+
const { timeZone, setTimeZone } = usePreferencesOrThrow("useNajmTimeZone");
|
|
174
|
+
return React2.useMemo(
|
|
175
|
+
() => ({ timeZone, setTimeZone }),
|
|
176
|
+
[timeZone, setTimeZone]
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/providers/paginationLabels.ts
|
|
181
|
+
var DEFAULT_PAGINATION_KEY_PREFIX = "common.pagination";
|
|
182
|
+
function buildPaginationLabels(t, prefix = DEFAULT_PAGINATION_KEY_PREFIX) {
|
|
183
|
+
const key = (field) => `${prefix}.${field}`;
|
|
184
|
+
return {
|
|
185
|
+
rowsPerPage: t(key("rowsPerPage")),
|
|
186
|
+
pagination: t(key("pagination")),
|
|
187
|
+
firstPage: t(key("firstPage")),
|
|
188
|
+
previousPage: t(key("previousPage")),
|
|
189
|
+
nextPage: t(key("nextPage")),
|
|
190
|
+
lastPage: t(key("lastPage")),
|
|
191
|
+
goToPage: (page) => t(key("goToPage"), { page }),
|
|
192
|
+
currentPage: (page) => t(key("currentPage"), { page }),
|
|
193
|
+
pageOf: (page, pageCount) => t(key("pageOf"), { page, pageCount }),
|
|
194
|
+
pageOfUnknown: (page) => t(key("pageOfUnknown"), { page }),
|
|
195
|
+
rowsSelected: (selected, total) => t(key("rowsSelected"), { selected, total })
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
var EMPTY_DESIGN = Object.freeze({
|
|
199
|
+
version: 1,
|
|
200
|
+
theme: {},
|
|
201
|
+
components: {}
|
|
202
|
+
});
|
|
203
|
+
var NajmDesignEditorContext = React2.createContext(null);
|
|
204
|
+
function useNajmDesignEditor() {
|
|
205
|
+
return React2.useContext(NajmDesignEditorContext);
|
|
206
|
+
}
|
|
207
|
+
function cloneDesign(design) {
|
|
208
|
+
return structuredClone(design);
|
|
209
|
+
}
|
|
210
|
+
function NajmDesignEditorProvider({
|
|
211
|
+
children,
|
|
212
|
+
design,
|
|
213
|
+
initialDesign
|
|
214
|
+
}) {
|
|
215
|
+
const [state, setState] = React2.useState(() => ({
|
|
216
|
+
committed: initialDesign ?? design ?? EMPTY_DESIGN,
|
|
217
|
+
draft: null
|
|
218
|
+
}));
|
|
219
|
+
const beginDraft = React2.useCallback(() => {
|
|
220
|
+
setState(
|
|
221
|
+
(current) => current.draft ? current : { ...current, draft: cloneDesign(current.committed) }
|
|
222
|
+
);
|
|
223
|
+
}, []);
|
|
224
|
+
const setDraft = React2.useCallback((next) => {
|
|
225
|
+
setState((current) => ({ ...current, draft: cloneDesign(next) }));
|
|
226
|
+
}, []);
|
|
227
|
+
const cancelDraft = React2.useCallback(() => {
|
|
228
|
+
setState(
|
|
229
|
+
(current) => current.draft === null ? current : { ...current, draft: null }
|
|
230
|
+
);
|
|
231
|
+
}, []);
|
|
232
|
+
const setCommitted = React2.useCallback((next) => {
|
|
233
|
+
setState(
|
|
234
|
+
(current) => current.committed === next && current.draft === null ? current : { committed: next, draft: null }
|
|
235
|
+
);
|
|
236
|
+
}, []);
|
|
237
|
+
const value = React2.useMemo(() => {
|
|
238
|
+
if (design) {
|
|
239
|
+
return {
|
|
240
|
+
design,
|
|
241
|
+
committed: design,
|
|
242
|
+
draft: null,
|
|
243
|
+
hasDraft: false,
|
|
244
|
+
beginDraft: noop,
|
|
245
|
+
setDraft: noop,
|
|
246
|
+
cancelDraft: noop,
|
|
247
|
+
setCommitted: noop
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
design: state.draft ?? state.committed,
|
|
252
|
+
committed: state.committed,
|
|
253
|
+
draft: state.draft,
|
|
254
|
+
hasDraft: state.draft !== null,
|
|
255
|
+
beginDraft,
|
|
256
|
+
setDraft,
|
|
257
|
+
cancelDraft,
|
|
258
|
+
setCommitted
|
|
259
|
+
};
|
|
260
|
+
}, [design, state, beginDraft, setDraft, cancelDraft, setCommitted]);
|
|
261
|
+
return /* @__PURE__ */ jsx(NajmDesignEditorContext.Provider, { value, children });
|
|
262
|
+
}
|
|
263
|
+
function noop() {
|
|
264
|
+
}
|
|
265
|
+
var NBadgeDefaultsContext = React2.createContext(null);
|
|
266
|
+
function NBadgeDefaultsProvider({
|
|
267
|
+
defaults,
|
|
268
|
+
t,
|
|
269
|
+
children
|
|
270
|
+
}) {
|
|
271
|
+
const value = React2.useMemo(
|
|
272
|
+
() => ({ defaults, t }),
|
|
273
|
+
[defaults, t]
|
|
274
|
+
);
|
|
275
|
+
return /* @__PURE__ */ jsx(NBadgeDefaultsContext.Provider, { value, children });
|
|
276
|
+
}
|
|
277
|
+
function useNBadgeDefaults() {
|
|
278
|
+
return React2.useContext(NBadgeDefaultsContext);
|
|
279
|
+
}
|
|
280
|
+
function resolveBadgeStatusLabel(status, defaults, t) {
|
|
281
|
+
if (!defaults) return void 0;
|
|
282
|
+
const normalized = normalizeStatusToken(status);
|
|
283
|
+
const literal = defaults.statusLabels?.[status] ?? defaults.statusLabels?.[normalized];
|
|
284
|
+
if (literal !== void 0) return literal;
|
|
285
|
+
const key = defaults.statusLabelKeys?.[status] ?? defaults.statusLabelKeys?.[normalized];
|
|
286
|
+
return key !== void 0 && t ? t(key) : void 0;
|
|
287
|
+
}
|
|
288
|
+
function mergeBadgeMaps(base, overrides) {
|
|
289
|
+
if (!base) return overrides;
|
|
290
|
+
if (!overrides) return base;
|
|
291
|
+
return { ...base, ...overrides };
|
|
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
|
+
}
|
|
347
|
+
function NajmUICore({
|
|
348
|
+
children,
|
|
349
|
+
className,
|
|
350
|
+
t,
|
|
351
|
+
paginationKeyPrefix = DEFAULT_PAGINATION_KEY_PREFIX,
|
|
352
|
+
tableDefaults,
|
|
353
|
+
badgeDefaults,
|
|
354
|
+
feedbackDefaults
|
|
355
|
+
}) {
|
|
356
|
+
const { theme } = useNajmTheme();
|
|
357
|
+
const design = useNajmDesignEditor()?.design ?? EMPTY_DESIGN;
|
|
358
|
+
const defaults = React2.useMemo(() => {
|
|
359
|
+
const translated = t ? buildPaginationLabels(t, paginationKeyPrefix) : void 0;
|
|
360
|
+
const overrides = tableDefaults?.paginationLabels;
|
|
361
|
+
const paginationLabels = translated || overrides ? { ...translated, ...overrides } : void 0;
|
|
362
|
+
return { ...tableDefaults, paginationLabels };
|
|
363
|
+
}, [t, paginationKeyPrefix, tableDefaults]);
|
|
364
|
+
const feedbackValue = React2.useMemo(
|
|
365
|
+
() => resolveFeedbackDefaultsValue(feedbackDefaults, t),
|
|
366
|
+
[feedbackDefaults, t]
|
|
367
|
+
);
|
|
368
|
+
return /* @__PURE__ */ jsx(
|
|
369
|
+
NajmDesignProvider,
|
|
370
|
+
{
|
|
371
|
+
config: design,
|
|
372
|
+
mode: theme,
|
|
373
|
+
className: cn("min-h-full", className),
|
|
374
|
+
children: /* @__PURE__ */ jsx(NTableDefaultsProvider, { value: defaults, children: /* @__PURE__ */ jsx(NBadgeDefaultsProvider, { defaults: badgeDefaults, t, children: /* @__PURE__ */ jsx(NFeedbackDefaultsProvider, { value: feedbackValue, children }) }) })
|
|
375
|
+
}
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
function NajmUIProvider({
|
|
379
|
+
children,
|
|
380
|
+
design,
|
|
381
|
+
initialDesign,
|
|
382
|
+
className,
|
|
383
|
+
t,
|
|
384
|
+
paginationKeyPrefix,
|
|
385
|
+
tableDefaults,
|
|
386
|
+
badgeDefaults,
|
|
387
|
+
feedbackDefaults,
|
|
388
|
+
initialTheme,
|
|
389
|
+
initialTimeZone,
|
|
390
|
+
onThemeChange,
|
|
391
|
+
onTimeZoneChange,
|
|
392
|
+
normalizeTimeZone
|
|
393
|
+
}) {
|
|
394
|
+
const outerPreferences = useNajmPreferencesContext();
|
|
395
|
+
const core = /* @__PURE__ */ jsx(NajmDesignEditorProvider, { design, initialDesign, children: /* @__PURE__ */ jsx(
|
|
396
|
+
NajmUICore,
|
|
397
|
+
{
|
|
398
|
+
className,
|
|
399
|
+
t,
|
|
400
|
+
paginationKeyPrefix,
|
|
401
|
+
tableDefaults,
|
|
402
|
+
badgeDefaults,
|
|
403
|
+
feedbackDefaults,
|
|
404
|
+
children
|
|
405
|
+
}
|
|
406
|
+
) });
|
|
407
|
+
if (outerPreferences) return core;
|
|
408
|
+
return /* @__PURE__ */ jsx(
|
|
409
|
+
NajmPreferencesProvider,
|
|
410
|
+
{
|
|
411
|
+
initialTheme,
|
|
412
|
+
initialTimeZone,
|
|
413
|
+
onThemeChange,
|
|
414
|
+
onTimeZoneChange,
|
|
415
|
+
normalizeTimeZone,
|
|
416
|
+
children: core
|
|
417
|
+
}
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// src/lib/imageSource.ts
|
|
422
|
+
var INLINE_SOURCE = /^(?:data|blob):/i;
|
|
423
|
+
function withSrcVersion(src, version) {
|
|
424
|
+
if (version === null || version === void 0 || version === "") return src;
|
|
425
|
+
if (INLINE_SOURCE.test(src)) return src;
|
|
426
|
+
const separator = src.includes("?") ? "&" : "?";
|
|
427
|
+
return `${src}${separator}v=${encodeURIComponent(String(version))}`;
|
|
428
|
+
}
|
|
429
|
+
function normalizeImageSources(candidates, version) {
|
|
430
|
+
const sources = [];
|
|
431
|
+
for (const candidate of candidates) {
|
|
432
|
+
const trimmed = candidate?.trim();
|
|
433
|
+
if (!trimmed) continue;
|
|
434
|
+
const stamped = withSrcVersion(trimmed, version);
|
|
435
|
+
if (!sources.includes(stamped)) sources.push(stamped);
|
|
436
|
+
}
|
|
437
|
+
return sources;
|
|
438
|
+
}
|
|
439
|
+
function selectImageSource(sources, failed) {
|
|
440
|
+
return sources.find((source) => !failed.includes(source));
|
|
441
|
+
}
|
|
442
|
+
var NO_FAILURES = [];
|
|
443
|
+
function useImageChain(sources) {
|
|
444
|
+
const key = JSON.stringify(sources);
|
|
445
|
+
const [state, setState] = React2.useState(() => ({
|
|
446
|
+
key,
|
|
447
|
+
failed: NO_FAILURES,
|
|
448
|
+
loaded: null
|
|
449
|
+
}));
|
|
450
|
+
const fresh = { key, failed: NO_FAILURES, loaded: null };
|
|
451
|
+
const current = state.key === key ? state : fresh;
|
|
452
|
+
if (state.key !== key) setState(fresh);
|
|
453
|
+
const active = selectImageSource(sources, current.failed);
|
|
454
|
+
const markLoaded = React2.useCallback(() => {
|
|
455
|
+
if (active === void 0) return;
|
|
456
|
+
setState(
|
|
457
|
+
(prev) => prev.key !== key || prev.loaded === active ? prev : { ...prev, loaded: active }
|
|
458
|
+
);
|
|
459
|
+
}, [key, active]);
|
|
460
|
+
const markFailed = React2.useCallback(() => {
|
|
461
|
+
if (active === void 0) return;
|
|
462
|
+
setState((prev) => {
|
|
463
|
+
if (prev.key !== key || prev.failed.includes(active)) return prev;
|
|
464
|
+
return {
|
|
465
|
+
...prev,
|
|
466
|
+
failed: [...prev.failed, active],
|
|
467
|
+
loaded: prev.loaded === active ? null : prev.loaded
|
|
468
|
+
};
|
|
469
|
+
});
|
|
470
|
+
}, [key, active]);
|
|
471
|
+
return {
|
|
472
|
+
src: active ?? sources[sources.length - 1],
|
|
473
|
+
exhausted: sources.length > 0 && active === void 0,
|
|
474
|
+
loaded: active !== void 0 && current.loaded === active,
|
|
475
|
+
markLoaded,
|
|
476
|
+
markFailed
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
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 };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { cn } from './chunk-KVZACF4G.mjs';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { createContext, useContext } from 'react';
|
|
4
|
+
import { OverlayScrollbars } from 'overlayscrollbars';
|
|
5
|
+
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
|
6
|
+
import { jsx } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
function assignRef(ref, node) {
|
|
9
|
+
if (!ref) return;
|
|
10
|
+
if (typeof ref === "function") ref(node);
|
|
11
|
+
else ref.current = node;
|
|
12
|
+
}
|
|
13
|
+
function applyViewportLayout(node, axis) {
|
|
14
|
+
node.style.width = "100%";
|
|
15
|
+
node.style.height = "100%";
|
|
16
|
+
node.style.minWidth = "0";
|
|
17
|
+
node.style.minHeight = "0";
|
|
18
|
+
node.style.overflowX = axis === "x" || axis === "both" ? "auto" : "hidden";
|
|
19
|
+
node.style.overflowY = axis === "y" || axis === "both" ? "auto" : "hidden";
|
|
20
|
+
}
|
|
21
|
+
function najmScrollOptions(axis, autoHide, options) {
|
|
22
|
+
return {
|
|
23
|
+
scrollbars: { theme: "os-theme-najm", autoHide, autoHideDelay: 500, clickScroll: true },
|
|
24
|
+
overflow: {
|
|
25
|
+
x: axis === "x" || axis === "both" ? "scroll" : "hidden",
|
|
26
|
+
y: axis === "y" || axis === "both" ? "scroll" : "hidden"
|
|
27
|
+
},
|
|
28
|
+
...options
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function useNajmScrollViewport({
|
|
32
|
+
axis = "y",
|
|
33
|
+
autoHide = "never",
|
|
34
|
+
options
|
|
35
|
+
} = {}) {
|
|
36
|
+
const hostRef = React.useRef(null);
|
|
37
|
+
const viewportRef = React.useRef(null);
|
|
38
|
+
React.useEffect(() => {
|
|
39
|
+
const target = hostRef.current;
|
|
40
|
+
const viewport = viewportRef.current;
|
|
41
|
+
if (!target || !viewport) return;
|
|
42
|
+
const instance = OverlayScrollbars(
|
|
43
|
+
{ target, elements: { viewport } },
|
|
44
|
+
najmScrollOptions(axis, autoHide, options)
|
|
45
|
+
);
|
|
46
|
+
const containWheel = (event) => event.stopPropagation();
|
|
47
|
+
viewport.addEventListener("wheel", containWheel, { passive: true });
|
|
48
|
+
return () => {
|
|
49
|
+
viewport.removeEventListener("wheel", containWheel);
|
|
50
|
+
instance.destroy();
|
|
51
|
+
};
|
|
52
|
+
}, [axis, autoHide, options]);
|
|
53
|
+
return { hostRef, viewportRef };
|
|
54
|
+
}
|
|
55
|
+
function NajmScroll({ className, axis = "y", autoHide = "never", viewportRef, events, options, element, children, style, ...props }) {
|
|
56
|
+
return /* @__PURE__ */ jsx(
|
|
57
|
+
OverlayScrollbarsComponent,
|
|
58
|
+
{
|
|
59
|
+
className: cn(className),
|
|
60
|
+
style: {
|
|
61
|
+
...style,
|
|
62
|
+
overflow: "hidden",
|
|
63
|
+
minHeight: 0,
|
|
64
|
+
minWidth: 0
|
|
65
|
+
},
|
|
66
|
+
element,
|
|
67
|
+
defer: true,
|
|
68
|
+
options: najmScrollOptions(axis, autoHide, options || void 0),
|
|
69
|
+
events: {
|
|
70
|
+
...events,
|
|
71
|
+
initialized: (instance, ...rest) => {
|
|
72
|
+
const viewport = instance.elements().viewport;
|
|
73
|
+
applyViewportLayout(viewport, axis);
|
|
74
|
+
assignRef(viewportRef, viewport);
|
|
75
|
+
events?.initialized?.(instance, ...rest);
|
|
76
|
+
},
|
|
77
|
+
updated: (instance, ...rest) => {
|
|
78
|
+
applyViewportLayout(instance.elements().viewport, axis);
|
|
79
|
+
events?.updated?.(instance, ...rest);
|
|
80
|
+
},
|
|
81
|
+
destroyed: (instance, ...rest) => {
|
|
82
|
+
assignRef(viewportRef, null);
|
|
83
|
+
events?.destroyed?.(instance, ...rest);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
...props,
|
|
87
|
+
children
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
var TableStoreContext = createContext(null);
|
|
92
|
+
var useTableStore = { use: {} };
|
|
93
|
+
var handler = {
|
|
94
|
+
get: (_, prop) => () => {
|
|
95
|
+
const store = useContext(TableStoreContext);
|
|
96
|
+
if (!store) throw new Error("useTableStore must be used within NTable");
|
|
97
|
+
return store.use[prop]();
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
useTableStore.use = new Proxy({}, handler);
|
|
101
|
+
function formatJsonValue(value) {
|
|
102
|
+
if (typeof value === "string") return value;
|
|
103
|
+
try {
|
|
104
|
+
return JSON.stringify(value ?? null, null, 2) ?? String(value);
|
|
105
|
+
} catch {
|
|
106
|
+
return String(value);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function NTableJson() {
|
|
110
|
+
const viewMode = useTableStore.use.viewMode();
|
|
111
|
+
const renderJson = useTableStore.use.renderJson();
|
|
112
|
+
const jsonValue = useTableStore.use.jsonValue();
|
|
113
|
+
if (viewMode !== "json") return null;
|
|
114
|
+
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) }) }) });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export { NTableJson, NajmScroll, TableStoreContext, useNajmScrollViewport, useTableStore };
|