@mezzanine-ui/core 1.0.4 → 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.
- package/calendar/calendar.d.ts +18 -3
- package/calendar/calendar.js +18 -23
- package/calendarMethodsDayjs/index.js +54 -12
- package/calendarMethodsMoment/index.js +31 -14
- package/calendarMethodsTemporal/index.d.ts +27 -0
- package/calendarMethodsTemporal/index.js +912 -0
- package/calendarMethodsTemporal/tokens.d.ts +105 -0
- package/calendarMethodsTemporal/tokens.js +454 -0
- package/package.json +8 -2
package/calendar/calendar.d.ts
CHANGED
|
@@ -76,9 +76,24 @@ export declare const calendarHalfYearYearsCount = 5;
|
|
|
76
76
|
export declare function getYearRange(year: number, mod: number): number[];
|
|
77
77
|
export declare function getCalendarYearRange(year: number): number[];
|
|
78
78
|
/**
|
|
79
|
-
* Locales that
|
|
80
|
-
*
|
|
81
|
-
*
|
|
79
|
+
* Locales that follow ISO 8601 week rules — Monday is the first day of week
|
|
80
|
+
* AND week 1 contains at least 4 days of the new year (`minimalDays = 4`).
|
|
81
|
+
*
|
|
82
|
+
* Audited against `Intl.Locale#weekInfo` (CLDR). Entries previously listed
|
|
83
|
+
* here that disagree with CLDR were removed:
|
|
84
|
+
* - `pt-pt`, `pt` → Sunday-first per CLDR (was emitting wrong week
|
|
85
|
+
* boundaries for Portuguese)
|
|
86
|
+
* - `he-il`, `he` → Sunday-first per CLDR
|
|
87
|
+
* - `ar-sa`, `ar` → Sunday-first / Saturday-first per CLDR
|
|
88
|
+
* - `en-au`, `en-nz` → Monday-first BUT minimalDays=1, NOT ISO
|
|
89
|
+
* - `ro-ro`, `ro`, `sl-si`, `sl`, `hr-hr`, `hr`, `tr-tr`, `tr`,
|
|
90
|
+
* `uk-ua`, `uk`, `lv-lv`, `lv` → Monday-first BUT minimalDays=1
|
|
91
|
+
*
|
|
92
|
+
* The Temporal adapter consumes `Intl.Locale#weekInfo` directly (see
|
|
93
|
+
* `usesISOWeekRules` in calendarMethodsTemporal). The dayjs/moment
|
|
94
|
+
* adapters still use this static set; the removals above also fix
|
|
95
|
+
* silent format/getWeek divergences in those adapters for the affected
|
|
96
|
+
* locales when CLDR data is the desired source of truth.
|
|
82
97
|
*/
|
|
83
98
|
export declare const ISO_WEEK_LOCALES: Set<string>;
|
|
84
99
|
/**
|
package/calendar/calendar.js
CHANGED
|
@@ -82,9 +82,24 @@ function getCalendarYearRange(year) {
|
|
|
82
82
|
return [start, end];
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
85
|
-
* Locales that
|
|
86
|
-
*
|
|
87
|
-
*
|
|
85
|
+
* Locales that follow ISO 8601 week rules — Monday is the first day of week
|
|
86
|
+
* AND week 1 contains at least 4 days of the new year (`minimalDays = 4`).
|
|
87
|
+
*
|
|
88
|
+
* Audited against `Intl.Locale#weekInfo` (CLDR). Entries previously listed
|
|
89
|
+
* here that disagree with CLDR were removed:
|
|
90
|
+
* - `pt-pt`, `pt` → Sunday-first per CLDR (was emitting wrong week
|
|
91
|
+
* boundaries for Portuguese)
|
|
92
|
+
* - `he-il`, `he` → Sunday-first per CLDR
|
|
93
|
+
* - `ar-sa`, `ar` → Sunday-first / Saturday-first per CLDR
|
|
94
|
+
* - `en-au`, `en-nz` → Monday-first BUT minimalDays=1, NOT ISO
|
|
95
|
+
* - `ro-ro`, `ro`, `sl-si`, `sl`, `hr-hr`, `hr`, `tr-tr`, `tr`,
|
|
96
|
+
* `uk-ua`, `uk`, `lv-lv`, `lv` → Monday-first BUT minimalDays=1
|
|
97
|
+
*
|
|
98
|
+
* The Temporal adapter consumes `Intl.Locale#weekInfo` directly (see
|
|
99
|
+
* `usesISOWeekRules` in calendarMethodsTemporal). The dayjs/moment
|
|
100
|
+
* adapters still use this static set; the removals above also fix
|
|
101
|
+
* silent format/getWeek divergences in those adapters for the affected
|
|
102
|
+
* locales when CLDR data is the desired source of truth.
|
|
88
103
|
*/
|
|
89
104
|
const ISO_WEEK_LOCALES = new Set([
|
|
90
105
|
'de-de',
|
|
@@ -99,8 +114,6 @@ const ISO_WEEK_LOCALES = new Set([
|
|
|
99
114
|
'nl',
|
|
100
115
|
'pl-pl',
|
|
101
116
|
'pl',
|
|
102
|
-
'pt-pt',
|
|
103
|
-
'pt',
|
|
104
117
|
'ru-ru',
|
|
105
118
|
'ru',
|
|
106
119
|
'sv-se',
|
|
@@ -115,35 +128,17 @@ const ISO_WEEK_LOCALES = new Set([
|
|
|
115
128
|
'cs',
|
|
116
129
|
'hu-hu',
|
|
117
130
|
'hu',
|
|
118
|
-
'ro-ro',
|
|
119
|
-
'ro',
|
|
120
131
|
'sk-sk',
|
|
121
132
|
'sk',
|
|
122
|
-
'sl-si',
|
|
123
|
-
'sl',
|
|
124
|
-
'hr-hr',
|
|
125
|
-
'hr',
|
|
126
133
|
'bg-bg',
|
|
127
134
|
'bg',
|
|
128
135
|
'el-gr',
|
|
129
136
|
'el',
|
|
130
|
-
'tr-tr',
|
|
131
|
-
'tr',
|
|
132
|
-
'uk-ua',
|
|
133
|
-
'uk',
|
|
134
|
-
'he-il',
|
|
135
|
-
'he',
|
|
136
|
-
'ar-sa',
|
|
137
|
-
'ar',
|
|
138
137
|
'et-ee',
|
|
139
138
|
'et',
|
|
140
|
-
'lv-lv',
|
|
141
|
-
'lv',
|
|
142
139
|
'lt-lt',
|
|
143
140
|
'lt',
|
|
144
141
|
'en-gb',
|
|
145
|
-
'en-au',
|
|
146
|
-
'en-nz',
|
|
147
142
|
]);
|
|
148
143
|
/**
|
|
149
144
|
* Check if a locale uses ISO week (Monday as first day of week)
|
|
@@ -150,6 +150,17 @@ const getActualFirstDayOfWeek = (locale) => {
|
|
|
150
150
|
const isMondayFirst = (locale) => {
|
|
151
151
|
return getActualFirstDayOfWeek(locale) === 1;
|
|
152
152
|
};
|
|
153
|
+
/**
|
|
154
|
+
* Whether the locale should be week-numbered using the ISO 8601 algorithm.
|
|
155
|
+
* Requires BOTH Monday-first AND `isISOWeekLocale` (i.e. minimalDays=4 per
|
|
156
|
+
* CLDR). For Monday-first locales whose CLDR `minimalDays` is 1 (en-AU,
|
|
157
|
+
* en-NZ, ro-RO, tr-TR, sl-SI, hr-HR, uk-UA, lv-LV …) this returns false so
|
|
158
|
+
* `getWeek`/`getWeekYear`/format `gggg/ww` use locale week numbering and
|
|
159
|
+
* stay consistent with `getDefaultModeFormat`.
|
|
160
|
+
*/
|
|
161
|
+
const usesISOWeekRules = (locale) => {
|
|
162
|
+
return isMondayFirst(locale) && isISOWeekLocale(locale);
|
|
163
|
+
};
|
|
153
164
|
const CalendarMethodsDayjs = {
|
|
154
165
|
/** Locale helpers */
|
|
155
166
|
getFirstDayOfWeek: (locale) => getActualFirstDayOfWeek(locale),
|
|
@@ -161,16 +172,36 @@ const CalendarMethodsDayjs = {
|
|
|
161
172
|
getHour: (date) => dayjs(date).hour(),
|
|
162
173
|
getDate: (date) => dayjs(date).date(),
|
|
163
174
|
getWeek: (date, locale) => {
|
|
164
|
-
if (
|
|
175
|
+
if (usesISOWeekRules(locale)) {
|
|
165
176
|
return dayjs(date).isoWeek();
|
|
166
177
|
}
|
|
167
|
-
|
|
178
|
+
// `.week()` reads the dayjs instance's locale (firstDayOfWeek + doy).
|
|
179
|
+
// Apply the requested locale explicitly — otherwise the global default
|
|
180
|
+
// (usually `en` Sunday-first) would be used, breaking Monday-first
|
|
181
|
+
// non-ISO locales such as en-AU / ro-RO.
|
|
182
|
+
return dayjs(date).locale(localeMapping(locale)).week();
|
|
168
183
|
},
|
|
169
184
|
getWeekYear: (date, locale) => {
|
|
170
|
-
if (
|
|
185
|
+
if (usesISOWeekRules(locale)) {
|
|
171
186
|
return dayjs(date).isoWeekYear();
|
|
172
187
|
}
|
|
173
|
-
|
|
188
|
+
// dayjs has no native locale `.weekYear()`. Use the same heuristic as
|
|
189
|
+
// moment.js: when the date sits on a year boundary that crosses week
|
|
190
|
+
// boundaries, the weekYear differs from the calendar year.
|
|
191
|
+
// • early-January (month=0) with week >= 52 → previous calendar's
|
|
192
|
+
// final week. weekYear = year - 1.
|
|
193
|
+
// • late-December (month=11) with week === 1 → next calendar's first
|
|
194
|
+
// week. weekYear = year + 1.
|
|
195
|
+
// • otherwise weekYear = year.
|
|
196
|
+
const d = dayjs(date).locale(localeMapping(locale));
|
|
197
|
+
const week = d.week();
|
|
198
|
+
const month = d.month();
|
|
199
|
+
const year = d.year();
|
|
200
|
+
if (month === 0 && week >= 52)
|
|
201
|
+
return year - 1;
|
|
202
|
+
if (month === 11 && week === 1)
|
|
203
|
+
return year + 1;
|
|
204
|
+
return year;
|
|
174
205
|
},
|
|
175
206
|
getWeekDay: (date) => {
|
|
176
207
|
const clone = dayjs(date).locale('en');
|
|
@@ -223,7 +254,7 @@ const CalendarMethodsDayjs = {
|
|
|
223
254
|
setDate: (date, target) => dayjs(date).date(target).toISOString(),
|
|
224
255
|
startOf: (target, granularity) => dayjs(target).startOf(granularity).toISOString(),
|
|
225
256
|
getCurrentWeekFirstDate: (value, locale) => {
|
|
226
|
-
if (
|
|
257
|
+
if (usesISOWeekRules(locale)) {
|
|
227
258
|
return dayjs(value)
|
|
228
259
|
.startOf('isoWeek')
|
|
229
260
|
.hour(0)
|
|
@@ -232,7 +263,10 @@ const CalendarMethodsDayjs = {
|
|
|
232
263
|
.millisecond(0)
|
|
233
264
|
.toISOString();
|
|
234
265
|
}
|
|
266
|
+
// `.startOf('week')` honors the instance locale's firstDayOfWeek, so
|
|
267
|
+
// apply the requested locale before truncating.
|
|
235
268
|
return dayjs(value)
|
|
269
|
+
.locale(localeMapping(locale))
|
|
236
270
|
.startOf('week')
|
|
237
271
|
.hour(0)
|
|
238
272
|
.minute(0)
|
|
@@ -314,18 +348,23 @@ const CalendarMethodsDayjs = {
|
|
|
314
348
|
isBetween: (value, target1, target2, granularity) => dayjs(value).isBetween(target1, target2, granularity),
|
|
315
349
|
isSameDate: (dateOne, dateTwo) => dayjs(dateOne).isSame(dayjs(dateTwo), 'date'),
|
|
316
350
|
isSameWeek: (dateOne, dateTwo, locale) => {
|
|
317
|
-
if (
|
|
351
|
+
if (usesISOWeekRules(locale)) {
|
|
318
352
|
return dayjs(dateOne).isSame(dayjs(dateTwo), 'isoWeek');
|
|
319
353
|
}
|
|
320
|
-
|
|
354
|
+
// `'week'` granularity uses the calling instance's locale — set locale
|
|
355
|
+
// on the comparator so non-ISO Monday-first locales align correctly.
|
|
356
|
+
return dayjs(dateOne)
|
|
357
|
+
.locale(localeMapping(locale))
|
|
358
|
+
.isSame(dayjs(dateTwo), 'week');
|
|
321
359
|
},
|
|
322
360
|
isInMonth: (target, month) => dayjs(target).month() === month,
|
|
323
361
|
isDateIncluded: (date, targets) => targets.some((target) => dayjs(date).isSame(dayjs(target), 'day')),
|
|
324
362
|
isWeekIncluded: (firstDateOfWeek, targets, locale) => {
|
|
325
|
-
if (
|
|
363
|
+
if (usesISOWeekRules(locale)) {
|
|
326
364
|
return targets.some((target) => dayjs(firstDateOfWeek).isSame(dayjs(target), 'isoWeek'));
|
|
327
365
|
}
|
|
328
|
-
|
|
366
|
+
const mappedLocale = localeMapping(locale);
|
|
367
|
+
return targets.some((target) => dayjs(firstDateOfWeek).locale(mappedLocale).isSame(dayjs(target), 'week'));
|
|
329
368
|
},
|
|
330
369
|
isMonthIncluded: (date, targets) => targets.some((target) => dayjs(date).isSame(dayjs(target), 'month')),
|
|
331
370
|
isYearIncluded: (date, targets) => targets.some((target) => dayjs(date).isSame(dayjs(target), 'year')),
|
|
@@ -353,9 +392,12 @@ const CalendarMethodsDayjs = {
|
|
|
353
392
|
// ISO values because dayjs does not expose a locale `weekYear()`).
|
|
354
393
|
// - GGGG / WW: ISO-8601 week year / number regardless of locale.
|
|
355
394
|
if (format.includes('gggg') || format.includes('GGGG')) {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
395
|
+
// Use ISO values for `gggg`/`ww` only when the locale truly uses
|
|
396
|
+
// ISO 8601 week rules. Monday-first non-ISO locales (e.g. en-AU,
|
|
397
|
+
// ro-RO) must emit locale-week values so format and getWeek agree.
|
|
398
|
+
const useISO = usesISOWeekRules(locale);
|
|
399
|
+
const localeYear = useISO ? result.isoWeekYear() : result.year();
|
|
400
|
+
const localeWeek = useISO ? result.isoWeek() : result.week();
|
|
359
401
|
const isoYear = result.isoWeekYear();
|
|
360
402
|
const isoWeek = result.isoWeek();
|
|
361
403
|
return format
|
|
@@ -17,6 +17,17 @@ const getActualFirstDayOfWeek = (locale) => {
|
|
|
17
17
|
const isMondayFirst = (locale) => {
|
|
18
18
|
return getActualFirstDayOfWeek(locale) === 1;
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Whether the locale should be week-numbered using the ISO 8601 algorithm.
|
|
22
|
+
* Requires BOTH Monday-first AND `isISOWeekLocale` (i.e. minimalDays=4 per
|
|
23
|
+
* CLDR). For Monday-first locales whose CLDR `minimalDays` is 1 (en-AU,
|
|
24
|
+
* en-NZ, ro-RO, tr-TR, sl-SI, hr-HR, uk-UA, lv-LV …) this returns false so
|
|
25
|
+
* `getWeek`/`getWeekYear` use locale week numbering and stay consistent
|
|
26
|
+
* with `getDefaultModeFormat`.
|
|
27
|
+
*/
|
|
28
|
+
const usesISOWeekRules = (locale) => {
|
|
29
|
+
return isMondayFirst(locale) && isISOWeekLocale(locale);
|
|
30
|
+
};
|
|
20
31
|
const CalendarMethodsMoment = {
|
|
21
32
|
/** Get date infos */
|
|
22
33
|
getNow: () => moment().toISOString(),
|
|
@@ -25,16 +36,20 @@ const CalendarMethodsMoment = {
|
|
|
25
36
|
getHour: (date) => moment(date).hour(),
|
|
26
37
|
getDate: (date) => moment(date).date(),
|
|
27
38
|
getWeek: (date, locale) => {
|
|
28
|
-
if (
|
|
39
|
+
if (usesISOWeekRules(locale)) {
|
|
29
40
|
return moment(date).isoWeek();
|
|
30
41
|
}
|
|
31
|
-
|
|
42
|
+
// `.week()` reads the moment instance's locale (firstDayOfWeek + doy).
|
|
43
|
+
// Apply the requested locale explicitly — otherwise the global default
|
|
44
|
+
// (usually `en-US` Sunday-first) would be used, breaking Monday-first
|
|
45
|
+
// non-ISO locales such as ro-RO / tr-TR.
|
|
46
|
+
return moment(date).locale(locale).week();
|
|
32
47
|
},
|
|
33
48
|
getWeekYear: (date, locale) => {
|
|
34
|
-
if (
|
|
49
|
+
if (usesISOWeekRules(locale)) {
|
|
35
50
|
return moment(date).isoWeekYear();
|
|
36
51
|
}
|
|
37
|
-
return moment(date).weekYear();
|
|
52
|
+
return moment(date).locale(locale).weekYear();
|
|
38
53
|
},
|
|
39
54
|
getWeekDay: (date) => {
|
|
40
55
|
const clone = moment(date).locale('en_US');
|
|
@@ -127,10 +142,9 @@ const CalendarMethodsMoment = {
|
|
|
127
142
|
},
|
|
128
143
|
startOf: (target, granularity) => moment(target).startOf(granularity).toISOString(),
|
|
129
144
|
getCurrentWeekFirstDate: (value, locale) => {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return m
|
|
145
|
+
if (usesISOWeekRules(locale)) {
|
|
146
|
+
// Monday-first AND ISO: starts on Monday using ISO week.
|
|
147
|
+
return moment(value)
|
|
134
148
|
.startOf('isoWeek')
|
|
135
149
|
.hour(0)
|
|
136
150
|
.minute(0)
|
|
@@ -138,8 +152,10 @@ const CalendarMethodsMoment = {
|
|
|
138
152
|
.millisecond(0)
|
|
139
153
|
.toISOString();
|
|
140
154
|
}
|
|
141
|
-
//
|
|
142
|
-
|
|
155
|
+
// Otherwise: locale-week start. `.startOf('week')` uses the instance
|
|
156
|
+
// locale's firstDayOfWeek, so apply the requested locale first.
|
|
157
|
+
return moment(value)
|
|
158
|
+
.locale(locale)
|
|
143
159
|
.startOf('week')
|
|
144
160
|
.hour(0)
|
|
145
161
|
.minute(0)
|
|
@@ -220,18 +236,19 @@ const CalendarMethodsMoment = {
|
|
|
220
236
|
isBetween: (value, target1, target2, granularity) => moment(value).isBetween(target1, target2, granularity),
|
|
221
237
|
isSameDate: (dateOne, dateTwo) => moment(dateOne).isSame(moment(dateTwo), 'date'),
|
|
222
238
|
isSameWeek: (dateOne, dateTwo, locale = 'en-us') => {
|
|
223
|
-
if (
|
|
239
|
+
if (usesISOWeekRules(locale)) {
|
|
224
240
|
return moment(dateOne).isSame(moment(dateTwo), 'isoWeek');
|
|
225
241
|
}
|
|
226
|
-
|
|
242
|
+
// `'week'` granularity uses the calling instance's locale.
|
|
243
|
+
return moment(dateOne).locale(locale).isSame(moment(dateTwo), 'week');
|
|
227
244
|
},
|
|
228
245
|
isInMonth: (target, month) => moment(target).month() === month,
|
|
229
246
|
isDateIncluded: (date, targets) => targets.some((target) => moment(date).isSame(moment(target), 'day')),
|
|
230
247
|
isWeekIncluded: (firstDateOfWeek, targets, locale = 'en-us') => {
|
|
231
|
-
if (
|
|
248
|
+
if (usesISOWeekRules(locale)) {
|
|
232
249
|
return targets.some((target) => moment(firstDateOfWeek).isSame(moment(target), 'isoWeek'));
|
|
233
250
|
}
|
|
234
|
-
return targets.some((target) => moment(firstDateOfWeek).isSame(moment(target), 'week'));
|
|
251
|
+
return targets.some((target) => moment(firstDateOfWeek).locale(locale).isSame(moment(target), 'week'));
|
|
235
252
|
},
|
|
236
253
|
isMonthIncluded: (date, targets) => targets.some((target) => moment(date).isSame(moment(target), 'month')),
|
|
237
254
|
isYearIncluded: (date, targets) => targets.some((target) => moment(date).isSame(moment(target), 'year')),
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CalendarMethodsTemporal — JS-native Temporal implementation of CalendarMethods.
|
|
3
|
+
*
|
|
4
|
+
* Wire format: ISO 8601 string (matches the moment/dayjs adapters, NOT the
|
|
5
|
+
* `Temporal.PlainDateTime#toString()` form). The internal representation is
|
|
6
|
+
* `Temporal.ZonedDateTime` in the system time zone, mirroring how dayjs/moment
|
|
7
|
+
* default to local time when reading/writing ISO strings.
|
|
8
|
+
*
|
|
9
|
+
* Locale week support: uses `Intl.Locale(locale).weekInfo` (Stage 3 / widely
|
|
10
|
+
* available) to determine the first day of week and minimal days in week 1.
|
|
11
|
+
* Falls back to the static ISO_WEEK_LOCALES set when `weekInfo` is missing
|
|
12
|
+
* from the runtime.
|
|
13
|
+
*
|
|
14
|
+
* Polyfill: this module relies on `globalThis.Temporal`. Apps that need to
|
|
15
|
+
* support Safari or Node SSR must install `@js-temporal/polyfill` and
|
|
16
|
+
* register it on `globalThis` from a Client Component (or equivalent client
|
|
17
|
+
* entry point) BEFORE this module is imported:
|
|
18
|
+
*
|
|
19
|
+
* import { Temporal } from '@js-temporal/polyfill';
|
|
20
|
+
* (globalThis as { Temporal?: unknown }).Temporal = Temporal;
|
|
21
|
+
*
|
|
22
|
+
* If Temporal is not present at the time any method is invoked, the call
|
|
23
|
+
* throws with the same installation guide.
|
|
24
|
+
*/
|
|
25
|
+
import { CalendarMethods as CalendarMethodsType } from '../calendar/typings';
|
|
26
|
+
declare const CalendarMethodsTemporal: CalendarMethodsType;
|
|
27
|
+
export default CalendarMethodsTemporal;
|