@mezzanine-ui/core 1.0.3 → 1.1.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,105 @@
1
+ /**
2
+ * Token translation helpers for the Temporal-based CalendarMethods.
3
+ *
4
+ * The other adapters (dayjs/moment/luxon) inherit moment's format token syntax
5
+ * (YYYY/MM/DD/HH/mm/ss/Q/[H]n/gggg/GGGG/ww/WW/...). Temporal has no such API,
6
+ * so we tokenize the format string manually and translate to either:
7
+ * 1. A formatted output string (formatTokens), or
8
+ * 2. A regex with field captures for parsing (buildParseRegex).
9
+ */
10
+ export interface FormatContext {
11
+ year: number;
12
+ month: number;
13
+ day: number;
14
+ hour: number;
15
+ minute: number;
16
+ second: number;
17
+ millisecond: number;
18
+ /** ISO day of week (1=Mon..7=Sun). */
19
+ dayOfWeek: number;
20
+ /**
21
+ * Locale-relative day of week (0=locale firstDay..6). Used by the moment
22
+ * `e` token. For Sunday-first locales this equals `dayOfWeek === 7 ? 0 : dayOfWeek`;
23
+ * for Monday-first it shifts so Monday=0; for Saturday-first Saturday=0.
24
+ */
25
+ localeWeekDay: number;
26
+ isoWeek: number;
27
+ isoWeekYear: number;
28
+ localeWeek: number;
29
+ localeWeekYear: number;
30
+ quarter: number;
31
+ halfYear: 1 | 2;
32
+ monthShort: string;
33
+ monthLong: string;
34
+ weekdayShort: string;
35
+ weekdayLong: string;
36
+ weekdayNarrow: string;
37
+ dayOfYear: number;
38
+ unixMs: number;
39
+ }
40
+ export declare function formatTokens(format: string, ctx: FormatContext): string;
41
+ export type ParseFieldKey = 'year' | 'month' | 'day' | 'hour' | 'hour12' | 'minute' | 'second' | 'millisecond' | 'isoWeek' | 'isoWeekYear' | 'localeWeek' | 'localeWeekYear' | 'quarter' | 'halfYear' | 'meridiem-upper' | 'meridiem-lower'
42
+ /** Captured short month name; resolved against `LocaleNames.monthShort`. */
43
+ | 'month-short'
44
+ /** Captured long month name; resolved against `LocaleNames.monthLong`. */
45
+ | 'month-long'
46
+ /** `Do` ordinal — captured digit only, suffix consumed by regex. */
47
+ | 'day-ordinal'
48
+ /** `S` token — 1-digit centiseconds; multiply by 100 → millisecond. */
49
+ | 'fractional-1'
50
+ /** `SS` token — 2-digit deciseconds; multiply by 10 → millisecond. */
51
+ | 'fractional-2'
52
+ /**
53
+ * `k` / `kk` — 1-24 hour clock used by some locales. The digit 24
54
+ * represents midnight (= hour 0); other values map straight to `hour`.
55
+ */
56
+ | 'hour-1to24'
57
+ /** `DDD` / `DDDD` — day of year (1-366); resolved with `year` to a date. */
58
+ | 'day-of-year'
59
+ /** `x` — Unix epoch milliseconds; standalone enough to derive full datetime. */
60
+ | 'unix-ms'
61
+ /** `X` — Unix epoch seconds; standalone enough to derive full datetime. */
62
+ | 'unix-s'
63
+ /** Weekday tokens / `d` / `e` are consumed but discarded (redundant). */
64
+ | 'skip';
65
+ /**
66
+ * Locale-aware name tables consumed by `buildParseRegex`. Each array is
67
+ * pre-computed by the caller so that `tokens.ts` stays free of `Intl.*` use.
68
+ */
69
+ export interface LocaleNames {
70
+ /** 12 entries, January..December — short form ("Jan"). */
71
+ monthShort: string[];
72
+ /** 12 entries, January..December — long form ("January"). */
73
+ monthLong: string[];
74
+ /** 7 entries, Sunday-indexed — short form ("Mon"). */
75
+ weekdayShort: string[];
76
+ /** 7 entries, Sunday-indexed — long form ("Monday"). */
77
+ weekdayLong: string[];
78
+ /** 7 entries, Sunday-indexed — narrow form ("M"). */
79
+ weekdayNarrow: string[];
80
+ }
81
+ export interface ParsedFields {
82
+ year?: number;
83
+ month?: number;
84
+ day?: number;
85
+ hour?: number;
86
+ hour12?: number;
87
+ minute?: number;
88
+ second?: number;
89
+ millisecond?: number;
90
+ isoWeek?: number;
91
+ isoWeekYear?: number;
92
+ localeWeek?: number;
93
+ localeWeekYear?: number;
94
+ quarter?: number;
95
+ halfYear?: 1 | 2;
96
+ meridiem?: 'am' | 'pm';
97
+ dayOfYear?: number;
98
+ unixMs?: number;
99
+ }
100
+ export declare function buildParseRegex(format: string, names: LocaleNames): {
101
+ regex: RegExp;
102
+ captures: ParseFieldKey[];
103
+ tokens: Set<string>;
104
+ };
105
+ export declare function applyParseRegex(text: string, regex: RegExp, captures: ParseFieldKey[], names: LocaleNames): ParsedFields | undefined;
@@ -0,0 +1,454 @@
1
+ /**
2
+ * Token translation helpers for the Temporal-based CalendarMethods.
3
+ *
4
+ * The other adapters (dayjs/moment/luxon) inherit moment's format token syntax
5
+ * (YYYY/MM/DD/HH/mm/ss/Q/[H]n/gggg/GGGG/ww/WW/...). Temporal has no such API,
6
+ * so we tokenize the format string manually and translate to either:
7
+ * 1. A formatted output string (formatTokens), or
8
+ * 2. A regex with field captures for parsing (buildParseRegex).
9
+ */
10
+ const pad = (value, length = 2) => String(Math.abs(value)).padStart(length, '0');
11
+ const TOKEN_PATTERN = 'YYYY|YY|Y|MMMM|MMM|MM|M|DDDD|DDD|DD|Do|D|dddd|ddd|dd|d|e|HH|H|hh|h|kk|k|mm|m|ss|s|SSS|SS|S|A|a|Q|gggg|GGGG|ww|WW|w|W|x|X';
12
+ const TOKEN_REGEX = new RegExp(TOKEN_PATTERN, 'g');
13
+ function tokenize(format) {
14
+ const segments = [];
15
+ let cursor = 0;
16
+ while (cursor < format.length) {
17
+ if (format[cursor] === '[') {
18
+ const end = format.indexOf(']', cursor);
19
+ if (end === -1) {
20
+ segments.push({ literal: format.slice(cursor) });
21
+ return segments;
22
+ }
23
+ segments.push({ literal: format.slice(cursor + 1, end) });
24
+ cursor = end + 1;
25
+ continue;
26
+ }
27
+ TOKEN_REGEX.lastIndex = cursor;
28
+ const match = TOKEN_REGEX.exec(format);
29
+ if (match && match.index === cursor) {
30
+ segments.push({ token: match[0] });
31
+ cursor += match[0].length;
32
+ continue;
33
+ }
34
+ const nextSpecial = findNextSpecial(format, cursor);
35
+ segments.push({ literal: format.slice(cursor, nextSpecial) });
36
+ cursor = nextSpecial;
37
+ }
38
+ return segments;
39
+ }
40
+ function findNextSpecial(format, from) {
41
+ for (let i = from; i < format.length; i += 1) {
42
+ if (format[i] === '[')
43
+ return i;
44
+ TOKEN_REGEX.lastIndex = i;
45
+ const m = TOKEN_REGEX.exec(format);
46
+ if (m && m.index === i)
47
+ return i;
48
+ }
49
+ return format.length;
50
+ }
51
+ function preprocessHalfYear(format, halfYear) {
52
+ if (!format.includes('[H]n'))
53
+ return format;
54
+ return format.replace('[H]n', `[H${halfYear}]`);
55
+ }
56
+ const hour12 = (hour) => {
57
+ const mod = hour % 12;
58
+ return mod === 0 ? 12 : mod;
59
+ };
60
+ function ordinal(n) {
61
+ var _a, _b;
62
+ const s = ['th', 'st', 'nd', 'rd'];
63
+ const v = n % 100;
64
+ return `${n}${(_b = (_a = s[(v - 20) % 10]) !== null && _a !== void 0 ? _a : s[v]) !== null && _b !== void 0 ? _b : s[0]}`;
65
+ }
66
+ function formatTokens(format, ctx) {
67
+ const normalized = preprocessHalfYear(format, ctx.halfYear);
68
+ const segments = tokenize(normalized);
69
+ return segments
70
+ .map((segment) => {
71
+ if (segment.literal !== undefined)
72
+ return segment.literal;
73
+ const token = segment.token;
74
+ switch (token) {
75
+ case 'YYYY':
76
+ return pad(ctx.year, 4);
77
+ case 'YY':
78
+ return pad(ctx.year % 100, 2);
79
+ case 'Y':
80
+ return String(ctx.year);
81
+ case 'MMMM':
82
+ return ctx.monthLong;
83
+ case 'MMM':
84
+ return ctx.monthShort;
85
+ case 'MM':
86
+ return pad(ctx.month);
87
+ case 'M':
88
+ return String(ctx.month);
89
+ case 'DDDD':
90
+ return pad(ctx.dayOfYear, 3);
91
+ case 'DDD':
92
+ return String(ctx.dayOfYear);
93
+ case 'DD':
94
+ return pad(ctx.day);
95
+ case 'Do':
96
+ return ordinal(ctx.day);
97
+ case 'D':
98
+ return String(ctx.day);
99
+ case 'dddd':
100
+ return ctx.weekdayLong;
101
+ case 'ddd':
102
+ return ctx.weekdayShort;
103
+ case 'dd':
104
+ return ctx.weekdayNarrow;
105
+ case 'd':
106
+ // moment `d`: ISO Sunday-indexed (Sun=0..Sat=6).
107
+ return String(ctx.dayOfWeek === 7 ? 0 : ctx.dayOfWeek);
108
+ case 'e':
109
+ // moment `e`: locale-relative (firstDay=0..6).
110
+ return String(ctx.localeWeekDay);
111
+ case 'HH':
112
+ return pad(ctx.hour);
113
+ case 'H':
114
+ return String(ctx.hour);
115
+ case 'hh':
116
+ return pad(hour12(ctx.hour));
117
+ case 'h':
118
+ return String(hour12(ctx.hour));
119
+ case 'kk':
120
+ return pad(ctx.hour === 0 ? 24 : ctx.hour);
121
+ case 'k':
122
+ return String(ctx.hour === 0 ? 24 : ctx.hour);
123
+ case 'mm':
124
+ return pad(ctx.minute);
125
+ case 'm':
126
+ return String(ctx.minute);
127
+ case 'ss':
128
+ return pad(ctx.second);
129
+ case 's':
130
+ return String(ctx.second);
131
+ case 'SSS':
132
+ return pad(ctx.millisecond, 3);
133
+ case 'SS':
134
+ return pad(Math.floor(ctx.millisecond / 10), 2);
135
+ case 'S':
136
+ return String(Math.floor(ctx.millisecond / 100));
137
+ case 'A':
138
+ return ctx.hour < 12 ? 'AM' : 'PM';
139
+ case 'a':
140
+ return ctx.hour < 12 ? 'am' : 'pm';
141
+ case 'Q':
142
+ return String(ctx.quarter);
143
+ case 'gggg':
144
+ return pad(ctx.localeWeekYear, 4);
145
+ case 'GGGG':
146
+ return pad(ctx.isoWeekYear, 4);
147
+ case 'ww':
148
+ return pad(ctx.localeWeek);
149
+ case 'WW':
150
+ return pad(ctx.isoWeek);
151
+ case 'w':
152
+ return String(ctx.localeWeek);
153
+ case 'W':
154
+ return String(ctx.isoWeek);
155
+ case 'x':
156
+ return String(ctx.unixMs);
157
+ case 'X':
158
+ return String(Math.floor(ctx.unixMs / 1000));
159
+ default:
160
+ return token;
161
+ }
162
+ })
163
+ .join('');
164
+ }
165
+ const HALF_YEAR_SENTINEL = '\x00HALFYEAR\x00';
166
+ function buildParseRegex(format, names) {
167
+ const normalized = format.replace('[H]n', HALF_YEAR_SENTINEL);
168
+ let body = '';
169
+ const captures = [];
170
+ const tokens = new Set();
171
+ let cursor = 0;
172
+ while (cursor < normalized.length) {
173
+ if (normalized.startsWith(HALF_YEAR_SENTINEL, cursor)) {
174
+ body += 'H(\\d)';
175
+ captures.push('halfYear');
176
+ tokens.add('[H]n');
177
+ cursor += HALF_YEAR_SENTINEL.length;
178
+ continue;
179
+ }
180
+ if (normalized[cursor] === '[') {
181
+ const end = normalized.indexOf(']', cursor);
182
+ if (end === -1) {
183
+ body += escapeRegex(normalized.slice(cursor));
184
+ break;
185
+ }
186
+ body += escapeRegex(normalized.slice(cursor + 1, end));
187
+ cursor = end + 1;
188
+ continue;
189
+ }
190
+ TOKEN_REGEX.lastIndex = cursor;
191
+ const match = TOKEN_REGEX.exec(normalized);
192
+ if (match && match.index === cursor) {
193
+ const token = match[0];
194
+ tokens.add(token);
195
+ const result = tokenToCapture(token, names);
196
+ if (result) {
197
+ body += result.pattern;
198
+ if (result.field)
199
+ captures.push(result.field);
200
+ }
201
+ else {
202
+ body += escapeRegex(token);
203
+ }
204
+ cursor += token.length;
205
+ continue;
206
+ }
207
+ const next = findNextSpecialOrSentinel(normalized, cursor);
208
+ body += escapeRegex(normalized.slice(cursor, next));
209
+ cursor = next;
210
+ }
211
+ return {
212
+ regex: new RegExp(`^${body}$`),
213
+ captures,
214
+ tokens,
215
+ };
216
+ }
217
+ /**
218
+ * Build a regex alternation that matches any of the supplied names, longest
219
+ * first to avoid the regex engine matching a prefix of a longer entry.
220
+ */
221
+ function namesAlternation(names) {
222
+ // De-dupe and sort longest-first.
223
+ const sorted = Array.from(new Set(names))
224
+ .filter(Boolean)
225
+ .sort((a, b) => b.length - a.length);
226
+ return `(${sorted.map(escapeRegex).join('|')})`;
227
+ }
228
+ /** Variant that also stops at the half-year sentinel. */
229
+ function findNextSpecialOrSentinel(format, from) {
230
+ for (let i = from; i < format.length; i += 1) {
231
+ if (format[i] === '[')
232
+ return i;
233
+ if (format.startsWith(HALF_YEAR_SENTINEL, i))
234
+ return i;
235
+ TOKEN_REGEX.lastIndex = i;
236
+ const m = TOKEN_REGEX.exec(format);
237
+ if (m && m.index === i)
238
+ return i;
239
+ }
240
+ return format.length;
241
+ }
242
+ function escapeRegex(text) {
243
+ return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
244
+ }
245
+ function tokenToCapture(token, names) {
246
+ switch (token) {
247
+ case 'YYYY':
248
+ return { pattern: '(\\d{4})', field: 'year' };
249
+ case 'YY':
250
+ return { pattern: '(\\d{2})', field: 'year' };
251
+ case 'Y':
252
+ return { pattern: '(\\d{1,4})', field: 'year' };
253
+ case 'MMMM':
254
+ return {
255
+ pattern: namesAlternation(names.monthLong),
256
+ field: 'month-long',
257
+ };
258
+ case 'MMM':
259
+ return {
260
+ pattern: namesAlternation(names.monthShort),
261
+ field: 'month-short',
262
+ };
263
+ case 'MM':
264
+ return { pattern: '(\\d{2})', field: 'month' };
265
+ case 'M':
266
+ return { pattern: '(\\d{1,2})', field: 'month' };
267
+ case 'Do':
268
+ // Capture the digit; consume the ordinal suffix non-capturing.
269
+ return {
270
+ pattern: '(\\d{1,2})(?:st|nd|rd|th)',
271
+ field: 'day-ordinal',
272
+ };
273
+ case 'DDDD':
274
+ return { pattern: '(\\d{3})', field: 'day-of-year' };
275
+ case 'DDD':
276
+ return { pattern: '(\\d{1,3})', field: 'day-of-year' };
277
+ case 'DD':
278
+ return { pattern: '(\\d{2})', field: 'day' };
279
+ case 'D':
280
+ return { pattern: '(\\d{1,2})', field: 'day' };
281
+ case 'dddd':
282
+ return { pattern: namesAlternation(names.weekdayLong), field: 'skip' };
283
+ case 'ddd':
284
+ return { pattern: namesAlternation(names.weekdayShort), field: 'skip' };
285
+ case 'dd':
286
+ return { pattern: namesAlternation(names.weekdayNarrow), field: 'skip' };
287
+ case 'd':
288
+ // ISO Sunday-indexed weekday number — consume but cannot derive date.
289
+ return { pattern: '(\\d)', field: 'skip' };
290
+ case 'e':
291
+ // Locale-relative weekday number — consume but cannot derive date.
292
+ return { pattern: '(\\d)', field: 'skip' };
293
+ case 'HH':
294
+ return { pattern: '(\\d{2})', field: 'hour' };
295
+ case 'H':
296
+ return { pattern: '(\\d{1,2})', field: 'hour' };
297
+ case 'hh':
298
+ return { pattern: '(\\d{2})', field: 'hour12' };
299
+ case 'h':
300
+ return { pattern: '(\\d{1,2})', field: 'hour12' };
301
+ case 'mm':
302
+ return { pattern: '(\\d{2})', field: 'minute' };
303
+ case 'm':
304
+ return { pattern: '(\\d{1,2})', field: 'minute' };
305
+ case 'ss':
306
+ return { pattern: '(\\d{2})', field: 'second' };
307
+ case 's':
308
+ return { pattern: '(\\d{1,2})', field: 'second' };
309
+ case 'SSS':
310
+ return { pattern: '(\\d{3})', field: 'millisecond' };
311
+ case 'SS':
312
+ return { pattern: '(\\d{2})', field: 'fractional-2' };
313
+ case 'S':
314
+ return { pattern: '(\\d)', field: 'fractional-1' };
315
+ case 'kk':
316
+ return { pattern: '(\\d{2})', field: 'hour-1to24' };
317
+ case 'k':
318
+ return { pattern: '(\\d{1,2})', field: 'hour-1to24' };
319
+ case 'A':
320
+ return { pattern: '(AM|PM)', field: 'meridiem-upper' };
321
+ case 'a':
322
+ return { pattern: '(am|pm)', field: 'meridiem-lower' };
323
+ case 'Q':
324
+ return { pattern: '(\\d)', field: 'quarter' };
325
+ case 'gggg':
326
+ return { pattern: '(\\d{4})', field: 'localeWeekYear' };
327
+ case 'GGGG':
328
+ return { pattern: '(\\d{4})', field: 'isoWeekYear' };
329
+ case 'ww':
330
+ return { pattern: '(\\d{2})', field: 'localeWeek' };
331
+ case 'WW':
332
+ return { pattern: '(\\d{2})', field: 'isoWeek' };
333
+ case 'w':
334
+ return { pattern: '(\\d{1,2})', field: 'localeWeek' };
335
+ case 'W':
336
+ return { pattern: '(\\d{1,2})', field: 'isoWeek' };
337
+ case 'x':
338
+ // Unix epoch milliseconds — anchor `$` and adjacent literals constrain
339
+ // the greedy match.
340
+ return { pattern: '(\\d+)', field: 'unix-ms' };
341
+ case 'X':
342
+ // Unix epoch seconds.
343
+ return { pattern: '(\\d+)', field: 'unix-s' };
344
+ default:
345
+ return null;
346
+ }
347
+ }
348
+ function applyParseRegex(text, regex, captures, names) {
349
+ const match = text.match(regex);
350
+ if (!match)
351
+ return undefined;
352
+ const fields = {};
353
+ for (let idx = 0; idx < captures.length; idx += 1) {
354
+ const field = captures[idx];
355
+ const raw = match[idx + 1];
356
+ if (raw === undefined)
357
+ continue;
358
+ if (field === 'skip')
359
+ continue;
360
+ if (field === 'meridiem-upper') {
361
+ fields.meridiem = raw === 'PM' ? 'pm' : 'am';
362
+ continue;
363
+ }
364
+ if (field === 'meridiem-lower') {
365
+ fields.meridiem = raw === 'pm' ? 'pm' : 'am';
366
+ continue;
367
+ }
368
+ if (field === 'month-short' || field === 'month-long') {
369
+ const table = field === 'month-short' ? names.monthShort : names.monthLong;
370
+ const monthIndex = table.indexOf(raw);
371
+ if (monthIndex === -1)
372
+ return undefined;
373
+ fields.month = monthIndex + 1;
374
+ continue;
375
+ }
376
+ if (field === 'day-ordinal') {
377
+ const value = parseInt(raw, 10);
378
+ if (Number.isNaN(value))
379
+ return undefined;
380
+ fields.day = value;
381
+ continue;
382
+ }
383
+ if (field === 'fractional-1') {
384
+ const value = parseInt(raw, 10);
385
+ if (Number.isNaN(value))
386
+ return undefined;
387
+ fields.millisecond = value * 100;
388
+ continue;
389
+ }
390
+ if (field === 'fractional-2') {
391
+ const value = parseInt(raw, 10);
392
+ if (Number.isNaN(value))
393
+ return undefined;
394
+ fields.millisecond = value * 10;
395
+ continue;
396
+ }
397
+ if (field === 'hour-1to24') {
398
+ const value = parseInt(raw, 10);
399
+ if (Number.isNaN(value))
400
+ return undefined;
401
+ if (value < 1 || value > 24)
402
+ return undefined;
403
+ // 24 represents midnight (start of next day in moment), but mezzanine
404
+ // round-trips through ISO so we map it to hour 0 of the same day.
405
+ fields.hour = value === 24 ? 0 : value;
406
+ continue;
407
+ }
408
+ if (field === 'day-of-year') {
409
+ const value = parseInt(raw, 10);
410
+ if (Number.isNaN(value))
411
+ return undefined;
412
+ // Validate against max possible (366 for leap year). Tighter validation
413
+ // against the actual `year` happens in the parseFormattedValue branch.
414
+ if (value < 1 || value > 366)
415
+ return undefined;
416
+ fields.dayOfYear = value;
417
+ continue;
418
+ }
419
+ if (field === 'unix-ms') {
420
+ const value = Number(raw);
421
+ if (!Number.isFinite(value))
422
+ return undefined;
423
+ fields.unixMs = value;
424
+ continue;
425
+ }
426
+ if (field === 'unix-s') {
427
+ const value = Number(raw);
428
+ if (!Number.isFinite(value))
429
+ return undefined;
430
+ fields.unixMs = value * 1000;
431
+ continue;
432
+ }
433
+ const value = parseInt(raw, 10);
434
+ if (Number.isNaN(value))
435
+ continue;
436
+ if (field === 'halfYear') {
437
+ if (value !== 1 && value !== 2)
438
+ continue;
439
+ fields.halfYear = value;
440
+ continue;
441
+ }
442
+ if (field === 'year' && raw.length === 2) {
443
+ // 2-digit year pivot matches moment.js / dayjs behaviour:
444
+ // 00..68 → 2000..2068
445
+ // 69..99 → 1969..1999
446
+ fields.year = value > 68 ? value + 1900 : value + 2000;
447
+ continue;
448
+ }
449
+ fields[field] = value;
450
+ }
451
+ return fields;
452
+ }
453
+
454
+ export { applyParseRegex, buildParseRegex, formatTokens };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mezzanine-ui/core",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "description": "Core for mezzanine-ui",
5
5
  "author": "Mezzanine",
6
6
  "repository": {
@@ -23,12 +23,16 @@
23
23
  "build:clean": "node ../../scripts/cleanBuild.js"
24
24
  },
25
25
  "peerDependencies": {
26
+ "@js-temporal/polyfill": ">=0.5",
26
27
  "dayjs": ">=1",
27
28
  "lodash": ">=4",
28
29
  "luxon": ">=3",
29
30
  "moment": ">=2"
30
31
  },
31
32
  "peerDependenciesMeta": {
33
+ "@js-temporal/polyfill": {
34
+ "optional": true
35
+ },
32
36
  "dayjs": {
33
37
  "optional": true
34
38
  },
@@ -46,6 +50,8 @@
46
50
  "tslib": "^2.8.1"
47
51
  },
48
52
  "devDependencies": {
53
+ "@js-temporal/polyfill": "^0.5.1",
49
54
  "@types/luxon": "^3.6.2"
50
- }
55
+ },
56
+ "gitHead": "f5fa136dac936a0debafff9ea5a3815ff0b5c040"
51
57
  }