@petrarca/sonnet-core 0.4.2 → 0.6.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.
@@ -0,0 +1,100 @@
1
+ import * as React from 'react';
2
+ import React__default from 'react';
3
+
4
+ /**
5
+ * App-wide component configuration contract.
6
+ *
7
+ * A consuming app sets default props for components once at the root via
8
+ * SonnetConfigProvider; individual component instances override via props.
9
+ * Resolution order is: instance prop > provider default > built-in default.
10
+ *
11
+ * The config is keyed by component name under `components`. Each component
12
+ * package augments `SonnetComponentDefaults` (declaration merging) with its
13
+ * own configurable-prop shape, so the type stays modular -- new components add
14
+ * their key without editing this file.
15
+ *
16
+ * Global, cross-cutting settings (locale, density, ...) can be added to
17
+ * `SonnetGlobalConfig` later without affecting per-component defaults.
18
+ */
19
+ /**
20
+ * Per-component default props, keyed by component name. Component packages
21
+ * extend this interface via declaration merging, e.g.:
22
+ *
23
+ * declare module "@petrarca/sonnet-core" {
24
+ * interface SonnetComponentDefaults {
25
+ * EntityTable?: { defaultProps?: Partial<EntityTableConfigurable> };
26
+ * }
27
+ * }
28
+ */
29
+ interface SonnetComponentDefaults {
30
+ }
31
+ /**
32
+ * Cross-cutting global settings. Extend via declaration merging as needed.
33
+ * Empty by default; packages add fields without editing this file.
34
+ */
35
+ interface SonnetGlobalConfig {
36
+ /**
37
+ * BCP-47 locale (e.g. `"en-US"`, `"de-DE"`) used for display and input
38
+ * parsing of locale-sensitive components (dates, numbers). Values exchanged
39
+ * with consumers stay locale-independent (ISO). When unset, components fall
40
+ * back to the browser locale (`navigator.language`), then `"en"`.
41
+ */
42
+ locale?: string;
43
+ }
44
+ /** The full app-wide configuration object held by SonnetConfigProvider. */
45
+ interface SonnetConfig {
46
+ /** Cross-cutting globals (locale, density, ...). */
47
+ globals?: SonnetGlobalConfig;
48
+ /** Per-component default props, keyed by component name. */
49
+ components?: SonnetComponentDefaults;
50
+ }
51
+
52
+ /**
53
+ * SonnetConfigProvider -- sets app-wide component defaults.
54
+ *
55
+ * Place once at the app root to define default props for components (and
56
+ * cross-cutting globals). Individual instances still override via props.
57
+ * Nested providers merge into their parent, so a subtree can refine or
58
+ * override outer defaults.
59
+ *
60
+ * Resolution order for any prop (see useComponentDefaults):
61
+ * instance prop > provider default > built-in default.
62
+ */
63
+
64
+ interface SonnetConfigProviderProps {
65
+ /** The configuration to apply. Merged onto any parent provider's config. */
66
+ value: SonnetConfig;
67
+ children: React__default.ReactNode;
68
+ }
69
+ declare function SonnetConfigProvider({ value, children, }: SonnetConfigProviderProps): React__default.ReactElement;
70
+
71
+ declare const SonnetConfigContext: React.Context<SonnetConfig>;
72
+
73
+ /**
74
+ * useComponentDefaults -- resolve a component's props against app-wide config.
75
+ *
76
+ * Resolution order, per prop: instance prop > provider default > built-in.
77
+ * A component calls this at the top of its body:
78
+ *
79
+ * const resolved = useComponentDefaults("EntityTable", BUILTIN, props);
80
+ *
81
+ * where BUILTIN is a stable (module-level) object of the component's built-in
82
+ * defaults. With no provider in the tree, the result is BUILTIN merged with
83
+ * props -- identical to not using the config at all, so existing behavior is
84
+ * preserved.
85
+ */
86
+ declare function useComponentDefaults<Props extends Record<string, unknown>>(componentName: string, builtinDefaults: Partial<Props>, props: Props): Props;
87
+
88
+ /**
89
+ * useLocale -- resolve the active BCP-47 locale.
90
+ *
91
+ * Resolution order: explicit override > provider global (SonnetConfigProvider)
92
+ * > browser (`navigator.language`) > `"en"`. Locale-sensitive components use
93
+ * this for display and input parsing only; values exchanged with consumers
94
+ * remain locale-independent (ISO).
95
+ */
96
+ /** The browser locale, or "en" when unavailable (e.g. SSR). */
97
+ declare function getBrowserLocale(): string;
98
+ declare function useLocale(override?: string): string;
99
+
100
+ export { type SonnetComponentDefaults, type SonnetConfig, SonnetConfigContext, SonnetConfigProvider, type SonnetConfigProviderProps, type SonnetGlobalConfig, getBrowserLocale, useComponentDefaults, useLocale };
@@ -0,0 +1,78 @@
1
+ // src/config/SonnetConfigProvider.tsx
2
+ import { useContext, useMemo } from "react";
3
+
4
+ // src/config/SonnetConfigContext.ts
5
+ import { createContext } from "react";
6
+ var SonnetConfigContext = createContext({});
7
+
8
+ // src/config/SonnetConfigProvider.tsx
9
+ import { jsx } from "react/jsx-runtime";
10
+ function mergeConfig(parent, child) {
11
+ const components = {
12
+ ...parent.components
13
+ };
14
+ const childComponents = child.components;
15
+ if (childComponents) {
16
+ for (const name of Object.keys(childComponents)) {
17
+ components[name] = {
18
+ ...components[name],
19
+ ...childComponents[name],
20
+ defaultProps: {
21
+ ...components[name]?.defaultProps,
22
+ ...childComponents[name]?.defaultProps
23
+ }
24
+ };
25
+ }
26
+ }
27
+ return {
28
+ globals: { ...parent.globals, ...child.globals },
29
+ components
30
+ };
31
+ }
32
+ function SonnetConfigProvider({
33
+ value,
34
+ children
35
+ }) {
36
+ const parent = useContext(SonnetConfigContext);
37
+ const merged = useMemo(() => mergeConfig(parent, value), [parent, value]);
38
+ return /* @__PURE__ */ jsx(SonnetConfigContext.Provider, { value: merged, children });
39
+ }
40
+
41
+ // src/config/useComponentDefaults.ts
42
+ import { useContext as useContext2, useMemo as useMemo2 } from "react";
43
+ function useComponentDefaults(componentName, builtinDefaults, props) {
44
+ const config = useContext2(SonnetConfigContext);
45
+ const components = config.components;
46
+ const providerDefaults = components?.[componentName]?.defaultProps;
47
+ return useMemo2(() => {
48
+ const resolved = {
49
+ ...builtinDefaults,
50
+ ...providerDefaults
51
+ };
52
+ for (const key of Object.keys(props)) {
53
+ if (props[key] !== void 0) resolved[key] = props[key];
54
+ }
55
+ return resolved;
56
+ }, [builtinDefaults, providerDefaults, props]);
57
+ }
58
+
59
+ // src/config/useLocale.ts
60
+ import { useContext as useContext3 } from "react";
61
+ function getBrowserLocale() {
62
+ if (typeof navigator !== "undefined" && navigator.language) {
63
+ return navigator.language;
64
+ }
65
+ return "en";
66
+ }
67
+ function useLocale(override) {
68
+ const config = useContext3(SonnetConfigContext);
69
+ return override ?? config.globals?.locale ?? getBrowserLocale();
70
+ }
71
+ export {
72
+ SonnetConfigContext,
73
+ SonnetConfigProvider,
74
+ getBrowserLocale,
75
+ useComponentDefaults,
76
+ useLocale
77
+ };
78
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/config/SonnetConfigProvider.tsx","../../src/config/SonnetConfigContext.ts","../../src/config/useComponentDefaults.ts","../../src/config/useLocale.ts"],"sourcesContent":["/**\n * SonnetConfigProvider -- sets app-wide component defaults.\n *\n * Place once at the app root to define default props for components (and\n * cross-cutting globals). Individual instances still override via props.\n * Nested providers merge into their parent, so a subtree can refine or\n * override outer defaults.\n *\n * Resolution order for any prop (see useComponentDefaults):\n * instance prop > provider default > built-in default.\n */\n\nimport React, { useContext, useMemo } from \"react\";\nimport { SonnetConfigContext } from \"./SonnetConfigContext\";\nimport type { SonnetConfig } from \"./types\";\n\nexport interface SonnetConfigProviderProps {\n /** The configuration to apply. Merged onto any parent provider's config. */\n value: SonnetConfig;\n children: React.ReactNode;\n}\n\n// Merge child config onto parent. Globals shallow-merge; component defaults\n// merge per component name, with each component's defaultProps shallow-merged\n// (child wins). One level of nesting is sufficient for the defaultProps shape.\nfunction mergeConfig(parent: SonnetConfig, child: SonnetConfig): SonnetConfig {\n const components: Record<string, { defaultProps?: Record<string, unknown> }> =\n {\n ...(parent.components as Record<\n string,\n { defaultProps?: Record<string, unknown> }\n >),\n };\n const childComponents = child.components as\n | Record<string, { defaultProps?: Record<string, unknown> }>\n | undefined;\n if (childComponents) {\n for (const name of Object.keys(childComponents)) {\n components[name] = {\n ...components[name],\n ...childComponents[name],\n defaultProps: {\n ...components[name]?.defaultProps,\n ...childComponents[name]?.defaultProps,\n },\n };\n }\n }\n return {\n globals: { ...parent.globals, ...child.globals },\n components: components as SonnetConfig[\"components\"],\n };\n}\n\nexport function SonnetConfigProvider({\n value,\n children,\n}: SonnetConfigProviderProps): React.ReactElement {\n const parent = useContext(SonnetConfigContext);\n const merged = useMemo(() => mergeConfig(parent, value), [parent, value]);\n return (\n <SonnetConfigContext.Provider value={merged}>\n {children}\n </SonnetConfigContext.Provider>\n );\n}\n","/**\n * React context holding the resolved app-wide SonnetConfig.\n *\n * Nested providers merge into their parent (see SonnetConfigProvider), so a\n * provider deeper in the tree can refine or override an outer one for its\n * subtree. The default is an empty config -- with no provider, components fall\n * back to their built-in defaults, preserving existing behavior.\n */\n\nimport { createContext } from \"react\";\nimport type { SonnetConfig } from \"./types\";\n\nexport const SonnetConfigContext = createContext<SonnetConfig>({});\n","/**\n * useComponentDefaults -- resolve a component's props against app-wide config.\n *\n * Resolution order, per prop: instance prop > provider default > built-in.\n * A component calls this at the top of its body:\n *\n * const resolved = useComponentDefaults(\"EntityTable\", BUILTIN, props);\n *\n * where BUILTIN is a stable (module-level) object of the component's built-in\n * defaults. With no provider in the tree, the result is BUILTIN merged with\n * props -- identical to not using the config at all, so existing behavior is\n * preserved.\n */\n\nimport { useContext, useMemo } from \"react\";\nimport { SonnetConfigContext } from \"./SonnetConfigContext\";\n\nexport function useComponentDefaults<Props extends Record<string, unknown>>(\n componentName: string,\n builtinDefaults: Partial<Props>,\n props: Props,\n): Props {\n const config = useContext(SonnetConfigContext);\n const components = config.components as\n | Record<string, { defaultProps?: Partial<Props> } | undefined>\n | undefined;\n const providerDefaults = components?.[componentName]?.defaultProps;\n\n return useMemo(() => {\n // Spread order encodes precedence: builtin < provider < instance props.\n // Only undefined instance props fall through to provider/builtin, so an\n // explicit prop always wins.\n const resolved: Record<string, unknown> = {\n ...builtinDefaults,\n ...providerDefaults,\n };\n for (const key of Object.keys(props)) {\n if (props[key] !== undefined) resolved[key] = props[key];\n }\n return resolved as Props;\n }, [builtinDefaults, providerDefaults, props]);\n}\n","/**\n * useLocale -- resolve the active BCP-47 locale.\n *\n * Resolution order: explicit override > provider global (SonnetConfigProvider)\n * > browser (`navigator.language`) > `\"en\"`. Locale-sensitive components use\n * this for display and input parsing only; values exchanged with consumers\n * remain locale-independent (ISO).\n */\n\nimport { useContext } from \"react\";\nimport { SonnetConfigContext } from \"./SonnetConfigContext\";\n\n/** The browser locale, or \"en\" when unavailable (e.g. SSR). */\nexport function getBrowserLocale(): string {\n if (typeof navigator !== \"undefined\" && navigator.language) {\n return navigator.language;\n }\n return \"en\";\n}\n\nexport function useLocale(override?: string): string {\n const config = useContext(SonnetConfigContext);\n return override ?? config.globals?.locale ?? getBrowserLocale();\n}\n"],"mappings":";AAYA,SAAgB,YAAY,eAAe;;;ACH3C,SAAS,qBAAqB;AAGvB,IAAM,sBAAsB,cAA4B,CAAC,CAAC;;;ADiD7D;AApCJ,SAAS,YAAY,QAAsB,OAAmC;AAC5E,QAAM,aACJ;AAAA,IACE,GAAI,OAAO;AAAA,EAIb;AACF,QAAM,kBAAkB,MAAM;AAG9B,MAAI,iBAAiB;AACnB,eAAW,QAAQ,OAAO,KAAK,eAAe,GAAG;AAC/C,iBAAW,IAAI,IAAI;AAAA,QACjB,GAAG,WAAW,IAAI;AAAA,QAClB,GAAG,gBAAgB,IAAI;AAAA,QACvB,cAAc;AAAA,UACZ,GAAG,WAAW,IAAI,GAAG;AAAA,UACrB,GAAG,gBAAgB,IAAI,GAAG;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL,SAAS,EAAE,GAAG,OAAO,SAAS,GAAG,MAAM,QAAQ;AAAA,IAC/C;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AACF,GAAkD;AAChD,QAAM,SAAS,WAAW,mBAAmB;AAC7C,QAAM,SAAS,QAAQ,MAAM,YAAY,QAAQ,KAAK,GAAG,CAAC,QAAQ,KAAK,CAAC;AACxE,SACE,oBAAC,oBAAoB,UAApB,EAA6B,OAAO,QAClC,UACH;AAEJ;;;AEnDA,SAAS,cAAAA,aAAY,WAAAC,gBAAe;AAG7B,SAAS,qBACd,eACA,iBACA,OACO;AACP,QAAM,SAASC,YAAW,mBAAmB;AAC7C,QAAM,aAAa,OAAO;AAG1B,QAAM,mBAAmB,aAAa,aAAa,GAAG;AAEtD,SAAOC,SAAQ,MAAM;AAInB,UAAM,WAAoC;AAAA,MACxC,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AACA,eAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,UAAI,MAAM,GAAG,MAAM,OAAW,UAAS,GAAG,IAAI,MAAM,GAAG;AAAA,IACzD;AACA,WAAO;AAAA,EACT,GAAG,CAAC,iBAAiB,kBAAkB,KAAK,CAAC;AAC/C;;;AChCA,SAAS,cAAAC,mBAAkB;AAIpB,SAAS,mBAA2B;AACzC,MAAI,OAAO,cAAc,eAAe,UAAU,UAAU;AAC1D,WAAO,UAAU;AAAA,EACnB;AACA,SAAO;AACT;AAEO,SAAS,UAAU,UAA2B;AACnD,QAAM,SAASC,YAAW,mBAAmB;AAC7C,SAAO,YAAY,OAAO,SAAS,UAAU,iBAAiB;AAChE;","names":["useContext","useMemo","useContext","useMemo","useContext","useContext"]}
@@ -1,5 +1,5 @@
1
- import { b as EntityFetcherFactory, a as EntityOption, E as EntityOptionFetcher } from '../types-B29bSeIg.js';
2
- export { c as EntityFetchParams, G as GraphqlFetcherConfig, R as RestFetcherConfig } from '../types-B29bSeIg.js';
1
+ import { b as EntityFetcherFactory, a as EntityOption, E as EntityOptionFetcher } from '../types-DJ4hb97y.js';
2
+ export { c as EntityFetchParams, G as GraphqlFetcherConfig, R as RestFetcherConfig } from '../types-DJ4hb97y.js';
3
3
  import * as React from 'react';
4
4
 
5
5
  declare const FetcherContext: React.Context<EntityFetcherFactory | null>;
@@ -1,4 +1,4 @@
1
- import { E as EntityOptionFetcher, a as EntityOption } from '../types-B29bSeIg.js';
1
+ import { E as EntityOptionFetcher, a as EntityOption } from '../types-DJ4hb97y.js';
2
2
 
3
3
  interface UseClipboardOptions {
4
4
  timeout?: number;
package/dist/index.d.ts CHANGED
@@ -34,6 +34,189 @@ declare function formatDateTimeTz(iso: string | null | undefined): string;
34
34
  /** Return "{count} {word}" with the word pluralized when count != 1. */
35
35
  declare function pluralize(count: number, word: string): string;
36
36
 
37
+ /**
38
+ * Date parsing and formatting -- pure functional API.
39
+ *
40
+ * The public surface is a set of pure functions. A `CompiledDateFormat`
41
+ * pre-computes the format structure so repeated parse/format calls (e.g.
42
+ * on every keystroke) don't re-derive component positions each time. Call
43
+ * `compileDateFormat` once in a `useMemo` and pass the result to
44
+ * `parseDate` / `formatDateInput`.
45
+ *
46
+ * The parser operates on native `Date` values internally. Widgets and form
47
+ * data exchange locale-independent ISO 8601 strings -- use
48
+ * `formatIsoDate` / `parseIsoDate` at the boundary.
49
+ */
50
+ /**
51
+ * Pre-compiled date format. Opaque to callers; produced by
52
+ * {@link compileDateFormat} and consumed by {@link parseDate} and
53
+ * {@link formatDateInput}.
54
+ */
55
+ interface CompiledDateFormat {
56
+ readonly format: string;
57
+ readonly yearThreshold: number;
58
+ readonly dayIndex: number;
59
+ readonly monthIndex: number;
60
+ readonly yearIndex: number;
61
+ readonly has2DigitYear: boolean;
62
+ readonly validSeparators: readonly string[];
63
+ }
64
+ /** Options for {@link compileDateFormat}. */
65
+ interface DateFormatOptions {
66
+ /**
67
+ * Component order for parsing and display. Supported tokens: `DD` (day),
68
+ * `MM` (month), `YYYY` or `YY` (year). Default: `"DD/MM/YYYY"`.
69
+ */
70
+ format?: string;
71
+ /**
72
+ * Threshold for expanding 2-digit years. If a 2-digit year is greater than
73
+ * this value it is treated as the prior century, otherwise the current one.
74
+ * Special cases: `0` always current century, `-1` always prior century.
75
+ * Default: the current year modulo 100, captured at compile time.
76
+ */
77
+ yearThreshold?: number;
78
+ }
79
+ /** Result of {@link parseDate}. */
80
+ interface DateParseResult {
81
+ /** Normalized display string (formatted per the compiled format), or "" on failure. */
82
+ value: string;
83
+ /** Parsed `Date` object, or null on failure. Needed by calendar components. */
84
+ date: Date | null;
85
+ /** Error message on failure, or "" on success. */
86
+ error: string;
87
+ }
88
+ /**
89
+ * Precision of a partial ISO 8601 date:
90
+ * year -> "YYYY"
91
+ * month -> "YYYY-MM"
92
+ * day -> "YYYY-MM-DD"
93
+ */
94
+ type DatePrecision = "year" | "month" | "day";
95
+ /**
96
+ * Pre-compile a date format string into an opaque `CompiledDateFormat`.
97
+ *
98
+ * Call once per format string (e.g. in `useMemo`) and pass the result to
99
+ * {@link parseDate} and {@link formatDateInput}.
100
+ */
101
+ declare function compileDateFormat(options?: DateFormatOptions): CompiledDateFormat;
102
+ /**
103
+ * Parse a user-entered date string against a compiled format.
104
+ *
105
+ * Accepts colon/separator-split and compact numeric input. The shorthands
106
+ * `"."`, `"t"`, and `"today"` resolve to the current date. Empty input
107
+ * returns `{ value: "", date: null, error: "" }`.
108
+ */
109
+ declare function parseDate(input: string, fmt: CompiledDateFormat): DateParseResult;
110
+ /**
111
+ * Format a `Date` as a display string using the compiled format.
112
+ * Returns "" for null or invalid dates.
113
+ */
114
+ declare function formatDateInput(date: Date | null | undefined, fmt: CompiledDateFormat): string;
115
+ /** Whether two dates fall on the same calendar day. */
116
+ declare function isDateEqual(a: Date | null, b: Date | null): boolean;
117
+ /**
118
+ * Convert a local `Date` to a partial ISO date string at the given precision
119
+ * (default `"day"`), using local components (no timezone shift).
120
+ * Returns "" for null or invalid dates.
121
+ */
122
+ declare function formatIsoDate(date: Date | null | undefined, precision?: DatePrecision): string;
123
+ /**
124
+ * Parse a partial ISO date string (`YYYY`, `YYYY-MM`, or `YYYY-MM-DD`) into a
125
+ * local `Date`. Missing month/day default to January/1st. Returns null for
126
+ * empty or malformed input.
127
+ */
128
+ declare function parseIsoDate(iso: string | null | undefined): Date | null;
129
+ /**
130
+ * Detect the precision of a partial ISO date string.
131
+ * Returns `"day"` for empty, malformed, or full-date input.
132
+ */
133
+ declare function isoDatePrecision(iso: string | null | undefined): DatePrecision;
134
+
135
+ /**
136
+ * Time parsing and formatting -- pure functional API.
137
+ *
138
+ * A time-of-day is a zone-free wall-clock value (Temporal.PlainTime): it
139
+ * carries no date and no timezone. Values are normalized ISO time strings:
140
+ * `"HH:mm"` (minute granularity) or `"HH:mm:ss"` (second granularity).
141
+ *
142
+ * API conventions match dateParser.ts:
143
+ * parseTime(input, granularity) -> TimeParseResult { value, error }
144
+ * formatIsoTime(h, m, s, granularity) -> string
145
+ * normalizeTime(iso, granularity) -> string
146
+ * An empty or failed result is represented as `value: ""`, not null.
147
+ */
148
+ /** Granularity of a time value: minutes or seconds. */
149
+ type TimeGranularity = "minute" | "second";
150
+ /** Result of {@link parseTime}. */
151
+ interface TimeParseResult {
152
+ /** Normalized ISO time string, or "" when parsing failed or input is empty. */
153
+ value: string;
154
+ /** Error message on failure, or "" on success. */
155
+ error: string;
156
+ }
157
+ /**
158
+ * Format H/M/S integer components as a normalized ISO time string.
159
+ * This is an internal building block; consumers typically use {@link normalizeTime}.
160
+ */
161
+ declare function formatIsoTime(hour: number, minute: number, second: number, granularity?: TimeGranularity): string;
162
+ /**
163
+ * Parse a user-entered time string into a normalized ISO time value.
164
+ *
165
+ * Accepts colon-separated (`"9:30"`, `"21:05:00"`) and compact numeric
166
+ * (`"0930"`, `"213005"`) forms. Missing minutes/seconds default to zero.
167
+ * The shorthands `"."`, `"n"`, and `"now"` resolve to the current time.
168
+ * Empty input returns `{ value: "", error: "" }`.
169
+ */
170
+ declare function parseTime(input: string, granularity?: TimeGranularity): TimeParseResult;
171
+ /**
172
+ * Normalize an ISO time string (`"HH:mm"` or `"HH:mm:ss"`) to the requested
173
+ * granularity. Returns "" for empty or malformed input.
174
+ */
175
+ declare function normalizeTime(iso: string | null | undefined, granularity?: TimeGranularity): string;
176
+ /**
177
+ * Split a plain wall-clock datetime (`"YYYY-MM-DDTHH:mm[:ss]"`) into its date
178
+ * (`"YYYY-MM-DD"`) and time (`"HH:mm[:ss]"`) halves. Missing halves return "".
179
+ */
180
+ declare function splitDateTime(iso: string | null | undefined): {
181
+ date: string;
182
+ time: string;
183
+ };
184
+ /**
185
+ * Join a date (`"YYYY-MM-DD"`) and time (`"HH:mm[:ss]"`) into a plain
186
+ * wall-clock datetime. Returns "" when the date is missing; a missing time
187
+ * yields the date alone.
188
+ */
189
+ declare function joinDateTime(date: string, time: string): string;
190
+
191
+ /**
192
+ * Locale-derived date formatting metadata.
193
+ *
194
+ * Uses the Intl APIs (no dependency) to derive, for a BCP-47 locale:
195
+ * - the day/month/year order and separator, as a DateParser format string
196
+ * - localized short weekday labels
197
+ * - the first day of the week (0 = Sunday .. 6 = Saturday)
198
+ *
199
+ * These drive display and input parsing only; exchanged values stay ISO.
200
+ */
201
+
202
+ /** DateParser format string per precision, derived for a locale. */
203
+ interface LocaleDateFormats {
204
+ year: string;
205
+ month: string;
206
+ day: string;
207
+ }
208
+ /** Derive DateParser format strings for each precision in the given locale. */
209
+ declare function getLocaleDateFormats(locale: string): LocaleDateFormats;
210
+ /** Derive the DateParser format for a single precision in the given locale. */
211
+ declare function getLocaleDateFormat(locale: string, precision: DatePrecision): string;
212
+ /**
213
+ * Localized short weekday labels ordered from the locale's first day of week.
214
+ * Returns 7 entries, e.g. `["Mon","Tue",...]` or `["Sun","Mon",...]`.
215
+ */
216
+ declare function getWeekdayLabels(locale: string): string[];
217
+ /** First day of the week for the locale: 0 = Sunday .. 6 = Saturday. */
218
+ declare function getFirstDayOfWeek(locale: string): number;
219
+
37
220
  /**
38
221
  * Escapes HTML characters to prevent XSS and rendering issues
39
222
  */
@@ -146,4 +329,4 @@ interface PageResult<T> {
146
329
  */
147
330
  declare function toPageResult<T>(rows: T[]): PageResult<T>;
148
331
 
149
- export { FORM_ITEM_ID_FIELD, JSON_CSS_VARIABLES, type NormalizedError, type OffsetRange, type PageMeta, type PageResult, cn, copyTextToClipboard, devLog, errorLog, escapeHtml, formatDate, formatDateTime, formatDateTimeTz, formatJsonValue, formatNumber, formatNumberCompact, generateId, infoLog, isEqual, normalizeError, pluralize, resolvePointerRanges, snakeCaseToTitleCase, toPageResult, useComposedRefs, warnLog };
332
+ export { type CompiledDateFormat, type DateFormatOptions, type DateParseResult, type DatePrecision, FORM_ITEM_ID_FIELD, JSON_CSS_VARIABLES, type LocaleDateFormats, type NormalizedError, type OffsetRange, type PageMeta, type PageResult, type TimeGranularity, type TimeParseResult, cn, compileDateFormat, copyTextToClipboard, devLog, errorLog, escapeHtml, formatDate, formatDateInput, formatDateTime, formatDateTimeTz, formatIsoDate, formatIsoTime, formatJsonValue, formatNumber, formatNumberCompact, generateId, getFirstDayOfWeek, getLocaleDateFormat, getLocaleDateFormats, getWeekdayLabels, infoLog, isDateEqual, isEqual, isoDatePrecision, joinDateTime, normalizeError, normalizeTime, parseDate, parseIsoDate, parseTime, pluralize, resolvePointerRanges, snakeCaseToTitleCase, splitDateTime, toPageResult, useComposedRefs, warnLog };