najm-kit 2.11.13 → 2.11.14

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,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import React__default from 'react';
3
- import { e as NajmMode, a as NajmDesignConfig } from './design-types-Rkpt8Pg1.js';
3
+ import { b as NajmMode, N as NajmDesignConfig } from './design-types-DffH_9XC.js';
4
4
  import { b as NTablePaginationLabels, N as NajmTranslate } from './paginationLabels-dZLSNxfo.js';
5
5
  import * as class_variance_authority_types from 'class-variance-authority/types';
6
6
  import { VariantProps } from 'class-variance-authority';
@@ -3,11 +3,11 @@ import { Translations } from 'najm-i18n';
3
3
  import { F as FormDevToolsOptions, N as NBrandingInput } from '../NNotFoundState-CgU76llk.js';
4
4
  export { a as NEmptyState, b as NEmptyStateProps, c as NErrorState, d as NErrorStateProps, e as NFeedbackSurface, f as NForbiddenState, g as NForbiddenStateProps, h as NLoadingState, i as NLoadingStateProps, j as NNotFoundState, k as NNotFoundStateProps } from '../NNotFoundState-CgU76llk.js';
5
5
  import { NajmNextUIProviderProps } from './next.js';
6
- export { D as DEFAULT_FEEDBACK_KEY_PREFIX, F as FeedbackKey, N as NFeedbackDefaults, a as NFeedbackLabelKeys, b as NFeedbackLabels } from '../NajmUIProvider-DTyRrukg.js';
6
+ export { D as DEFAULT_FEEDBACK_KEY_PREFIX, F as FeedbackKey, N as NFeedbackDefaults, a as NFeedbackLabelKeys, b as NFeedbackLabels } from '../NajmUIProvider-BwL5HFIV.js';
7
7
  import 'zod';
8
8
  import 'lucide-react';
9
9
  import 'next/image';
10
- import '../design-types-Rkpt8Pg1.js';
10
+ import '../design-types-DffH_9XC.js';
11
11
  import '../paginationLabels-dZLSNxfo.js';
12
12
  import 'class-variance-authority/types';
13
13
  import 'class-variance-authority';
@@ -1,7 +1,7 @@
1
1
  import React__default from 'react';
2
2
  import { ImageProps } from 'next/image';
3
- import { c as NajmUIProviderProps } from '../NajmUIProvider-DTyRrukg.js';
4
- import '../design-types-Rkpt8Pg1.js';
3
+ import { c as NajmUIProviderProps } from '../NajmUIProvider-BwL5HFIV.js';
4
+ import '../design-types-DffH_9XC.js';
5
5
  import '../paginationLabels-dZLSNxfo.js';
6
6
  import 'class-variance-authority/types';
7
7
  import 'class-variance-authority';
@@ -0,0 +1,28 @@
1
+ // src/lib/timeZones.ts
2
+ var NAJM_TIME_ZONES = [
3
+ "UTC",
4
+ "Atlantic/Azores",
5
+ "America/Los_Angeles",
6
+ "America/Denver",
7
+ "America/Chicago",
8
+ "America/New_York",
9
+ "America/Sao_Paulo",
10
+ "Pacific/Honolulu",
11
+ "Europe/London",
12
+ "Europe/Paris",
13
+ "Africa/Casablanca",
14
+ "Africa/Tunis",
15
+ "Africa/Cairo",
16
+ "Africa/Nairobi",
17
+ "Asia/Riyadh",
18
+ "Asia/Dubai",
19
+ "Asia/Kolkata",
20
+ "Asia/Bangkok",
21
+ "Asia/Shanghai",
22
+ "Asia/Tokyo",
23
+ "Australia/Sydney",
24
+ "Pacific/Auckland"
25
+ ];
26
+ var NAJM_DEFAULT_TIME_ZONE = "UTC";
27
+
28
+ export { NAJM_DEFAULT_TIME_ZONE, NAJM_TIME_ZONES };
@@ -1,4 +1,4 @@
1
- import { a as NajmDesignConfig, d as NajmVariantStyle } from './design-types-Rkpt8Pg1.js';
1
+ import { N as NajmDesignConfig, a as NajmVariantStyle } from './design-types-DffH_9XC.js';
2
2
 
3
3
  /** Keeps authored TypeScript design objects type-checked without changing them. */
4
4
  declare function defineNajmDesignConfig(config: NajmDesignConfig): NajmDesignConfig;
@@ -156,4 +156,4 @@ declare const NAJM_COMPONENT_NAMES: readonly NajmComponentName[];
156
156
  declare const RADIUS_VALUE_MAP: Record<string, string>;
157
157
  declare function resolveRadiusValue(radius: NajmComponentRadius | undefined): string | undefined;
158
158
 
159
- export { type NajmComponentThemeConfig as N, RADIUS_VALUE_MAP as R, type NajmDesignConfig as a, type NajmLayoutConfig as b, type NajmTypographyConfig as c, type NajmVariantStyle as d, type NajmMode as e, type NajmThemeProviderProps as f, type NajmAppearance as g, type NajmThemeConfig as h, type NajmAccent as i, type NajmThemeTokens as j, type NajmPreset as k, type NajmComponentName as l, type NajmComponentStyleConfig as m, type NajmResponsiveBreakpoint as n, type NajmResponsiveValue as o, NAJM_COMPONENT_NAMES as p, type NajmComponentRadius as q, type NajmDensity as r, type NajmSlotStyle as s, resolveRadiusValue as t };
159
+ export { type NajmDesignConfig as N, RADIUS_VALUE_MAP as R, type NajmVariantStyle as a, type NajmMode as b, type NajmComponentThemeConfig as c, type NajmLayoutConfig as d, type NajmTypographyConfig as e, type NajmThemeProviderProps as f, type NajmAppearance as g, type NajmThemeConfig as h, type NajmAccent as i, type NajmThemeTokens as j, type NajmPreset as k, type NajmComponentName as l, type NajmComponentStyleConfig as m, type NajmResponsiveBreakpoint as n, type NajmResponsiveValue as o, NAJM_COMPONENT_NAMES as p, type NajmComponentRadius as q, type NajmDensity as r, type NajmSlotStyle as s, resolveRadiusValue as t };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default, { RefObject, ReactNode, ComponentType, InputHTMLAttributes, Ref, ImgHTMLAttributes, CSSProperties, MouseEvent, MouseEventHandler } from 'react';
3
- import { a as NajmDesignConfig, f as NajmThemeProviderProps, g as NajmAppearance, e as NajmMode, h as NajmThemeConfig, i as NajmAccent, j as NajmThemeTokens, k as NajmPreset, l as NajmComponentName, m as NajmComponentStyleConfig, N as NajmComponentThemeConfig, c as NajmTypographyConfig, b as NajmLayoutConfig, n as NajmResponsiveBreakpoint, o as NajmResponsiveValue } from './design-types-Rkpt8Pg1.js';
4
- export { p as NAJM_COMPONENT_NAMES, q as NajmComponentRadius, r as NajmDensity, s as NajmSlotStyle, d as NajmVariantStyle, R as RADIUS_VALUE_MAP, t as resolveRadiusValue } from './design-types-Rkpt8Pg1.js';
5
- import { d as NTableToolbarLabels, e as NIconSource, B as BadgeColor, f as BadgeShape } from './NajmUIProvider-DTyRrukg.js';
6
- export { g as Badge, h as BadgeIcon, i as BadgeLook, j as BadgeProps, k as BadgeSize, l as BadgeVariant, D as DEFAULT_FEEDBACK_KEY_PREFIX, m as DEFAULT_TIME_ZONE, F as FeedbackKey, n as NBadge, o as NBadgeDefaults, p as NBadgeLook, q as NBadgeProps, N as NFeedbackDefaults, a as NFeedbackLabelKeys, b as NFeedbackLabels, r as NIcon, s as NIconProps, t as NTableDefaults, u as NTableDefaultsProvider, v as NajmPreferencesContextValue, w as NajmPreferencesProvider, x as NajmPreferencesProviderProps, y as NajmUIProvider, c as NajmUIProviderProps, z as badgeColorVariants, A as badgeVariants, C as useDocumentDirection, E as useNTableDefaults, G as useNajmPreferencesContext, H as useNajmTheme, I as useNajmTimeZone, J as useResolvedToolbarLabels } from './NajmUIProvider-DTyRrukg.js';
3
+ import { N as NajmDesignConfig, f as NajmThemeProviderProps, g as NajmAppearance, b as NajmMode, h as NajmThemeConfig, i as NajmAccent, j as NajmThemeTokens, k as NajmPreset, l as NajmComponentName, m as NajmComponentStyleConfig, c as NajmComponentThemeConfig, e as NajmTypographyConfig, d as NajmLayoutConfig, n as NajmResponsiveBreakpoint, o as NajmResponsiveValue } from './design-types-DffH_9XC.js';
4
+ export { p as NAJM_COMPONENT_NAMES, q as NajmComponentRadius, r as NajmDensity, s as NajmSlotStyle, a as NajmVariantStyle, R as RADIUS_VALUE_MAP, t as resolveRadiusValue } from './design-types-DffH_9XC.js';
5
+ import { d as NTableToolbarLabels, e as NIconSource, B as BadgeColor, f as BadgeShape } from './NajmUIProvider-BwL5HFIV.js';
6
+ export { g as Badge, h as BadgeIcon, i as BadgeLook, j as BadgeProps, k as BadgeSize, l as BadgeVariant, D as DEFAULT_FEEDBACK_KEY_PREFIX, m as DEFAULT_TIME_ZONE, F as FeedbackKey, n as NBadge, o as NBadgeDefaults, p as NBadgeLook, q as NBadgeProps, N as NFeedbackDefaults, a as NFeedbackLabelKeys, b as NFeedbackLabels, r as NIcon, s as NIconProps, t as NTableDefaults, u as NTableDefaultsProvider, v as NajmPreferencesContextValue, w as NajmPreferencesProvider, x as NajmPreferencesProviderProps, y as NajmUIProvider, c as NajmUIProviderProps, z as badgeColorVariants, A as badgeVariants, C as useDocumentDirection, E as useNTableDefaults, G as useNajmPreferencesContext, H as useNajmTheme, I as useNajmTimeZone, J as useResolvedToolbarLabels } from './NajmUIProvider-BwL5HFIV.js';
7
7
  import { N as NajmTranslate, c as NTablePaginationVariant, b as NTablePaginationLabels, a as NTableCardPagination } from './paginationLabels-dZLSNxfo.js';
8
8
  export { D as DEFAULT_PAGINATION_KEY_PREFIX, d as NTableInfinitePagination, e as NTableLoadMorePagination, f as buildPaginationLabels } from './paginationLabels-dZLSNxfo.js';
9
- export { d as defineNajmDesignConfig, p as parseNajmDesignConfig, r as resolveVariantAlias, s as stringifyNajmDesignConfig } from './design-config-D_x1GCu3.js';
9
+ export { d as defineNajmDesignConfig, p as parseNajmDesignConfig, r as resolveVariantAlias, s as stringifyNajmDesignConfig } from './design-config-CL9vqqQ9.js';
10
10
  import * as class_variance_authority_types from 'class-variance-authority/types';
11
11
  import { VariantProps } from 'class-variance-authority';
12
12
  import * as LabelPrimitive from '@radix-ui/react-label';
package/dist/index.mjs CHANGED
@@ -15,6 +15,7 @@ import './chunk-F5KXJCCJ.mjs';
15
15
  import { humanizeToken } from './chunk-JABLSOQN.mjs';
16
16
  export { DEFAULT_PLACEHOLDER, formatCurrency, formatDate, formatDateTime, formatNumber, formatPercent, formatRelativeTime, formatTime, humanizeToken, localDateInput, slugify } from './chunk-JABLSOQN.mjs';
17
17
  export { DEFAULT_MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, cleanQuery, createOffsetPagination, fetchOffsetPage, getPageIndex } from './chunk-2NX2VKS2.mjs';
18
+ import { NAJM_TIME_ZONES } from './chunk-XGIYOEWD.mjs';
18
19
  import { resolveRadiusValue, resolveVariantAlias, parseNajmDesignConfig } from './chunk-TFHWLE7N.mjs';
19
20
  export { NAJM_COMPONENT_NAMES, RADIUS_VALUE_MAP, defineNajmDesignConfig, defineNajmThemeConfig, parseNajmDesignConfig, parseNajmThemeConfig, resolveRadiusValue, resolveVariantAlias, stringifyNajmDesignConfig, stringifyNajmThemeConfig } from './chunk-TFHWLE7N.mjs';
20
21
  import * as React66 from 'react';
@@ -6206,30 +6207,6 @@ var TimeInput = React66__default.forwardRef(({ value = "", onChange, placeholder
6206
6207
  ] });
6207
6208
  });
6208
6209
  TimeInput.displayName = "TimeInput";
6209
- var timeZoneValues = [
6210
- "UTC",
6211
- "Atlantic/Azores",
6212
- "America/Los_Angeles",
6213
- "America/Denver",
6214
- "America/Chicago",
6215
- "America/New_York",
6216
- "America/Sao_Paulo",
6217
- "Pacific/Honolulu",
6218
- "Europe/London",
6219
- "Europe/Paris",
6220
- "Africa/Casablanca",
6221
- "Africa/Tunis",
6222
- "Africa/Cairo",
6223
- "Africa/Nairobi",
6224
- "Asia/Riyadh",
6225
- "Asia/Dubai",
6226
- "Asia/Kolkata",
6227
- "Asia/Bangkok",
6228
- "Asia/Shanghai",
6229
- "Asia/Tokyo",
6230
- "Australia/Sydney",
6231
- "Pacific/Auckland"
6232
- ];
6233
6210
  var timeZoneFormatter = new Intl.DateTimeFormat("en-US", {
6234
6211
  timeZone: "UTC",
6235
6212
  timeZoneName: "longOffset"
@@ -6241,7 +6218,7 @@ function getTimeZoneLabel(timeZone) {
6241
6218
  }).formatToParts(/* @__PURE__ */ new Date()).find((part) => part.type === "timeZoneName")?.value ?? "GMT";
6242
6219
  return `${timeZone} (${offset})`;
6243
6220
  }
6244
- var timeZones = timeZoneValues.map((value) => ({
6221
+ var timeZones = NAJM_TIME_ZONES.map((value) => ({
6245
6222
  value,
6246
6223
  label: getTimeZoneLabel(value)
6247
6224
  }));
@@ -1,3 +1,160 @@
1
- export { U as UiBootstrapConfig, a as UiBootstrapDiagnostic, b as UiBootstrapFailureReason, c as UiBootstrapFetcher, d as UiBootstrapLoader, e as UiBootstrapResource, f as UiBootstrapResources, g as UiBootstrapSnapshot, h as UiBootstrapValue, i as createUiBootstrapLoader } from '../uiBootstrap-Ci6K5j5t.js';
2
- export { d as defineNajmDesignConfig, p as parseNajmDesignConfig, s as stringifyNajmDesignConfig } from '../design-config-D_x1GCu3.js';
3
- export { N as NajmComponentThemeConfig, a as NajmDesignConfig, b as NajmLayoutConfig, c as NajmTypographyConfig } from '../design-types-Rkpt8Pg1.js';
1
+ export { b as UiBootstrapConfig, c as UiBootstrapDiagnostic, d as UiBootstrapFailureReason, e as UiBootstrapFetcher, h as UiBootstrapLoader, f as UiBootstrapResource, U as UiBootstrapResources, a as UiBootstrapSnapshot, g as UiBootstrapValue, i as createUiBootstrapLoader } from '../uiBootstrap-C66AFCo_.js';
2
+ import { b as NajmMode } from '../design-types-DffH_9XC.js';
3
+ export { c as NajmComponentThemeConfig, N as NajmDesignConfig, d as NajmLayoutConfig, e as NajmTypographyConfig } from '../design-types-DffH_9XC.js';
4
+ export { d as defineNajmDesignConfig, p as parseNajmDesignConfig, s as stringifyNajmDesignConfig } from '../design-config-CL9vqqQ9.js';
5
+
6
+ /**
7
+ * IANA zone identifiers offered by `TimeZoneInput` and accepted by the default
8
+ * preference handlers.
9
+ *
10
+ * Broad enough to cover the regions Najm applications ship to, deliberately
11
+ * not the full IANA database — a 400-entry combobox is not a usable control,
12
+ * and every entry here is a value the server contract must keep accepting.
13
+ * Each one is verified against `Intl.DateTimeFormat` in the package tests, so
14
+ * a typo cannot be published.
15
+ */
16
+ declare const NAJM_TIME_ZONES: readonly ["UTC", "Atlantic/Azores", "America/Los_Angeles", "America/Denver", "America/Chicago", "America/New_York", "America/Sao_Paulo", "Pacific/Honolulu", "Europe/London", "Europe/Paris", "Africa/Casablanca", "Africa/Tunis", "Africa/Cairo", "Africa/Nairobi", "Asia/Riyadh", "Asia/Dubai", "Asia/Kolkata", "Asia/Bangkok", "Asia/Shanghai", "Asia/Tokyo", "Australia/Sydney", "Pacific/Auckland"];
17
+ /** One of the canonical zones. Applications with a custom list infer their own. */
18
+ type NajmTimeZone = (typeof NAJM_TIME_ZONES)[number];
19
+ /** The zone assumed when an application configures none. */
20
+ declare const NAJM_DEFAULT_TIME_ZONE: NajmTimeZone;
21
+
22
+ /**
23
+ * The part of an i18n definition this contract needs.
24
+ *
25
+ * Structural on purpose: `najm-i18n` is an *optional* peer of this package, and
26
+ * a preference handler must not be the reason a consumer has to install it. A
27
+ * `najm-i18n` definition satisfies this shape as it is.
28
+ */
29
+ interface NajmPreferenceI18n<Language extends string = string> {
30
+ readonly supportedLanguages: readonly Language[];
31
+ readonly defaultLanguage: Language;
32
+ normalizeLanguage(value: unknown): Language;
33
+ }
34
+ /** Cookie names, one per preference. */
35
+ interface NajmPreferenceCookieNames {
36
+ language: string;
37
+ theme: string;
38
+ timeZone: string;
39
+ }
40
+ /**
41
+ * Cookie attributes, applied to all three.
42
+ *
43
+ * `httpOnly` is the default because nothing in the browser reads these back —
44
+ * the client provider holds the value it just set, and the server reads the
45
+ * cookie. `secure` is left unset by default rather than `true`: these cookies
46
+ * must survive `http://localhost`, and a deployment terminating TLS at the
47
+ * edge sees no difference. Applications serving only HTTPS should set it.
48
+ */
49
+ interface NajmPreferenceCookieOptions {
50
+ httpOnly: boolean;
51
+ maxAge: number;
52
+ path: string;
53
+ sameSite: "lax" | "strict" | "none";
54
+ secure?: boolean;
55
+ domain?: string;
56
+ }
57
+ /**
58
+ * Anything shaped like Next's cookie store.
59
+ *
60
+ * Structural rather than an import: this file must stay free of `next`, and a
61
+ * test can pass `{ get: (name) => ... }` without building a request.
62
+ */
63
+ interface NajmCookieReader {
64
+ get(name: string): {
65
+ value: string;
66
+ } | undefined;
67
+ }
68
+ interface NajmPreferenceSnapshot<Language extends string = string, TimeZone extends string = NajmTimeZone> {
69
+ language: Language;
70
+ theme: NajmMode;
71
+ timeZone: TimeZone;
72
+ }
73
+ interface NajmPreferenceResolveOptions {
74
+ /**
75
+ * Used only when the language cookie is absent or holds an unsupported
76
+ * value — a signed-in user's stored language, typically. Never overrides a
77
+ * valid cookie: the cookie is what the user last chose in this browser.
78
+ */
79
+ languageFallback?: unknown;
80
+ }
81
+ /** A route handler, ready to `export const POST = ...`. */
82
+ type NajmPreferenceHandler = (request: Request) => Promise<Response>;
83
+ interface NajmPreferenceHandlers {
84
+ /** Reads `{ language }`. */
85
+ language: NajmPreferenceHandler;
86
+ /** Reads `{ theme }`. */
87
+ theme: NajmPreferenceHandler;
88
+ /** Reads `{ timeZone }`. */
89
+ timeZone: NajmPreferenceHandler;
90
+ }
91
+ interface NajmPreferencesConfig<Language extends string = string, TimeZone extends string = NajmTimeZone> {
92
+ /** The application's catalog definition. The one required field. */
93
+ i18n: NajmPreferenceI18n<Language>;
94
+ /**
95
+ * Zones this application accepts. Defaults to the canonical list that
96
+ * `TimeZoneInput` offers.
97
+ *
98
+ * Pass this *only* alongside a matching `items` on the input. Two lists that
99
+ * disagree is the bug the shared default exists to prevent.
100
+ */
101
+ timeZones?: readonly TimeZone[];
102
+ /**
103
+ * Defaults to `UTC`, or to the first configured zone if `UTC` is not in it.
104
+ *
105
+ * `NoInfer` so this field cannot narrow `TimeZone`. Without it, an
106
+ * application that names `Africa/Casablanca` and takes the canonical list
107
+ * gets a definition typed as accepting *only* Casablanca — the opposite of
108
+ * what it configured, and a type error at every other zone downstream.
109
+ */
110
+ defaultTimeZone?: NoInfer<TimeZone>;
111
+ /** Defaults to `light`. */
112
+ defaultTheme?: NajmMode;
113
+ /** Merged over the `najm-ui-*` defaults, per key. */
114
+ cookieNames?: Partial<NajmPreferenceCookieNames>;
115
+ /** Merged over the secure defaults, per key. */
116
+ cookieOptions?: Partial<NajmPreferenceCookieOptions>;
117
+ /** Body field names, if this application's client posts something else. */
118
+ fields?: Partial<Record<"language" | "theme" | "timeZone", string>>;
119
+ /** Rejection messages, per preference. The defaults are generic and safe. */
120
+ messages?: Partial<Record<"language" | "theme" | "timeZone", string>>;
121
+ }
122
+ interface NajmPreferences<Language extends string = string, TimeZone extends string = NajmTimeZone> {
123
+ readonly cookieNames: Readonly<NajmPreferenceCookieNames>;
124
+ readonly cookieOptions: Readonly<NajmPreferenceCookieOptions>;
125
+ readonly timeZones: readonly TimeZone[];
126
+ readonly defaultTimeZone: TimeZone;
127
+ readonly defaultTheme: NajmMode;
128
+ readonly defaultLanguage: Language;
129
+ /** Every preference for this request, resolved from cookies. */
130
+ resolve(cookies: NajmCookieReader, options?: NajmPreferenceResolveOptions): NajmPreferenceSnapshot<Language, TimeZone>;
131
+ handlers: NajmPreferenceHandlers;
132
+ }
133
+ /** The language of a configured definition, so applications alias nothing. */
134
+ type NajmPreferenceLanguage<P> = P extends NajmPreferences<infer Language, string> ? Language : never;
135
+ /** The time zone of a configured definition. */
136
+ type NajmPreferenceTimeZone<P> = P extends NajmPreferences<string, infer TimeZone> ? TimeZone : never;
137
+ /**
138
+ * Configures the preference contract for one application.
139
+ *
140
+ * @example Zero configuration beyond the catalog
141
+ * ```ts
142
+ * export const preferences = defineNajmPreferences({ i18n: appI18n });
143
+ * ```
144
+ *
145
+ * @example An application with published cookie names to keep
146
+ * ```ts
147
+ * export const preferences = defineNajmPreferences({
148
+ * i18n: appI18n,
149
+ * defaultTimeZone: "Africa/Casablanca",
150
+ * cookieNames: {
151
+ * language: "app-ui-language",
152
+ * theme: "app-ui-theme",
153
+ * timeZone: "app-ui-timezone",
154
+ * },
155
+ * });
156
+ * ```
157
+ */
158
+ declare function defineNajmPreferences<Language extends string, const TimeZone extends string = NajmTimeZone>(config: NajmPreferencesConfig<Language, TimeZone>): NajmPreferences<Language, TimeZone>;
159
+
160
+ export { NAJM_DEFAULT_TIME_ZONE, NAJM_TIME_ZONES, type NajmCookieReader, NajmMode, type NajmPreferenceCookieNames, type NajmPreferenceCookieOptions, type NajmPreferenceHandler, type NajmPreferenceHandlers, type NajmPreferenceI18n, type NajmPreferenceLanguage, type NajmPreferenceResolveOptions, type NajmPreferenceSnapshot, type NajmPreferenceTimeZone, type NajmPreferences, type NajmPreferencesConfig, type NajmTimeZone, defineNajmPreferences };
@@ -1,2 +1,131 @@
1
1
  export { createUiBootstrapLoader } from '../chunk-7H6NFBQT.mjs';
2
+ import { NAJM_TIME_ZONES, NAJM_DEFAULT_TIME_ZONE } from '../chunk-XGIYOEWD.mjs';
3
+ export { NAJM_DEFAULT_TIME_ZONE, NAJM_TIME_ZONES } from '../chunk-XGIYOEWD.mjs';
2
4
  export { defineNajmDesignConfig, parseNajmDesignConfig, stringifyNajmDesignConfig } from '../chunk-TFHWLE7N.mjs';
5
+
6
+ // src/server/preferences.ts
7
+ var THEME_MODES = ["light", "dark"];
8
+ var DEFAULT_THEME = "light";
9
+ var ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365;
10
+ var DEFAULT_COOKIE_NAMES = {
11
+ language: "najm-ui-language",
12
+ theme: "najm-ui-theme",
13
+ timeZone: "najm-ui-timezone"
14
+ };
15
+ var DEFAULT_COOKIE_OPTIONS = {
16
+ httpOnly: true,
17
+ maxAge: ONE_YEAR_IN_SECONDS,
18
+ path: "/",
19
+ sameSite: "lax"
20
+ };
21
+ var COOKIE_NAME_PATTERN = /^[A-Za-z0-9!#$%&'*+\-.^_`|~]+$/;
22
+ var COOKIE_VALUE_PATTERN = /^[A-Za-z0-9!#$%&'()*+\-./:<=>?@[\]^_`|~]*$/;
23
+ function serializeCookie(name, value, options) {
24
+ if (!COOKIE_NAME_PATTERN.test(name) || !COOKIE_VALUE_PATTERN.test(value)) {
25
+ throw new Error("najm-kit/server: refusing to serialize an unsafe preference cookie");
26
+ }
27
+ const parts = [`${name}=${value}`, `Path=${options.path}`, `Max-Age=${options.maxAge}`];
28
+ if (options.domain) parts.push(`Domain=${options.domain}`);
29
+ if (options.httpOnly) parts.push("HttpOnly");
30
+ if (options.secure) parts.push("Secure");
31
+ parts.push(`SameSite=${options.sameSite[0].toUpperCase()}${options.sameSite.slice(1)}`);
32
+ return parts.join("; ");
33
+ }
34
+ function isRecord(value) {
35
+ return typeof value === "object" && value !== null;
36
+ }
37
+ async function readField(request, field) {
38
+ const body = await request.json().catch(() => null);
39
+ return isRecord(body) ? body[field] : void 0;
40
+ }
41
+ function rejection(message) {
42
+ return Response.json({ message }, { status: 400 });
43
+ }
44
+ function accepted(field, value, cookie) {
45
+ return Response.json({ [field]: value }, { headers: { "Set-Cookie": cookie } });
46
+ }
47
+ function defineNajmPreferences(config) {
48
+ const { i18n } = config;
49
+ const timeZones = Object.freeze([
50
+ ...config.timeZones ?? NAJM_TIME_ZONES
51
+ ]);
52
+ if (timeZones.length === 0) {
53
+ throw new Error("najm-kit/server: `timeZones` must list at least one zone");
54
+ }
55
+ const timeZoneSet = new Set(timeZones);
56
+ const fallbackTimeZone = timeZoneSet.has(NAJM_DEFAULT_TIME_ZONE) ? NAJM_DEFAULT_TIME_ZONE : timeZones[0];
57
+ const defaultTimeZone = config.defaultTimeZone ?? fallbackTimeZone;
58
+ if (!timeZoneSet.has(defaultTimeZone)) {
59
+ throw new Error(
60
+ `najm-kit/server: default time zone "${defaultTimeZone}" is not one of the configured zones`
61
+ );
62
+ }
63
+ const defaultTheme = config.defaultTheme ?? DEFAULT_THEME;
64
+ if (!THEME_MODES.includes(defaultTheme)) {
65
+ throw new Error(`najm-kit/server: default theme "${defaultTheme}" is not a supported mode`);
66
+ }
67
+ const cookieNames = Object.freeze({ ...DEFAULT_COOKIE_NAMES, ...config.cookieNames });
68
+ const cookieOptions = Object.freeze({ ...DEFAULT_COOKIE_OPTIONS, ...config.cookieOptions });
69
+ const fields = {
70
+ language: config.fields?.language ?? "language",
71
+ theme: config.fields?.theme ?? "theme",
72
+ timeZone: config.fields?.timeZone ?? "timeZone"
73
+ };
74
+ const messages = {
75
+ language: config.messages?.language ?? "Unsupported language.",
76
+ theme: config.messages?.theme ?? "Unsupported theme.",
77
+ timeZone: config.messages?.timeZone ?? "Unsupported time zone."
78
+ };
79
+ const isTheme = (value) => typeof value === "string" && THEME_MODES.includes(value);
80
+ const isTimeZone = (value) => typeof value === "string" && timeZoneSet.has(value);
81
+ const isLanguage = (value) => typeof value === "string" && i18n.supportedLanguages.includes(value);
82
+ function resolve(cookies, options = {}) {
83
+ const languageCookie = cookies.get(cookieNames.language)?.value;
84
+ const language = isLanguage(languageCookie) ? languageCookie : i18n.normalizeLanguage(options.languageFallback);
85
+ const themeCookie = cookies.get(cookieNames.theme)?.value;
86
+ const timeZoneCookie = cookies.get(cookieNames.timeZone)?.value;
87
+ return {
88
+ language,
89
+ theme: isTheme(themeCookie) ? themeCookie : defaultTheme,
90
+ timeZone: isTimeZone(timeZoneCookie) ? timeZoneCookie : defaultTimeZone
91
+ };
92
+ }
93
+ const handlers = {
94
+ async language(request) {
95
+ const value = await readField(request, fields.language);
96
+ if (!isLanguage(value)) return rejection(messages.language);
97
+ const language = i18n.normalizeLanguage(value);
98
+ return accepted(
99
+ fields.language,
100
+ language,
101
+ serializeCookie(cookieNames.language, language, cookieOptions)
102
+ );
103
+ },
104
+ async theme(request) {
105
+ const value = await readField(request, fields.theme);
106
+ if (!isTheme(value)) return rejection(messages.theme);
107
+ return accepted(fields.theme, value, serializeCookie(cookieNames.theme, value, cookieOptions));
108
+ },
109
+ async timeZone(request) {
110
+ const value = await readField(request, fields.timeZone);
111
+ if (!isTimeZone(value)) return rejection(messages.timeZone);
112
+ return accepted(
113
+ fields.timeZone,
114
+ value,
115
+ serializeCookie(cookieNames.timeZone, value, cookieOptions)
116
+ );
117
+ }
118
+ };
119
+ return Object.freeze({
120
+ cookieNames,
121
+ cookieOptions,
122
+ timeZones,
123
+ defaultTimeZone,
124
+ defaultTheme,
125
+ defaultLanguage: i18n.defaultLanguage,
126
+ resolve,
127
+ handlers: Object.freeze(handlers)
128
+ });
129
+ }
130
+
131
+ export { defineNajmPreferences };
@@ -1,5 +1,5 @@
1
- import { f as UiBootstrapResources, g as UiBootstrapSnapshot, U as UiBootstrapConfig } from '../uiBootstrap-Ci6K5j5t.js';
2
- export { a as UiBootstrapDiagnostic, b as UiBootstrapFailureReason, c as UiBootstrapFetcher, e as UiBootstrapResource, h as UiBootstrapValue } from '../uiBootstrap-Ci6K5j5t.js';
1
+ import { U as UiBootstrapResources, a as UiBootstrapSnapshot, b as UiBootstrapConfig } from '../uiBootstrap-C66AFCo_.js';
2
+ export { c as UiBootstrapDiagnostic, d as UiBootstrapFailureReason, e as UiBootstrapFetcher, f as UiBootstrapResource, g as UiBootstrapValue } from '../uiBootstrap-C66AFCo_.js';
3
3
 
4
4
  interface ReactServerUiBootstrap<R extends UiBootstrapResources> {
5
5
  /** Every resource for this request, resolved once and shared. */
package/dist/theme.css CHANGED
@@ -317,10 +317,10 @@ input:autofill {
317
317
  overflow-x: auto;
318
318
  scrollbar-width: none;
319
319
  }
320
- .najm-overlay-scroll-x::-webkit-scrollbar {
321
- display: none;
322
- }
323
-
320
+ .najm-overlay-scroll-x::-webkit-scrollbar {
321
+ display: none;
322
+ }
323
+
324
324
  /* Responsive table actions stay discoverable on touch and tablet layouts.
325
325
  Fine-pointer desktops may keep the quieter hover/focus reveal treatment. */
326
326
  .ntable-card-action {
@@ -377,7 +377,7 @@ input:autofill {
377
377
  .nimage-input-compact-overlay:focus-visible {
378
378
  opacity: 1;
379
379
  }
380
- }
380
+ }
381
381
 
382
382
  /* OverlayScrollbars theme used by the <NajmScroll> component — a thin,
383
383
  translucent slate bar that floats over content with no reserved space.
@@ -90,4 +90,4 @@ interface UiBootstrapLoader<R extends UiBootstrapResources> {
90
90
  }
91
91
  declare function createUiBootstrapLoader<R extends UiBootstrapResources>(config: UiBootstrapConfig<R>): UiBootstrapLoader<R>;
92
92
 
93
- export { type UiBootstrapConfig as U, type UiBootstrapDiagnostic as a, type UiBootstrapFailureReason as b, type UiBootstrapFetcher as c, type UiBootstrapLoader as d, type UiBootstrapResource as e, type UiBootstrapResources as f, type UiBootstrapSnapshot as g, type UiBootstrapValue as h, createUiBootstrapLoader as i };
93
+ export { type UiBootstrapResources as U, type UiBootstrapSnapshot as a, type UiBootstrapConfig as b, type UiBootstrapDiagnostic as c, type UiBootstrapFailureReason as d, type UiBootstrapFetcher as e, type UiBootstrapResource as f, type UiBootstrapValue as g, type UiBootstrapLoader as h, createUiBootstrapLoader as i };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "najm-kit",
3
- "version": "2.11.13",
3
+ "version": "2.11.14",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Reusable React UI component package for Najm framework",
@@ -198,7 +198,7 @@
198
198
  "@uiw/react-codemirror": "^4.25.0",
199
199
  "@vitejs/plugin-react": "^5.2.0",
200
200
  "happy-dom": "^20.11.1",
201
- "najm-i18n": "^2.1.0",
201
+ "najm-i18n": "^2.1.1",
202
202
  "postcss": "^8.5.22",
203
203
  "react-hook-form": "^7",
204
204
  "rimraf": "^6",