najm-kit 2.11.13 → 2.11.15
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 +411 -376
- package/README.md +1195 -1065
- package/dist/{NajmUIProvider-DTyRrukg.d.ts → NajmUIProvider-BwL5HFIV.d.ts} +1 -1
- package/dist/adapters/app.d.ts +2 -2
- package/dist/adapters/next.d.ts +2 -2
- package/dist/chunk-XGIYOEWD.mjs +28 -0
- package/dist/{design-config-D_x1GCu3.d.ts → design-config-CL9vqqQ9.d.ts} +1 -1
- package/dist/{design-types-Rkpt8Pg1.d.ts → design-types-DffH_9XC.d.ts} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.mjs +88 -57
- package/dist/server/index.d.ts +160 -3
- package/dist/server/index.mjs +129 -0
- package/dist/server/react.d.ts +2 -2
- package/dist/theme.css +5 -5
- package/dist/{uiBootstrap-Ci6K5j5t.d.ts → uiBootstrap-C66AFCo_.d.ts} +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default from 'react';
|
|
3
|
-
import {
|
|
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';
|
package/dist/adapters/app.d.ts
CHANGED
|
@@ -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-
|
|
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-
|
|
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';
|
package/dist/adapters/next.d.ts
CHANGED
|
@@ -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-
|
|
4
|
-
import '../design-types-
|
|
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 {
|
|
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
|
|
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 {
|
|
4
|
-
export { p as NAJM_COMPONENT_NAMES, q as NajmComponentRadius, r as NajmDensity, s as NajmSlotStyle,
|
|
5
|
-
import { d as NTableToolbarLabels, e as NIconSource, B as BadgeColor, f as BadgeShape } from './NajmUIProvider-
|
|
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-
|
|
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-
|
|
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';
|
|
@@ -28,7 +29,7 @@ import { HexColorPicker } from 'react-colorful';
|
|
|
28
29
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
29
30
|
import { converter, parse, formatHsl, formatRgb, formatHex } from 'culori';
|
|
30
31
|
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
31
|
-
import { Command as Command$1 } from 'cmdk';
|
|
32
|
+
import { Command as Command$1, defaultFilter } from 'cmdk';
|
|
32
33
|
import * as SheetPrimitive from '@radix-ui/react-dialog';
|
|
33
34
|
import { create } from 'zustand';
|
|
34
35
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
@@ -4563,21 +4564,39 @@ var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...
|
|
|
4563
4564
|
const displayLabel = selectedItem?.label ?? (allowFreeText && value ? value : "");
|
|
4564
4565
|
const shouldDisplayIcon = Boolean(icon) && showIcon && !value;
|
|
4565
4566
|
const iconProps = getIconColorProps(iconColor, "h-4 w-4");
|
|
4567
|
+
const [activeItem, setActiveItem] = useState(selectedItem?.label ?? normalizedItems[0]?.label ?? "");
|
|
4566
4568
|
const trimmedQuery = query.trim();
|
|
4567
4569
|
const queryMatchesItem = trimmedQuery !== "" && normalizedItems.some((i) => i.value === trimmedQuery || i.label.toLowerCase() === trimmedQuery.toLowerCase());
|
|
4568
4570
|
const showFreeTextOption = allowFreeText && trimmedQuery !== "" && !queryMatchesItem;
|
|
4571
|
+
const rankItems = (search) => normalizedItems.map((item, index) => ({
|
|
4572
|
+
index,
|
|
4573
|
+
item,
|
|
4574
|
+
score: shouldFilter ? defaultFilter(item.label, search.trim(), [item.value, item.label]) : 1
|
|
4575
|
+
})).filter(({ score }) => score > 0).sort((left, right) => right.score - left.score || left.index - right.index);
|
|
4569
4576
|
const commit = (next) => {
|
|
4570
4577
|
onChange(next);
|
|
4578
|
+
setActiveItem(normalizedItems.find((item) => item.value === next)?.label ?? "");
|
|
4571
4579
|
setOpen(false);
|
|
4572
4580
|
setQuery("");
|
|
4573
4581
|
onSearchChange?.("");
|
|
4574
4582
|
};
|
|
4575
4583
|
const updateQuery = (next) => {
|
|
4584
|
+
setActiveItem(rankItems(next)[0]?.item.label ?? "");
|
|
4576
4585
|
setQuery(next);
|
|
4577
4586
|
onSearchChange?.(next);
|
|
4578
4587
|
};
|
|
4588
|
+
const updateActiveItem = (next) => {
|
|
4589
|
+
const nextItem = normalizedItems.find((item) => item.label === next);
|
|
4590
|
+
if (trimmedQuery !== "" && shouldFilter && (!nextItem || defaultFilter(nextItem.label, trimmedQuery, [nextItem.value, nextItem.label]) <= 0)) {
|
|
4591
|
+
return;
|
|
4592
|
+
}
|
|
4593
|
+
setActiveItem(next);
|
|
4594
|
+
};
|
|
4579
4595
|
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: (o) => {
|
|
4580
4596
|
setOpen(o);
|
|
4597
|
+
if (o) {
|
|
4598
|
+
setActiveItem(selectedItem?.label ?? normalizedItems[0]?.label ?? "");
|
|
4599
|
+
}
|
|
4581
4600
|
if (!o) {
|
|
4582
4601
|
setQuery("");
|
|
4583
4602
|
onSearchChange?.("");
|
|
@@ -4595,6 +4614,11 @@ var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...
|
|
|
4595
4614
|
"aria-label": ariaLabel,
|
|
4596
4615
|
tabIndex: disabled ? -1 : 0,
|
|
4597
4616
|
"aria-expanded": open,
|
|
4617
|
+
onKeyDown: (event) => {
|
|
4618
|
+
if (disabled || event.key !== "Enter" && event.key !== " ") return;
|
|
4619
|
+
event.preventDefault();
|
|
4620
|
+
setOpen(true);
|
|
4621
|
+
},
|
|
4598
4622
|
className: cn(
|
|
4599
4623
|
"cursor-pointer outline-none data-[state=open]:border-ring",
|
|
4600
4624
|
className
|
|
@@ -4620,38 +4644,69 @@ var ComboboxInput = ({ placeholder = "Select...", searchPlaceholder = "Search...
|
|
|
4620
4644
|
pointerDismissedRef.current = false;
|
|
4621
4645
|
triggerRef.current?.blur();
|
|
4622
4646
|
},
|
|
4623
|
-
children: /* @__PURE__ */ jsxs(
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4647
|
+
children: /* @__PURE__ */ jsxs(
|
|
4648
|
+
Command,
|
|
4649
|
+
{
|
|
4650
|
+
shouldFilter,
|
|
4651
|
+
value: activeItem,
|
|
4652
|
+
onValueChange: updateActiveItem,
|
|
4653
|
+
children: [
|
|
4654
|
+
/* @__PURE__ */ jsx(
|
|
4655
|
+
CommandInput,
|
|
4656
|
+
{
|
|
4657
|
+
placeholder: searchPlaceholder,
|
|
4658
|
+
className: "h-9",
|
|
4659
|
+
value: query,
|
|
4660
|
+
onValueChange: updateQuery,
|
|
4661
|
+
onKeyDown: (e) => {
|
|
4662
|
+
const rankedItems = rankItems(trimmedQuery);
|
|
4663
|
+
if (trimmedQuery !== "" && rankedItems.length > 0 && ["ArrowDown", "ArrowUp", "Home", "End"].includes(e.key)) {
|
|
4664
|
+
e.preventDefault();
|
|
4665
|
+
e.stopPropagation();
|
|
4666
|
+
const currentIndex = rankedItems.findIndex(({ item }) => item.label === activeItem);
|
|
4667
|
+
const nextIndex = e.key === "Home" ? 0 : e.key === "End" ? rankedItems.length - 1 : e.key === "ArrowDown" ? Math.min(currentIndex + 1, rankedItems.length - 1) : Math.max(currentIndex < 0 ? 0 : currentIndex - 1, 0);
|
|
4668
|
+
setActiveItem(rankedItems[nextIndex]?.item.label ?? "");
|
|
4669
|
+
return;
|
|
4670
|
+
}
|
|
4671
|
+
if (e.key !== "Enter") return;
|
|
4672
|
+
if (showFreeTextOption) {
|
|
4673
|
+
e.preventDefault();
|
|
4674
|
+
commit(trimmedQuery);
|
|
4675
|
+
return;
|
|
4676
|
+
}
|
|
4677
|
+
if (trimmedQuery !== "") {
|
|
4678
|
+
const activeMatch = normalizedItems.find((item) => item.label === activeItem);
|
|
4679
|
+
const nextItem = activeMatch && defaultFilter(
|
|
4680
|
+
activeMatch.label,
|
|
4681
|
+
trimmedQuery,
|
|
4682
|
+
[activeMatch.value, activeMatch.label]
|
|
4683
|
+
) > 0 ? activeMatch : rankedItems[0]?.item;
|
|
4684
|
+
if (nextItem) {
|
|
4685
|
+
e.preventDefault();
|
|
4686
|
+
commit(nextItem.value);
|
|
4687
|
+
}
|
|
4688
|
+
}
|
|
4689
|
+
}
|
|
4635
4690
|
}
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
] }
|
|
4652
|
-
]
|
|
4653
|
-
|
|
4654
|
-
|
|
4691
|
+
),
|
|
4692
|
+
/* @__PURE__ */ jsxs(CommandList, { children: [
|
|
4693
|
+
/* @__PURE__ */ jsx(CommandEmpty, { children: loading ? loadingMessage : emptyMessage }),
|
|
4694
|
+
/* @__PURE__ */ jsxs(CommandGroup, { children: [
|
|
4695
|
+
showFreeTextOption && /* @__PURE__ */ jsxs(CommandItem, { value: trimmedQuery, onSelect: () => commit(trimmedQuery), className: "cursor-pointer", children: [
|
|
4696
|
+
/* @__PURE__ */ jsx(Check, { className: "mr-2 h-4 w-4 opacity-0" }),
|
|
4697
|
+
'Use "',
|
|
4698
|
+
trimmedQuery,
|
|
4699
|
+
'"'
|
|
4700
|
+
] }, "__free_text__"),
|
|
4701
|
+
normalizedItems.map((item) => /* @__PURE__ */ jsxs(CommandItem, { value: item.label, keywords: [item.value, item.label], onSelect: () => commit(value === item.value ? "" : item.value), className: "cursor-pointer", children: [
|
|
4702
|
+
/* @__PURE__ */ jsx(Check, { className: cn("mr-2 h-4 w-4", value === item.value ? "opacity-100" : "opacity-0") }),
|
|
4703
|
+
item.label
|
|
4704
|
+
] }, item.value))
|
|
4705
|
+
] })
|
|
4706
|
+
] })
|
|
4707
|
+
]
|
|
4708
|
+
}
|
|
4709
|
+
)
|
|
4655
4710
|
}
|
|
4656
4711
|
)
|
|
4657
4712
|
] });
|
|
@@ -6206,30 +6261,6 @@ var TimeInput = React66__default.forwardRef(({ value = "", onChange, placeholder
|
|
|
6206
6261
|
] });
|
|
6207
6262
|
});
|
|
6208
6263
|
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
6264
|
var timeZoneFormatter = new Intl.DateTimeFormat("en-US", {
|
|
6234
6265
|
timeZone: "UTC",
|
|
6235
6266
|
timeZoneName: "longOffset"
|
|
@@ -6241,7 +6272,7 @@ function getTimeZoneLabel(timeZone) {
|
|
|
6241
6272
|
}).formatToParts(/* @__PURE__ */ new Date()).find((part) => part.type === "timeZoneName")?.value ?? "GMT";
|
|
6242
6273
|
return `${timeZone} (${offset})`;
|
|
6243
6274
|
}
|
|
6244
|
-
var timeZones =
|
|
6275
|
+
var timeZones = NAJM_TIME_ZONES.map((value) => ({
|
|
6245
6276
|
value,
|
|
6246
6277
|
label: getTimeZoneLabel(value)
|
|
6247
6278
|
}));
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,3 +1,160 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
3
|
-
export {
|
|
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 };
|
package/dist/server/index.mjs
CHANGED
|
@@ -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 };
|
package/dist/server/react.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
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.
|