najm-kit 2.6.3 → 2.6.4

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.
@@ -0,0 +1,173 @@
1
+ import { NajmDesignProvider } from './chunk-YBM5CTE6.mjs';
2
+ import * as React2 from 'react';
3
+ import React2__default from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ var NTableDefaultsContext = React2__default.createContext({});
7
+ function NTableDefaultsProvider({
8
+ children,
9
+ value
10
+ }) {
11
+ return /* @__PURE__ */ jsx(NTableDefaultsContext.Provider, { value, children });
12
+ }
13
+ function useNTableDefaults() {
14
+ return React2__default.useContext(NTableDefaultsContext);
15
+ }
16
+ function useResolvedPaginationLabels(own) {
17
+ const defaults = useNTableDefaults();
18
+ const inherited = defaults.paginationLabels;
19
+ return React2__default.useMemo(
20
+ () => ({ ...inherited, ...own }),
21
+ [inherited, own]
22
+ );
23
+ }
24
+ var NajmPreferencesContext = React2.createContext(null);
25
+ var DEFAULT_TIME_ZONE = "UTC";
26
+ function applyTheme(theme) {
27
+ if (typeof document === "undefined") return;
28
+ document.documentElement.classList.toggle("dark", theme === "dark");
29
+ }
30
+ function applyTimeZone(timeZone) {
31
+ if (typeof document === "undefined") return;
32
+ document.documentElement.dataset.timeZone = timeZone;
33
+ }
34
+ function NajmPreferencesProvider({
35
+ children,
36
+ initialTheme = "light",
37
+ initialTimeZone = DEFAULT_TIME_ZONE,
38
+ onThemeChange,
39
+ onTimeZoneChange,
40
+ normalizeTimeZone
41
+ }) {
42
+ const [theme, setThemeState] = React2.useState(initialTheme);
43
+ const [timeZone, setTimeZoneState] = React2.useState(
44
+ () => normalizeTimeZone ? normalizeTimeZone(initialTimeZone) : initialTimeZone
45
+ );
46
+ const onThemeChangeRef = React2.useRef(onThemeChange);
47
+ const onTimeZoneChangeRef = React2.useRef(onTimeZoneChange);
48
+ const normalizeRef = React2.useRef(normalizeTimeZone);
49
+ React2.useEffect(() => {
50
+ onThemeChangeRef.current = onThemeChange;
51
+ onTimeZoneChangeRef.current = onTimeZoneChange;
52
+ normalizeRef.current = normalizeTimeZone;
53
+ });
54
+ React2.useEffect(() => {
55
+ applyTheme(theme);
56
+ applyTimeZone(timeZone);
57
+ }, []);
58
+ const setTheme = React2.useCallback(async (next) => {
59
+ setThemeState(next);
60
+ applyTheme(next);
61
+ await onThemeChangeRef.current?.(next);
62
+ }, []);
63
+ const setTimeZone = React2.useCallback(async (next) => {
64
+ const normalized = normalizeRef.current ? normalizeRef.current(next) : next;
65
+ setTimeZoneState(normalized);
66
+ applyTimeZone(normalized);
67
+ await onTimeZoneChangeRef.current?.(normalized);
68
+ }, []);
69
+ const value = React2.useMemo(
70
+ () => ({ theme, setTheme, timeZone, setTimeZone }),
71
+ [theme, setTheme, timeZone, setTimeZone]
72
+ );
73
+ return /* @__PURE__ */ jsx(NajmPreferencesContext.Provider, { value, children });
74
+ }
75
+ function useNajmPreferencesContext() {
76
+ return React2.useContext(NajmPreferencesContext);
77
+ }
78
+ function usePreferencesOrThrow(hook) {
79
+ const value = React2.useContext(NajmPreferencesContext);
80
+ if (!value) {
81
+ throw new Error(
82
+ `${hook} must be rendered under a NajmUIProvider or NajmPreferencesProvider.`
83
+ );
84
+ }
85
+ return value;
86
+ }
87
+ function useNajmTheme() {
88
+ const { theme, setTheme } = usePreferencesOrThrow("useNajmTheme");
89
+ return React2.useMemo(() => ({ theme, setTheme }), [theme, setTheme]);
90
+ }
91
+ function useNajmTimeZone() {
92
+ const { timeZone, setTimeZone } = usePreferencesOrThrow("useNajmTimeZone");
93
+ return React2.useMemo(
94
+ () => ({ timeZone, setTimeZone }),
95
+ [timeZone, setTimeZone]
96
+ );
97
+ }
98
+
99
+ // src/providers/paginationLabels.ts
100
+ var DEFAULT_PAGINATION_KEY_PREFIX = "common.pagination";
101
+ function buildPaginationLabels(t, prefix = DEFAULT_PAGINATION_KEY_PREFIX) {
102
+ const key = (field) => `${prefix}.${field}`;
103
+ return {
104
+ rowsPerPage: t(key("rowsPerPage")),
105
+ pagination: t(key("pagination")),
106
+ firstPage: t(key("firstPage")),
107
+ previousPage: t(key("previousPage")),
108
+ nextPage: t(key("nextPage")),
109
+ lastPage: t(key("lastPage")),
110
+ goToPage: (page) => t(key("goToPage"), { page }),
111
+ currentPage: (page) => t(key("currentPage"), { page }),
112
+ pageOf: (page, pageCount) => t(key("pageOf"), { page, pageCount }),
113
+ pageOfUnknown: (page) => t(key("pageOfUnknown"), { page }),
114
+ rowsSelected: (selected, total) => t(key("rowsSelected"), { selected, total })
115
+ };
116
+ }
117
+ function NajmUICore({
118
+ children,
119
+ design,
120
+ className,
121
+ t,
122
+ paginationKeyPrefix = DEFAULT_PAGINATION_KEY_PREFIX,
123
+ tableDefaults
124
+ }) {
125
+ const { theme } = useNajmTheme();
126
+ const defaults = React2.useMemo(() => {
127
+ const translated = t ? buildPaginationLabels(t, paginationKeyPrefix) : void 0;
128
+ const overrides = tableDefaults?.paginationLabels;
129
+ const paginationLabels = translated || overrides ? { ...translated, ...overrides } : void 0;
130
+ return { ...tableDefaults, paginationLabels };
131
+ }, [t, paginationKeyPrefix, tableDefaults]);
132
+ return /* @__PURE__ */ jsx(NajmDesignProvider, { config: design, mode: theme, className, children: /* @__PURE__ */ jsx(NTableDefaultsProvider, { value: defaults, children }) });
133
+ }
134
+ function NajmUIProvider({
135
+ children,
136
+ design,
137
+ className,
138
+ t,
139
+ paginationKeyPrefix,
140
+ tableDefaults,
141
+ initialTheme,
142
+ initialTimeZone,
143
+ onThemeChange,
144
+ onTimeZoneChange,
145
+ normalizeTimeZone
146
+ }) {
147
+ const outerPreferences = useNajmPreferencesContext();
148
+ const core = /* @__PURE__ */ jsx(
149
+ NajmUICore,
150
+ {
151
+ design,
152
+ className,
153
+ t,
154
+ paginationKeyPrefix,
155
+ tableDefaults,
156
+ children
157
+ }
158
+ );
159
+ if (outerPreferences) return core;
160
+ return /* @__PURE__ */ jsx(
161
+ NajmPreferencesProvider,
162
+ {
163
+ initialTheme,
164
+ initialTimeZone,
165
+ onThemeChange,
166
+ onTimeZoneChange,
167
+ normalizeTimeZone,
168
+ children: core
169
+ }
170
+ );
171
+ }
172
+
173
+ export { DEFAULT_PAGINATION_KEY_PREFIX, DEFAULT_TIME_ZONE, NTableDefaultsProvider, NajmPreferencesProvider, NajmUIProvider, buildPaginationLabels, useNTableDefaults, useNajmPreferencesContext, useNajmTheme, useNajmTimeZone, useResolvedPaginationLabels };
@@ -0,0 +1,366 @@
1
+ import * as React from 'react';
2
+ import { Slot } from '@radix-ui/react-slot';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ // src/theme/presets/modes.ts
6
+ var lightMode = {
7
+ background: "oklch(1 0 0)",
8
+ foreground: "oklch(0.1445 0 0)",
9
+ card: "oklch(1 0 0)",
10
+ "card-foreground": "oklch(0.1445 0 0)",
11
+ popover: "oklch(1 0 0)",
12
+ "popover-foreground": "oklch(0.1445 0 0)",
13
+ secondary: "oklch(0.9703 0 0)",
14
+ "secondary-foreground": "oklch(0.2044 0 0)",
15
+ tertiary: "oklch(0.9676 0.007 247.897)",
16
+ "tertiary-foreground": "oklch(0.3138 0.0453 249.447)",
17
+ muted: "oklch(0.9703 0 0)",
18
+ "muted-foreground": "oklch(0.5555 0 0)",
19
+ accent: "oklch(0.9703 0 0)",
20
+ "accent-foreground": "oklch(0.2044 0 0)",
21
+ destructive: "oklch(0.6368 0.2078 25.326)",
22
+ "destructive-foreground": "oklch(0.9848 0 0)",
23
+ border: "oklch(0.9219 0 0)",
24
+ input: "oklch(0.9219 0 0)",
25
+ radius: "0.5rem",
26
+ sidebar: "oklch(0.985 0 0)",
27
+ "sidebar-foreground": "oklch(0.1445 0 0)",
28
+ "sidebar-primary": "oklch(0.2228 0.0043 286.044)",
29
+ "sidebar-primary-foreground": "oklch(0.9848 0 0)",
30
+ "sidebar-accent": "oklch(0.9703 0 0)",
31
+ "sidebar-accent-foreground": "oklch(0.2044 0 0)",
32
+ "sidebar-border": "oklch(0.9219 0 0)",
33
+ "sidebar-ring": "oklch(0.2228 0.0043 286.044)"
34
+ };
35
+ var darkMode = {
36
+ background: "oklch(0.1417 0.0044 285.819)",
37
+ foreground: "oklch(0.9683 0.0014 286.375)",
38
+ card: "oklch(0.1872 0.0066 285.748)",
39
+ "card-foreground": "oklch(0.9683 0.0014 286.375)",
40
+ popover: "oklch(0.1872 0.0066 285.748)",
41
+ "popover-foreground": "oklch(0.9683 0.0014 286.375)",
42
+ secondary: "oklch(0.2313 0.007 285.839)",
43
+ "secondary-foreground": "oklch(0.9203 0.0034 286.332)",
44
+ tertiary: "oklch(0.3138 0.0453 249.447)",
45
+ "tertiary-foreground": "oklch(0.8529 0.0324 248.208)",
46
+ muted: "oklch(0.2313 0.007 285.839)",
47
+ "muted-foreground": "oklch(0.6255 0.0171 285.896)",
48
+ accent: "oklch(0.2313 0.007 285.839)",
49
+ "accent-foreground": "oklch(0.9683 0.0014 286.375)",
50
+ destructive: "oklch(0.6356 0.2082 25.378)",
51
+ "destructive-foreground": "oklch(1 0 0)",
52
+ border: "oklch(0.262 0.0085 285.799)",
53
+ input: "oklch(0.262 0.0085 285.799)",
54
+ radius: "0.5rem",
55
+ sidebar: "oklch(0.205 0 0)",
56
+ "sidebar-foreground": "oklch(0.9683 0.0014 286.375)",
57
+ "sidebar-primary": "oklch(0.4865 0.2423 291.866)",
58
+ "sidebar-primary-foreground": "oklch(0.9848 0 0)",
59
+ "sidebar-accent": "oklch(0.2313 0.007 285.839)",
60
+ "sidebar-accent-foreground": "oklch(0.9683 0.0014 286.375)",
61
+ "sidebar-border": "oklch(0.262 0.0085 285.799)",
62
+ "sidebar-ring": "oklch(0.4865 0.2423 291.866)"
63
+ };
64
+
65
+ // src/theme/presets/accents.ts
66
+ var accents = {
67
+ neutral: {
68
+ primary: "oklch(0.2228 0.0043 286.044)",
69
+ "primary-foreground": "oklch(0.9848 0 0)",
70
+ ring: "oklch(0.2228 0.0043 286.044)",
71
+ accent: "oklch(0.2747 0.006 286.001)",
72
+ "accent-foreground": "oklch(0.9848 0 0)",
73
+ "sidebar-primary": "oklch(0.2228 0.0043 286.044)",
74
+ "sidebar-ring": "oklch(0.2228 0.0043 286.044)"
75
+ },
76
+ emerald: {
77
+ primary: "oklch(0.6902 0.1481 162.368)",
78
+ "primary-foreground": "oklch(1 0 0)",
79
+ ring: "oklch(0.6902 0.1481 162.368)",
80
+ accent: "oklch(0.3519 0.0714 164.26)",
81
+ "accent-foreground": "oklch(0.9131 0.0924 171.145)",
82
+ "sidebar-primary": "oklch(0.6902 0.1481 162.368)",
83
+ "sidebar-ring": "oklch(0.6902 0.1481 162.368)"
84
+ },
85
+ green: {
86
+ primary: "oklch(0.7205 0.192 149.493)",
87
+ "primary-foreground": "oklch(1 0 0)",
88
+ ring: "oklch(0.7205 0.192 149.493)",
89
+ accent: "oklch(0.333 0.0811 150.922)",
90
+ "accent-foreground": "oklch(0.8958 0.096 156.121)",
91
+ "sidebar-primary": "oklch(0.7205 0.192 149.493)",
92
+ "sidebar-ring": "oklch(0.7205 0.192 149.493)"
93
+ },
94
+ slate: {
95
+ primary: "oklch(0.6227 0.0463 256.82)",
96
+ "primary-foreground": "oklch(1 0 0)",
97
+ ring: "oklch(0.6227 0.0463 256.82)",
98
+ accent: "oklch(0.3115 0.0245 256.824)",
99
+ "accent-foreground": "oklch(0.8784 0.0141 256.711)",
100
+ "sidebar-primary": "oklch(0.6227 0.0463 256.82)",
101
+ "sidebar-ring": "oklch(0.6227 0.0463 256.82)"
102
+ },
103
+ blue: {
104
+ primary: "oklch(0.6261 0.1859 259.596)",
105
+ "primary-foreground": "oklch(1 0 0)",
106
+ ring: "oklch(0.6261 0.1859 259.596)",
107
+ accent: "oklch(0.2941 0.1092 259.917)",
108
+ "accent-foreground": "oklch(0.8064 0.0902 259.76)",
109
+ "sidebar-primary": "oklch(0.6261 0.1859 259.596)",
110
+ "sidebar-ring": "oklch(0.6261 0.1859 259.596)"
111
+ },
112
+ violet: {
113
+ primary: "oklch(0.4865 0.2423 291.866)",
114
+ "primary-foreground": "oklch(1 0 0)",
115
+ ring: "oklch(0.6016 0.2214 292.234)",
116
+ accent: "oklch(0.2467 0.109 294.41)",
117
+ "accent-foreground": "oklch(0.7817 0.1036 301.636)",
118
+ "sidebar-primary": "oklch(0.4865 0.2423 291.866)",
119
+ "sidebar-ring": "oklch(0.6016 0.2214 292.234)"
120
+ }
121
+ };
122
+
123
+ // src/theme/presets/compose.ts
124
+ function lightAccentFromPrimary(primary = "") {
125
+ const m = primary.trim().match(/^oklch\(\s*([\d.]+)\s+([\d.]+)\s+([\d.]+)\s*\)$/i);
126
+ if (!m) return { accent: "oklch(0.95 0 0)", "accent-foreground": "oklch(0.42 0 0)" };
127
+ const c = Number(m[2]);
128
+ const h = Number(m[3]);
129
+ const tint = Math.min(c, 0.05);
130
+ const fg = Math.min(c, 0.12);
131
+ return {
132
+ accent: `oklch(0.95 ${tint} ${h})`,
133
+ "accent-foreground": `oklch(0.42 ${fg} ${h})`
134
+ };
135
+ }
136
+ function composePreset(mode, accent) {
137
+ const base = mode === "dark" ? darkMode : lightMode;
138
+ const accentTokens = accents[accent];
139
+ if (mode === "light") {
140
+ const { accent: _a, "accent-foreground": _af, ...brandTokens } = accentTokens;
141
+ return { ...base, ...brandTokens, ...lightAccentFromPrimary(brandTokens.primary) };
142
+ }
143
+ return { ...base, ...accentTokens };
144
+ }
145
+ var PRESET_MAP = {
146
+ light: { mode: "light", accent: "neutral" },
147
+ dark: { mode: "dark", accent: "neutral" },
148
+ "dark-emerald": { mode: "dark", accent: "emerald" },
149
+ "dark-green": { mode: "dark", accent: "green" },
150
+ "dark-slate": { mode: "dark", accent: "slate" },
151
+ "dark-blue": { mode: "dark", accent: "blue" },
152
+ "dark-violet": { mode: "dark", accent: "violet" }
153
+ };
154
+ function resolvePreset(preset) {
155
+ const { mode, accent } = PRESET_MAP[preset];
156
+ return composePreset(mode, accent);
157
+ }
158
+ var ACCENT_KEYS = /* @__PURE__ */ new Set([
159
+ "primary",
160
+ "primary-foreground",
161
+ "ring",
162
+ "accent",
163
+ "accent-foreground",
164
+ "sidebar-primary",
165
+ "sidebar-ring"
166
+ ]);
167
+ function tokensToStyle(tokens, accentOnly) {
168
+ const style = {};
169
+ for (const [key, value] of Object.entries(tokens)) {
170
+ if (value && (!accentOnly || ACCENT_KEYS.has(key))) {
171
+ style[`--${key}`] = value;
172
+ }
173
+ }
174
+ return style;
175
+ }
176
+ var RADIUS_TOKENS = [
177
+ "--radius-xs",
178
+ "--radius-sm",
179
+ "--radius-md",
180
+ "--radius-lg",
181
+ "--radius-xl",
182
+ "--radius-2xl",
183
+ "--radius-3xl",
184
+ "--radius-4xl"
185
+ ];
186
+ function radiusToStyle(radius) {
187
+ const style = { "--radius": radius };
188
+ for (const key of RADIUS_TOKENS) style[key] = "var(--radius)";
189
+ return style;
190
+ }
191
+ function resolveThemeTokens({
192
+ preset,
193
+ mode,
194
+ accent,
195
+ explicitTokens,
196
+ configTokens,
197
+ configMode,
198
+ overrides
199
+ }) {
200
+ if (explicitTokens) return explicitTokens;
201
+ const tokenMode = mode ?? configMode;
202
+ const modeOverrides = tokenMode ? overrides?.[tokenMode] : void 0;
203
+ const tokensMatchMode = !configMode || !tokenMode || configMode === tokenMode;
204
+ const scopedTokens = tokensMatchMode ? configTokens : void 0;
205
+ if (preset) {
206
+ return { ...resolvePreset(preset), ...scopedTokens ?? {}, ...modeOverrides ?? {} };
207
+ }
208
+ if (tokenMode) {
209
+ return {
210
+ ...composePreset(tokenMode, accent ?? "neutral"),
211
+ ...scopedTokens ?? {},
212
+ ...modeOverrides ?? {}
213
+ };
214
+ }
215
+ if (scopedTokens || modeOverrides) return { ...scopedTokens ?? {}, ...modeOverrides ?? {} };
216
+ return null;
217
+ }
218
+ var NajmThemeDepthContext = React.createContext(0);
219
+ var NajmThemeModeContext = React.createContext(void 0);
220
+ function useNajmThemeMode() {
221
+ return React.useContext(NajmThemeModeContext);
222
+ }
223
+ var NajmThemeContainerCtx = React.createContext(null);
224
+ var DEFAULT_APPEARANCE = {};
225
+ var NajmAppearanceContext = React.createContext(DEFAULT_APPEARANCE);
226
+ function useNajmAppearance() {
227
+ return React.useContext(NajmAppearanceContext);
228
+ }
229
+ function NajmThemeProvider({
230
+ config,
231
+ preset,
232
+ mode,
233
+ accent,
234
+ tokens,
235
+ accentOnly,
236
+ appearance,
237
+ radius,
238
+ className,
239
+ asChild,
240
+ children
241
+ }) {
242
+ const depth = React.useContext(NajmThemeDepthContext);
243
+ const parentMode = React.useContext(NajmThemeModeContext);
244
+ const parentAppearance = React.useContext(NajmAppearanceContext);
245
+ const effectivePreset = preset ?? config?.preset;
246
+ const effectiveMode = mode ?? config?.mode;
247
+ const effectiveAccent = accent ?? config?.accent;
248
+ const effectiveAccentOnly = accentOnly ?? config?.accentOnly;
249
+ const effectiveRadius = radius ?? config?.radius;
250
+ const effectiveBorderWidth = appearance?.borderWidth ?? config?.appearance?.borderWidth;
251
+ const resolved = React.useMemo(() => {
252
+ return resolveThemeTokens({
253
+ preset: effectivePreset,
254
+ mode: effectiveMode,
255
+ accent: effectiveAccent,
256
+ explicitTokens: tokens,
257
+ configTokens: config?.tokens,
258
+ configMode: config?.mode,
259
+ overrides: config?.overrides
260
+ });
261
+ }, [
262
+ effectivePreset,
263
+ effectiveMode,
264
+ effectiveAccent,
265
+ tokens,
266
+ config?.tokens,
267
+ config?.mode,
268
+ config?.overrides
269
+ ]);
270
+ const style = React.useMemo(
271
+ () => {
272
+ const tokenStyle = resolved ? tokensToStyle(resolved, effectiveAccentOnly) : void 0;
273
+ const radiusStyle = effectiveRadius !== void 0 ? radiusToStyle(effectiveRadius) : void 0;
274
+ const borderWidthStyle = effectiveBorderWidth !== void 0 ? { "--border-width": effectiveBorderWidth } : void 0;
275
+ if (!tokenStyle && !radiusStyle && !borderWidthStyle) return void 0;
276
+ return { ...tokenStyle, ...radiusStyle, ...borderWidthStyle };
277
+ },
278
+ [resolved, effectiveAccentOnly, effectiveRadius, effectiveBorderWidth]
279
+ );
280
+ const Comp = asChild ? Slot : "div";
281
+ const [container, setContainer] = React.useState(null);
282
+ const containerRef = React.useRef(null);
283
+ const handleContainerRef = React.useCallback((node) => {
284
+ if (containerRef.current === node) return;
285
+ containerRef.current = node;
286
+ setContainer(node);
287
+ }, []);
288
+ const resolvedAppearance = React.useMemo(
289
+ () => ({ ...parentAppearance, ...config?.appearance ?? {}, ...appearance ?? {} }),
290
+ [parentAppearance, config?.appearance, appearance]
291
+ );
292
+ return /* @__PURE__ */ jsx(NajmThemeDepthContext.Provider, { value: depth + 1, children: /* @__PURE__ */ jsx(NajmThemeModeContext.Provider, { value: effectiveMode ?? parentMode, children: /* @__PURE__ */ jsx(NajmAppearanceContext.Provider, { value: resolvedAppearance, children: /* @__PURE__ */ jsx(NajmThemeContainerCtx.Provider, { value: container, children: /* @__PURE__ */ jsx(
293
+ Comp,
294
+ {
295
+ ref: handleContainerRef,
296
+ suppressHydrationWarning: true,
297
+ "data-najm-theme": effectivePreset ?? `${effectiveMode ?? "light"}-${effectiveAccent ?? "neutral"}`,
298
+ className,
299
+ style,
300
+ children
301
+ }
302
+ ) }) }) }) });
303
+ }
304
+ var NajmDesignContext = React.createContext({
305
+ components: {}
306
+ });
307
+ function useNajmDesign() {
308
+ return React.useContext(NajmDesignContext);
309
+ }
310
+ function useNajmComponentStyle(name) {
311
+ const { components } = useNajmDesign();
312
+ return components[name];
313
+ }
314
+ var SCALE_FACTOR = {
315
+ compact: "0.95",
316
+ default: "1",
317
+ comfortable: "1.05"
318
+ };
319
+ function typographyToStyle(t) {
320
+ const style = {};
321
+ if (t.fontSans) style["--font-sans"] = t.fontSans;
322
+ if (t.fontHeading) style["--font-heading"] = t.fontHeading;
323
+ if (t.fontMono) style["--font-mono"] = t.fontMono;
324
+ if (t.baseSize) style["--font-size-base"] = t.baseSize;
325
+ if (t.lineHeight) style["--line-height-base"] = t.lineHeight;
326
+ if (t.letterSpacing) style["--letter-spacing-base"] = t.letterSpacing;
327
+ if (t.scale) style["--font-scale"] = SCALE_FACTOR[t.scale];
328
+ return style;
329
+ }
330
+ function layoutToStyle(layout) {
331
+ const style = {};
332
+ if (layout.pageGutter) style["--page-gutter"] = layout.pageGutter;
333
+ if (layout.sectionGap) style["--section-gap"] = layout.sectionGap;
334
+ return style;
335
+ }
336
+ function NajmDesignProvider({
337
+ config,
338
+ mode,
339
+ className,
340
+ children
341
+ }) {
342
+ const contextValue = React.useMemo(
343
+ () => ({ components: config.components ?? {}, typography: config.typography, layout: config.layout }),
344
+ [config.components, config.typography, config.layout]
345
+ );
346
+ const typographyStyle = React.useMemo(
347
+ () => config.typography ? typographyToStyle(config.typography) : void 0,
348
+ [config.typography]
349
+ );
350
+ const layoutStyle = React.useMemo(
351
+ () => config.layout ? layoutToStyle(config.layout) : void 0,
352
+ [config.layout]
353
+ );
354
+ const providerStyle = React.useMemo(
355
+ () => ({ ...layoutStyle ?? {}, ...typographyStyle ?? {} }),
356
+ [layoutStyle, typographyStyle]
357
+ );
358
+ return /* @__PURE__ */ jsx(NajmDesignContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(NajmThemeProvider, { config: config.theme, mode, className, children: layoutStyle || typographyStyle ? (
359
+ // `display: contents` lets design CSS variables cascade to
360
+ // children without introducing a layout box that would break height
361
+ // chains (e.g. h-full) in the consuming app.
362
+ /* @__PURE__ */ jsx("div", { style: { display: "contents", ...providerStyle }, "data-najm-design-vars": "", children })
363
+ ) : children }) });
364
+ }
365
+
366
+ export { NajmDesignProvider, NajmThemeContainerCtx, NajmThemeProvider, composePreset, resolvePreset, useNajmAppearance, useNajmComponentStyle, useNajmDesign, useNajmThemeMode };