@kalyx/core 0.3.0 → 1.0.0-rc.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/dist/index.cjs CHANGED
@@ -25,6 +25,7 @@ __export(index_exports, {
25
25
  DEFAULT_RANGEPICKER_LABELS: () => DEFAULT_RANGEPICKER_LABELS,
26
26
  DEFAULT_TIMEPICKER_LABELS: () => DEFAULT_TIMEPICKER_LABELS,
27
27
  DateFnsAdapter: () => DateFnsAdapter,
28
+ civilMidnightFromUtcDay: () => civilMidnightFromUtcDay,
28
29
  formatFullDate: () => formatFullDate,
29
30
  formatInTimezone: () => formatInTimezone,
30
31
  formatMonthYear: () => formatMonthYear,
@@ -35,6 +36,7 @@ __export(index_exports, {
35
36
  getCalendarDays: () => getCalendarDays,
36
37
  getMonthName: () => getMonthName,
37
38
  getTime: () => getTime,
39
+ getTimeInTimezone: () => getTimeInTimezone,
38
40
  getTimezoneOffsetMinutes: () => getTimezoneOffsetMinutes,
39
41
  getWeekdayNames: () => getWeekdayNames,
40
42
  isDateDisabled: () => isDateDisabled,
@@ -46,6 +48,7 @@ __export(index_exports, {
46
48
  parseInputValue: () => parseInputValue,
47
49
  parseTimeString: () => parseTimeString,
48
50
  setTime: () => setTime,
51
+ setTimeInTimezone: () => setTimeInTimezone,
49
52
  startOfDayInTimezone: () => startOfDayInTimezone,
50
53
  to12Hour: () => to12Hour,
51
54
  to24Hour: () => to24Hour,
@@ -54,9 +57,116 @@ __export(index_exports, {
54
57
  module.exports = __toCommonJS(index_exports);
55
58
 
56
59
  // src/adapters/date-fns.ts
60
+ var import_date_fns2 = require("date-fns");
61
+
62
+ // src/utils/timezone.ts
57
63
  var import_date_fns = require("date-fns");
64
+ var formatterCache = /* @__PURE__ */ new Map();
65
+ function getCachedPartsFormatter(timeZone) {
66
+ const key = `parts:${timeZone}`;
67
+ let fmt = formatterCache.get(key);
68
+ if (!fmt) {
69
+ fmt = new Intl.DateTimeFormat("en-US", {
70
+ timeZone,
71
+ year: "numeric",
72
+ month: "2-digit",
73
+ day: "2-digit",
74
+ hour: "2-digit",
75
+ minute: "2-digit",
76
+ second: "2-digit",
77
+ hourCycle: "h23"
78
+ });
79
+ formatterCache.set(key, fmt);
80
+ }
81
+ return fmt;
82
+ }
83
+ function partsInTimezone(utc, timeZone) {
84
+ const dtf = getCachedPartsFormatter(timeZone);
85
+ const parts = Object.fromEntries(
86
+ dtf.formatToParts(utc).map((p) => [p.type, p.value])
87
+ );
88
+ return {
89
+ year: Number(parts.year),
90
+ month: Number(parts.month),
91
+ day: Number(parts.day),
92
+ // Some locales/engines return '24' instead of '0' at midnight
93
+ hour: parts.hour === "24" ? 0 : Number(parts.hour),
94
+ minute: Number(parts.minute),
95
+ second: Number(parts.second)
96
+ };
97
+ }
98
+ function formatInTimezone(iso, formatStr, timeZone) {
99
+ const p = partsInTimezone((0, import_date_fns.parseISO)(iso), timeZone);
100
+ const tokens = {
101
+ yyyy: String(p.year),
102
+ MM: String(p.month).padStart(2, "0"),
103
+ dd: String(p.day).padStart(2, "0"),
104
+ HH: String(p.hour).padStart(2, "0"),
105
+ mm: String(p.minute).padStart(2, "0"),
106
+ ss: String(p.second).padStart(2, "0")
107
+ };
108
+ let result = formatStr;
109
+ for (const [token, value] of Object.entries(tokens).sort((a, b) => b[0].length - a[0].length)) {
110
+ result = result.split(token).join(value);
111
+ }
112
+ return result;
113
+ }
114
+ function getTimezoneOffsetMinutes(iso, timeZone) {
115
+ const utc = (0, import_date_fns.parseISO)(iso);
116
+ const p = partsInTimezone(utc, timeZone);
117
+ const asUtcEpoch = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute, p.second);
118
+ return Math.round((asUtcEpoch - utc.getTime()) / 6e4);
119
+ }
120
+ function startOfDayInTimezone(iso, timeZone) {
121
+ const utc = (0, import_date_fns.parseISO)(iso);
122
+ const p = partsInTimezone(utc, timeZone);
123
+ const civilMidnightUtc = Date.UTC(p.year, p.month - 1, p.day, 0, 0, 0);
124
+ const midnightProbe = new Date(civilMidnightUtc).toISOString();
125
+ const offsetMinutes = getTimezoneOffsetMinutes(midnightProbe, timeZone);
126
+ return new Date(civilMidnightUtc - offsetMinutes * 6e4).toISOString();
127
+ }
128
+ function isSameDayInTimezone(a, b, timeZone) {
129
+ const pa = partsInTimezone((0, import_date_fns.parseISO)(a), timeZone);
130
+ const pb = partsInTimezone((0, import_date_fns.parseISO)(b), timeZone);
131
+ return pa.year === pb.year && pa.month === pb.month && pa.day === pb.day;
132
+ }
133
+ function todayInTimezone(timeZone) {
134
+ return startOfDayInTimezone((/* @__PURE__ */ new Date()).toISOString(), timeZone);
135
+ }
136
+ function civilMidnightFromUtcDay(gridUtcIso, timeZone) {
137
+ const utc = (0, import_date_fns.parseISO)(gridUtcIso);
138
+ const probe = new Date(Date.UTC(
139
+ utc.getUTCFullYear(),
140
+ utc.getUTCMonth(),
141
+ utc.getUTCDate(),
142
+ 12,
143
+ 0,
144
+ 0
145
+ )).toISOString();
146
+ return startOfDayInTimezone(probe, timeZone);
147
+ }
148
+ function getTimeInTimezone(iso, timeZone) {
149
+ const p = partsInTimezone((0, import_date_fns.parseISO)(iso), timeZone);
150
+ return { hours: p.hour, minutes: p.minute, seconds: p.second };
151
+ }
152
+ function setTimeInTimezone(iso, partial, timeZone) {
153
+ const p = partsInTimezone((0, import_date_fns.parseISO)(iso), timeZone);
154
+ const targetHours = partial.hours ?? p.hour;
155
+ const targetMinutes = partial.minutes ?? p.minute;
156
+ const targetSeconds = partial.seconds ?? p.second;
157
+ const civilEpoch = Date.UTC(p.year, p.month - 1, p.day, targetHours, targetMinutes, targetSeconds);
158
+ const probe1 = new Date(civilEpoch).toISOString();
159
+ const offset1 = getTimezoneOffsetMinutes(probe1, timeZone);
160
+ const realEpoch1 = civilEpoch - offset1 * 6e4;
161
+ const probe2 = new Date(realEpoch1).toISOString();
162
+ const offset2 = getTimezoneOffsetMinutes(probe2, timeZone);
163
+ const realEpoch2 = civilEpoch - offset2 * 6e4;
164
+ return new Date(realEpoch2).toISOString();
165
+ }
166
+
167
+ // src/adapters/date-fns.ts
58
168
  function toDate(iso) {
59
- return (0, import_date_fns.parseISO)(iso);
169
+ return (0, import_date_fns2.parseISO)(iso);
60
170
  }
61
171
  function toISO(date) {
62
172
  return date.toISOString();
@@ -98,7 +208,10 @@ var DateFnsAdapter = {
98
208
  if (!value) return "";
99
209
  return normalize(value);
100
210
  },
101
- format(iso, formatStr) {
211
+ format(iso, formatStr, timezone) {
212
+ if (timezone) {
213
+ return formatInTimezone(iso, formatStr, timezone);
214
+ }
102
215
  const d = toDate(iso);
103
216
  const tokens = {
104
217
  yyyy: String(d.getUTCFullYear()),
@@ -117,22 +230,25 @@ var DateFnsAdapter = {
117
230
  return result;
118
231
  },
119
232
  addDays(iso, n) {
120
- return toISO((0, import_date_fns.addDays)(toDate(iso), n));
233
+ return toISO((0, import_date_fns2.addDays)(toDate(iso), n));
121
234
  },
122
235
  addMonths(iso, n) {
123
- return toISO((0, import_date_fns.addMonths)(toDate(iso), n));
236
+ return toISO((0, import_date_fns2.addMonths)(toDate(iso), n));
124
237
  },
125
238
  addYears(iso, n) {
126
- return toISO((0, import_date_fns.addYears)(toDate(iso), n));
239
+ return toISO((0, import_date_fns2.addYears)(toDate(iso), n));
127
240
  },
128
241
  isBefore(a, b) {
129
- return (0, import_date_fns.isBefore)(toDate(a), toDate(b));
242
+ return (0, import_date_fns2.isBefore)(toDate(a), toDate(b));
130
243
  },
131
244
  isAfter(a, b) {
132
- return (0, import_date_fns.isAfter)(toDate(a), toDate(b));
245
+ return (0, import_date_fns2.isAfter)(toDate(a), toDate(b));
133
246
  },
134
- isSameDay(a, b) {
247
+ isSameDay(a, b, timezone) {
135
248
  if (!a || !b) return false;
249
+ if (timezone) {
250
+ return isSameDayInTimezone(a, b, timezone);
251
+ }
136
252
  const da = toDate(a);
137
253
  const db = toDate(b);
138
254
  return da.getUTCFullYear() === db.getUTCFullYear() && da.getUTCMonth() === db.getUTCMonth() && da.getUTCDate() === db.getUTCDate();
@@ -142,7 +258,10 @@ var DateFnsAdapter = {
142
258
  const db = toDate(b);
143
259
  return da.getUTCFullYear() === db.getUTCFullYear() && da.getUTCMonth() === db.getUTCMonth();
144
260
  },
145
- startOfDay(iso) {
261
+ startOfDay(iso, timezone) {
262
+ if (timezone) {
263
+ return startOfDayInTimezone(iso, timezone);
264
+ }
146
265
  return toISO(utcStartOfDay(toDate(iso)));
147
266
  },
148
267
  startOfMonth(iso) {
@@ -160,14 +279,17 @@ var DateFnsAdapter = {
160
279
  now() {
161
280
  return (/* @__PURE__ */ new Date()).toISOString();
162
281
  },
163
- today() {
282
+ today(timezone) {
283
+ if (timezone) {
284
+ return todayInTimezone(timezone);
285
+ }
164
286
  return toISO(utcStartOfDay(/* @__PURE__ */ new Date()));
165
287
  },
166
288
  isValid(value) {
167
289
  if (!value) return false;
168
290
  const normalized = normalize(value);
169
- const date = (0, import_date_fns.parseISO)(normalized);
170
- return (0, import_date_fns.isValid)(date);
291
+ const date = (0, import_date_fns2.parseISO)(normalized);
292
+ return (0, import_date_fns2.isValid)(date);
171
293
  },
172
294
  getYear(iso) {
173
295
  return toDate(iso).getUTCFullYear();
@@ -192,23 +314,24 @@ function getCalendarDays(monthISO, adapter, options = {}) {
192
314
  focusedDate,
193
315
  disabled = [],
194
316
  range,
195
- rangeHover
317
+ rangeHover,
318
+ timezone
196
319
  } = options;
197
- const todayISO = today ?? adapter.today();
320
+ const todayISO = today ?? adapter.today(timezone);
198
321
  const monthStart = adapter.startOfMonth(monthISO);
199
322
  const gridStart = adapter.startOfWeek(monthStart, weekStartsOn);
200
- const normalizedRange = normalizeRangeForDisplay(range, rangeHover, adapter);
323
+ const normalizedRange = normalizeRangeForDisplay(range, rangeHover, adapter, timezone);
201
324
  const weeks = [];
202
325
  let current = gridStart;
203
326
  for (let week = 0; week < 6; week++) {
204
327
  const days = [];
205
328
  for (let day = 0; day < 7; day++) {
206
329
  const isCurrentMonth = adapter.isSameMonth(current, monthISO);
207
- const isTodayDate = adapter.isSameDay(current, todayISO);
208
- const isSelected_ = selected ? adapter.isSameDay(current, selected) : false;
209
- const isFocused_ = focusedDate ? adapter.isSameDay(current, focusedDate) : false;
330
+ const isTodayDate = adapter.isSameDay(current, todayISO, timezone);
331
+ const isSelected_ = selected ? adapter.isSameDay(current, selected, timezone) : false;
332
+ const isFocused_ = focusedDate ? adapter.isSameDay(current, focusedDate, timezone) : false;
210
333
  const isDisabled_ = isDateDisabled(current, disabled, adapter);
211
- const rangeFlags = computeRangeFlags(current, normalizedRange, adapter);
334
+ const rangeFlags = computeRangeFlags(current, normalizedRange, adapter, timezone);
212
335
  days.push({
213
336
  isoString: current,
214
337
  dayNumber: adapter.getDate(current),
@@ -228,7 +351,7 @@ function getCalendarDays(monthISO, adapter, options = {}) {
228
351
  }
229
352
  return weeks;
230
353
  }
231
- function normalizeRangeForDisplay(range, hover, adapter) {
354
+ function normalizeRangeForDisplay(range, hover, adapter, _timezone) {
232
355
  if (!range) return { start: null, end: null };
233
356
  const { start, end } = range;
234
357
  if (start && end) {
@@ -248,16 +371,16 @@ function normalizeRangeForDisplay(range, hover, adapter) {
248
371
  }
249
372
  return { start: null, end: null };
250
373
  }
251
- function computeRangeFlags(iso, range, adapter) {
374
+ function computeRangeFlags(iso, range, adapter, timezone) {
252
375
  const { start, end } = range;
253
376
  if (!start) {
254
377
  return { isRangeStart: false, isRangeEnd: false, isInRange: false };
255
378
  }
256
- const isRangeStart = adapter.isSameDay(iso, start);
379
+ const isRangeStart = adapter.isSameDay(iso, start, timezone);
257
380
  if (!end) {
258
381
  return { isRangeStart, isRangeEnd: false, isInRange: false };
259
382
  }
260
- const isRangeEnd = adapter.isSameDay(iso, end);
383
+ const isRangeEnd = adapter.isSameDay(iso, end, timezone);
261
384
  const isInRange = !isRangeStart && !isRangeEnd && adapter.isAfter(iso, start) && adapter.isBefore(iso, end);
262
385
  return { isRangeStart, isRangeEnd, isInRange };
263
386
  }
@@ -393,13 +516,13 @@ function formatTimeFromISO(iso, format) {
393
516
  }
394
517
 
395
518
  // src/utils/locale.ts
396
- var formatterCache = /* @__PURE__ */ new Map();
519
+ var formatterCache2 = /* @__PURE__ */ new Map();
397
520
  function getCachedFormatter(locale, options) {
398
521
  const key = `${locale}:${JSON.stringify(options)}`;
399
- let fmt = formatterCache.get(key);
522
+ let fmt = formatterCache2.get(key);
400
523
  if (!fmt) {
401
524
  fmt = new Intl.DateTimeFormat(locale, options);
402
- formatterCache.set(key, fmt);
525
+ formatterCache2.set(key, fmt);
403
526
  }
404
527
  return fmt;
405
528
  }
@@ -444,81 +567,6 @@ function formatFullDate(iso, locale = "en-US") {
444
567
  }).format(date);
445
568
  }
446
569
 
447
- // src/utils/timezone.ts
448
- var import_date_fns2 = require("date-fns");
449
- var formatterCache2 = /* @__PURE__ */ new Map();
450
- function getCachedPartsFormatter(timeZone) {
451
- const key = `parts:${timeZone}`;
452
- let fmt = formatterCache2.get(key);
453
- if (!fmt) {
454
- fmt = new Intl.DateTimeFormat("en-US", {
455
- timeZone,
456
- year: "numeric",
457
- month: "2-digit",
458
- day: "2-digit",
459
- hour: "2-digit",
460
- minute: "2-digit",
461
- second: "2-digit",
462
- hourCycle: "h23"
463
- });
464
- formatterCache2.set(key, fmt);
465
- }
466
- return fmt;
467
- }
468
- function partsInTimezone(utc, timeZone) {
469
- const dtf = getCachedPartsFormatter(timeZone);
470
- const parts = Object.fromEntries(
471
- dtf.formatToParts(utc).map((p) => [p.type, p.value])
472
- );
473
- return {
474
- year: Number(parts.year),
475
- month: Number(parts.month),
476
- day: Number(parts.day),
477
- // Some locales/engines return '24' instead of '0' at midnight
478
- hour: parts.hour === "24" ? 0 : Number(parts.hour),
479
- minute: Number(parts.minute),
480
- second: Number(parts.second)
481
- };
482
- }
483
- function formatInTimezone(iso, formatStr, timeZone) {
484
- const p = partsInTimezone((0, import_date_fns2.parseISO)(iso), timeZone);
485
- const tokens = {
486
- yyyy: String(p.year),
487
- MM: String(p.month).padStart(2, "0"),
488
- dd: String(p.day).padStart(2, "0"),
489
- HH: String(p.hour).padStart(2, "0"),
490
- mm: String(p.minute).padStart(2, "0"),
491
- ss: String(p.second).padStart(2, "0")
492
- };
493
- let result = formatStr;
494
- for (const [token, value] of Object.entries(tokens).sort((a, b) => b[0].length - a[0].length)) {
495
- result = result.split(token).join(value);
496
- }
497
- return result;
498
- }
499
- function getTimezoneOffsetMinutes(iso, timeZone) {
500
- const utc = (0, import_date_fns2.parseISO)(iso);
501
- const p = partsInTimezone(utc, timeZone);
502
- const asUtcEpoch = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute, p.second);
503
- return Math.round((asUtcEpoch - utc.getTime()) / 6e4);
504
- }
505
- function startOfDayInTimezone(iso, timeZone) {
506
- const utc = (0, import_date_fns2.parseISO)(iso);
507
- const p = partsInTimezone(utc, timeZone);
508
- const civilMidnightUtc = Date.UTC(p.year, p.month - 1, p.day, 0, 0, 0);
509
- const midnightProbe = new Date(civilMidnightUtc).toISOString();
510
- const offsetMinutes = getTimezoneOffsetMinutes(midnightProbe, timeZone);
511
- return new Date(civilMidnightUtc - offsetMinutes * 6e4).toISOString();
512
- }
513
- function isSameDayInTimezone(a, b, timeZone) {
514
- const pa = partsInTimezone((0, import_date_fns2.parseISO)(a), timeZone);
515
- const pb = partsInTimezone((0, import_date_fns2.parseISO)(b), timeZone);
516
- return pa.year === pb.year && pa.month === pb.month && pa.day === pb.day;
517
- }
518
- function todayInTimezone(timeZone) {
519
- return startOfDayInTimezone((/* @__PURE__ */ new Date()).toISOString(), timeZone);
520
- }
521
-
522
570
  // src/utils/labels.ts
523
571
  var DEFAULT_DATEPICKER_LABELS = {
524
572
  triggerOpen: "Open calendar",
@@ -558,6 +606,7 @@ var DEFAULT_DATETIMEPICKER_LABELS = {
558
606
  DEFAULT_RANGEPICKER_LABELS,
559
607
  DEFAULT_TIMEPICKER_LABELS,
560
608
  DateFnsAdapter,
609
+ civilMidnightFromUtcDay,
561
610
  formatFullDate,
562
611
  formatInTimezone,
563
612
  formatMonthYear,
@@ -568,6 +617,7 @@ var DEFAULT_DATETIMEPICKER_LABELS = {
568
617
  getCalendarDays,
569
618
  getMonthName,
570
619
  getTime,
620
+ getTimeInTimezone,
571
621
  getTimezoneOffsetMinutes,
572
622
  getWeekdayNames,
573
623
  isDateDisabled,
@@ -579,6 +629,7 @@ var DEFAULT_DATETIMEPICKER_LABELS = {
579
629
  parseInputValue,
580
630
  parseTimeString,
581
631
  setTime,
632
+ setTimeInTimezone,
582
633
  startOfDayInTimezone,
583
634
  to12Hour,
584
635
  to24Hour,
package/dist/index.d.cts CHANGED
@@ -102,6 +102,12 @@ interface CalendarOptions {
102
102
  range?: DateRange | null;
103
103
  /** Currently hovered date (for RangePicker preview) */
104
104
  rangeHover?: ISODateString | null;
105
+ /**
106
+ * IANA timezone. When set, `isSameDay` comparisons for today/selected/range flags are
107
+ * evaluated in this zone — required when the picker stores values in display-tz civil
108
+ * midnight form while the grid iterates in UTC.
109
+ */
110
+ timezone?: string;
105
111
  }
106
112
 
107
113
  /**
@@ -306,6 +312,52 @@ declare function isSameDayInTimezone(a: ISODateString, b: ISODateString, timeZon
306
312
  * timezone rather than the server's local clock.
307
313
  */
308
314
  declare function todayInTimezone(timeZone: string): ISODateString;
315
+ /**
316
+ * Converts a UTC-midnight ISO (as produced by the default calendar grid iteration) into the
317
+ * civil midnight of the same calendar day in `timeZone`.
318
+ *
319
+ * This is the bridge used by DatePicker/RangePicker when `displayTimezone` is set: the grid
320
+ * iterates in UTC, so a cell's `isoString` is `YYYY-MM-DDT00:00:00.000Z`. When the user clicks
321
+ * that cell we want to emit an ISO representing the same civil day's midnight in the display
322
+ * timezone. A probe at noon UTC is used so the target civil day is unambiguous across any zone.
323
+ *
324
+ * @example
325
+ * civilMidnightFromUtcDay('2026-01-15T00:00:00.000Z', 'Asia/Seoul');
326
+ * // → '2026-01-14T15:00:00.000Z' (Seoul Jan 15 00:00 = UTC Jan 14 15:00)
327
+ */
328
+ declare function civilMidnightFromUtcDay(gridUtcIso: ISODateString, timeZone: string): ISODateString;
329
+ /**
330
+ * Extracts the time-of-day (hours / minutes / seconds) of a UTC instant as observed in
331
+ * `timeZone`. The result differs from reading UTC hours when the zone has a non-zero offset.
332
+ *
333
+ * @example
334
+ * getTimeInTimezone('2026-01-15T00:00:00.000Z', 'Asia/Seoul');
335
+ * // → { hours: 9, minutes: 0, seconds: 0 } (Seoul is UTC+9)
336
+ */
337
+ declare function getTimeInTimezone(iso: ISODateString, timeZone: string): {
338
+ hours: number;
339
+ minutes: number;
340
+ seconds: number;
341
+ };
342
+ /**
343
+ * Returns a new ISO UTC string where the civil date in `timeZone` is preserved and the time
344
+ * portion is replaced according to `partial` (as observed in that same timezone). Undefined
345
+ * fields keep their current value.
346
+ *
347
+ * Implementation note: the civil target (Y,M,D,H,m,s) is first mapped to a UTC epoch as if
348
+ * the wall-clock reading lived in UTC; then we subtract the timezone offset at that instant
349
+ * to recover the real UTC instant. The offset is refined once to absorb DST transitions.
350
+ *
351
+ * @example
352
+ * // In Asia/Seoul (UTC+9): set the hour to 10
353
+ * setTimeInTimezone('2026-01-15T00:00:00.000Z', { hours: 10 }, 'Asia/Seoul');
354
+ * // → '2026-01-15T01:00:00.000Z' (Seoul Jan 15 10:00 = UTC 01:00)
355
+ */
356
+ declare function setTimeInTimezone(iso: ISODateString, partial: {
357
+ hours?: number;
358
+ minutes?: number;
359
+ seconds?: number;
360
+ }, timeZone: string): ISODateString;
309
361
 
310
362
  /**
311
363
  * Default English labels for ARIA attributes and accessible text.
@@ -345,4 +397,4 @@ declare const DEFAULT_RANGEPICKER_LABELS: RangePickerLabels;
345
397
  declare const DEFAULT_TIMEPICKER_LABELS: TimePickerLabels;
346
398
  declare const DEFAULT_DATETIMEPICKER_LABELS: DateTimePickerLabels;
347
399
 
348
- export { type CalendarDay, type CalendarGrid, type CalendarOptions, type CalendarWeek, DEFAULT_DATEPICKER_LABELS, DEFAULT_DATETIMEPICKER_LABELS, DEFAULT_RANGEPICKER_LABELS, DEFAULT_TIMEPICKER_LABELS, type DateAdapter, DateFnsAdapter, type DatePickerLabels, type DateRange, type DateTimePickerLabels, type DisabledRule, type ISODateString, type RangePickerLabels, type TimePickerLabels, type TimeValue, type WeekStartsOn, type WeekdayInfo, formatFullDate, formatInTimezone, formatMonthYear, formatTimeFromISO, formatTimeString, generateHours, generateMinutes, getCalendarDays, getMonthName, getTime, getTimezoneOffsetMinutes, getWeekdayNames, isDateDisabled, isSameDayInTimezone, isSameTime, maxDate, minDate, normalizeISO, parseInputValue, parseTimeString, setTime, startOfDayInTimezone, to12Hour, to24Hour, todayInTimezone };
400
+ export { type CalendarDay, type CalendarGrid, type CalendarOptions, type CalendarWeek, DEFAULT_DATEPICKER_LABELS, DEFAULT_DATETIMEPICKER_LABELS, DEFAULT_RANGEPICKER_LABELS, DEFAULT_TIMEPICKER_LABELS, type DateAdapter, DateFnsAdapter, type DatePickerLabels, type DateRange, type DateTimePickerLabels, type DisabledRule, type ISODateString, type RangePickerLabels, type TimePickerLabels, type TimeValue, type WeekStartsOn, type WeekdayInfo, civilMidnightFromUtcDay, formatFullDate, formatInTimezone, formatMonthYear, formatTimeFromISO, formatTimeString, generateHours, generateMinutes, getCalendarDays, getMonthName, getTime, getTimeInTimezone, getTimezoneOffsetMinutes, getWeekdayNames, isDateDisabled, isSameDayInTimezone, isSameTime, maxDate, minDate, normalizeISO, parseInputValue, parseTimeString, setTime, setTimeInTimezone, startOfDayInTimezone, to12Hour, to24Hour, todayInTimezone };
package/dist/index.d.ts CHANGED
@@ -102,6 +102,12 @@ interface CalendarOptions {
102
102
  range?: DateRange | null;
103
103
  /** Currently hovered date (for RangePicker preview) */
104
104
  rangeHover?: ISODateString | null;
105
+ /**
106
+ * IANA timezone. When set, `isSameDay` comparisons for today/selected/range flags are
107
+ * evaluated in this zone — required when the picker stores values in display-tz civil
108
+ * midnight form while the grid iterates in UTC.
109
+ */
110
+ timezone?: string;
105
111
  }
106
112
 
107
113
  /**
@@ -306,6 +312,52 @@ declare function isSameDayInTimezone(a: ISODateString, b: ISODateString, timeZon
306
312
  * timezone rather than the server's local clock.
307
313
  */
308
314
  declare function todayInTimezone(timeZone: string): ISODateString;
315
+ /**
316
+ * Converts a UTC-midnight ISO (as produced by the default calendar grid iteration) into the
317
+ * civil midnight of the same calendar day in `timeZone`.
318
+ *
319
+ * This is the bridge used by DatePicker/RangePicker when `displayTimezone` is set: the grid
320
+ * iterates in UTC, so a cell's `isoString` is `YYYY-MM-DDT00:00:00.000Z`. When the user clicks
321
+ * that cell we want to emit an ISO representing the same civil day's midnight in the display
322
+ * timezone. A probe at noon UTC is used so the target civil day is unambiguous across any zone.
323
+ *
324
+ * @example
325
+ * civilMidnightFromUtcDay('2026-01-15T00:00:00.000Z', 'Asia/Seoul');
326
+ * // → '2026-01-14T15:00:00.000Z' (Seoul Jan 15 00:00 = UTC Jan 14 15:00)
327
+ */
328
+ declare function civilMidnightFromUtcDay(gridUtcIso: ISODateString, timeZone: string): ISODateString;
329
+ /**
330
+ * Extracts the time-of-day (hours / minutes / seconds) of a UTC instant as observed in
331
+ * `timeZone`. The result differs from reading UTC hours when the zone has a non-zero offset.
332
+ *
333
+ * @example
334
+ * getTimeInTimezone('2026-01-15T00:00:00.000Z', 'Asia/Seoul');
335
+ * // → { hours: 9, minutes: 0, seconds: 0 } (Seoul is UTC+9)
336
+ */
337
+ declare function getTimeInTimezone(iso: ISODateString, timeZone: string): {
338
+ hours: number;
339
+ minutes: number;
340
+ seconds: number;
341
+ };
342
+ /**
343
+ * Returns a new ISO UTC string where the civil date in `timeZone` is preserved and the time
344
+ * portion is replaced according to `partial` (as observed in that same timezone). Undefined
345
+ * fields keep their current value.
346
+ *
347
+ * Implementation note: the civil target (Y,M,D,H,m,s) is first mapped to a UTC epoch as if
348
+ * the wall-clock reading lived in UTC; then we subtract the timezone offset at that instant
349
+ * to recover the real UTC instant. The offset is refined once to absorb DST transitions.
350
+ *
351
+ * @example
352
+ * // In Asia/Seoul (UTC+9): set the hour to 10
353
+ * setTimeInTimezone('2026-01-15T00:00:00.000Z', { hours: 10 }, 'Asia/Seoul');
354
+ * // → '2026-01-15T01:00:00.000Z' (Seoul Jan 15 10:00 = UTC 01:00)
355
+ */
356
+ declare function setTimeInTimezone(iso: ISODateString, partial: {
357
+ hours?: number;
358
+ minutes?: number;
359
+ seconds?: number;
360
+ }, timeZone: string): ISODateString;
309
361
 
310
362
  /**
311
363
  * Default English labels for ARIA attributes and accessible text.
@@ -345,4 +397,4 @@ declare const DEFAULT_RANGEPICKER_LABELS: RangePickerLabels;
345
397
  declare const DEFAULT_TIMEPICKER_LABELS: TimePickerLabels;
346
398
  declare const DEFAULT_DATETIMEPICKER_LABELS: DateTimePickerLabels;
347
399
 
348
- export { type CalendarDay, type CalendarGrid, type CalendarOptions, type CalendarWeek, DEFAULT_DATEPICKER_LABELS, DEFAULT_DATETIMEPICKER_LABELS, DEFAULT_RANGEPICKER_LABELS, DEFAULT_TIMEPICKER_LABELS, type DateAdapter, DateFnsAdapter, type DatePickerLabels, type DateRange, type DateTimePickerLabels, type DisabledRule, type ISODateString, type RangePickerLabels, type TimePickerLabels, type TimeValue, type WeekStartsOn, type WeekdayInfo, formatFullDate, formatInTimezone, formatMonthYear, formatTimeFromISO, formatTimeString, generateHours, generateMinutes, getCalendarDays, getMonthName, getTime, getTimezoneOffsetMinutes, getWeekdayNames, isDateDisabled, isSameDayInTimezone, isSameTime, maxDate, minDate, normalizeISO, parseInputValue, parseTimeString, setTime, startOfDayInTimezone, to12Hour, to24Hour, todayInTimezone };
400
+ export { type CalendarDay, type CalendarGrid, type CalendarOptions, type CalendarWeek, DEFAULT_DATEPICKER_LABELS, DEFAULT_DATETIMEPICKER_LABELS, DEFAULT_RANGEPICKER_LABELS, DEFAULT_TIMEPICKER_LABELS, type DateAdapter, DateFnsAdapter, type DatePickerLabels, type DateRange, type DateTimePickerLabels, type DisabledRule, type ISODateString, type RangePickerLabels, type TimePickerLabels, type TimeValue, type WeekStartsOn, type WeekdayInfo, civilMidnightFromUtcDay, formatFullDate, formatInTimezone, formatMonthYear, formatTimeFromISO, formatTimeString, generateHours, generateMinutes, getCalendarDays, getMonthName, getTime, getTimeInTimezone, getTimezoneOffsetMinutes, getWeekdayNames, isDateDisabled, isSameDayInTimezone, isSameTime, maxDate, minDate, normalizeISO, parseInputValue, parseTimeString, setTime, setTimeInTimezone, startOfDayInTimezone, to12Hour, to24Hour, todayInTimezone };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/adapters/date-fns.ts
2
2
  import {
3
- parseISO,
3
+ parseISO as parseISO2,
4
4
  addDays as dfAddDays,
5
5
  addMonths as dfAddMonths,
6
6
  addYears as dfAddYears,
@@ -8,8 +8,115 @@ import {
8
8
  isAfter as dfIsAfter,
9
9
  isValid as dfIsValid
10
10
  } from "date-fns";
11
+
12
+ // src/utils/timezone.ts
13
+ import { parseISO } from "date-fns";
14
+ var formatterCache = /* @__PURE__ */ new Map();
15
+ function getCachedPartsFormatter(timeZone) {
16
+ const key = `parts:${timeZone}`;
17
+ let fmt = formatterCache.get(key);
18
+ if (!fmt) {
19
+ fmt = new Intl.DateTimeFormat("en-US", {
20
+ timeZone,
21
+ year: "numeric",
22
+ month: "2-digit",
23
+ day: "2-digit",
24
+ hour: "2-digit",
25
+ minute: "2-digit",
26
+ second: "2-digit",
27
+ hourCycle: "h23"
28
+ });
29
+ formatterCache.set(key, fmt);
30
+ }
31
+ return fmt;
32
+ }
33
+ function partsInTimezone(utc, timeZone) {
34
+ const dtf = getCachedPartsFormatter(timeZone);
35
+ const parts = Object.fromEntries(
36
+ dtf.formatToParts(utc).map((p) => [p.type, p.value])
37
+ );
38
+ return {
39
+ year: Number(parts.year),
40
+ month: Number(parts.month),
41
+ day: Number(parts.day),
42
+ // Some locales/engines return '24' instead of '0' at midnight
43
+ hour: parts.hour === "24" ? 0 : Number(parts.hour),
44
+ minute: Number(parts.minute),
45
+ second: Number(parts.second)
46
+ };
47
+ }
48
+ function formatInTimezone(iso, formatStr, timeZone) {
49
+ const p = partsInTimezone(parseISO(iso), timeZone);
50
+ const tokens = {
51
+ yyyy: String(p.year),
52
+ MM: String(p.month).padStart(2, "0"),
53
+ dd: String(p.day).padStart(2, "0"),
54
+ HH: String(p.hour).padStart(2, "0"),
55
+ mm: String(p.minute).padStart(2, "0"),
56
+ ss: String(p.second).padStart(2, "0")
57
+ };
58
+ let result = formatStr;
59
+ for (const [token, value] of Object.entries(tokens).sort((a, b) => b[0].length - a[0].length)) {
60
+ result = result.split(token).join(value);
61
+ }
62
+ return result;
63
+ }
64
+ function getTimezoneOffsetMinutes(iso, timeZone) {
65
+ const utc = parseISO(iso);
66
+ const p = partsInTimezone(utc, timeZone);
67
+ const asUtcEpoch = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute, p.second);
68
+ return Math.round((asUtcEpoch - utc.getTime()) / 6e4);
69
+ }
70
+ function startOfDayInTimezone(iso, timeZone) {
71
+ const utc = parseISO(iso);
72
+ const p = partsInTimezone(utc, timeZone);
73
+ const civilMidnightUtc = Date.UTC(p.year, p.month - 1, p.day, 0, 0, 0);
74
+ const midnightProbe = new Date(civilMidnightUtc).toISOString();
75
+ const offsetMinutes = getTimezoneOffsetMinutes(midnightProbe, timeZone);
76
+ return new Date(civilMidnightUtc - offsetMinutes * 6e4).toISOString();
77
+ }
78
+ function isSameDayInTimezone(a, b, timeZone) {
79
+ const pa = partsInTimezone(parseISO(a), timeZone);
80
+ const pb = partsInTimezone(parseISO(b), timeZone);
81
+ return pa.year === pb.year && pa.month === pb.month && pa.day === pb.day;
82
+ }
83
+ function todayInTimezone(timeZone) {
84
+ return startOfDayInTimezone((/* @__PURE__ */ new Date()).toISOString(), timeZone);
85
+ }
86
+ function civilMidnightFromUtcDay(gridUtcIso, timeZone) {
87
+ const utc = parseISO(gridUtcIso);
88
+ const probe = new Date(Date.UTC(
89
+ utc.getUTCFullYear(),
90
+ utc.getUTCMonth(),
91
+ utc.getUTCDate(),
92
+ 12,
93
+ 0,
94
+ 0
95
+ )).toISOString();
96
+ return startOfDayInTimezone(probe, timeZone);
97
+ }
98
+ function getTimeInTimezone(iso, timeZone) {
99
+ const p = partsInTimezone(parseISO(iso), timeZone);
100
+ return { hours: p.hour, minutes: p.minute, seconds: p.second };
101
+ }
102
+ function setTimeInTimezone(iso, partial, timeZone) {
103
+ const p = partsInTimezone(parseISO(iso), timeZone);
104
+ const targetHours = partial.hours ?? p.hour;
105
+ const targetMinutes = partial.minutes ?? p.minute;
106
+ const targetSeconds = partial.seconds ?? p.second;
107
+ const civilEpoch = Date.UTC(p.year, p.month - 1, p.day, targetHours, targetMinutes, targetSeconds);
108
+ const probe1 = new Date(civilEpoch).toISOString();
109
+ const offset1 = getTimezoneOffsetMinutes(probe1, timeZone);
110
+ const realEpoch1 = civilEpoch - offset1 * 6e4;
111
+ const probe2 = new Date(realEpoch1).toISOString();
112
+ const offset2 = getTimezoneOffsetMinutes(probe2, timeZone);
113
+ const realEpoch2 = civilEpoch - offset2 * 6e4;
114
+ return new Date(realEpoch2).toISOString();
115
+ }
116
+
117
+ // src/adapters/date-fns.ts
11
118
  function toDate(iso) {
12
- return parseISO(iso);
119
+ return parseISO2(iso);
13
120
  }
14
121
  function toISO(date) {
15
122
  return date.toISOString();
@@ -51,7 +158,10 @@ var DateFnsAdapter = {
51
158
  if (!value) return "";
52
159
  return normalize(value);
53
160
  },
54
- format(iso, formatStr) {
161
+ format(iso, formatStr, timezone) {
162
+ if (timezone) {
163
+ return formatInTimezone(iso, formatStr, timezone);
164
+ }
55
165
  const d = toDate(iso);
56
166
  const tokens = {
57
167
  yyyy: String(d.getUTCFullYear()),
@@ -84,8 +194,11 @@ var DateFnsAdapter = {
84
194
  isAfter(a, b) {
85
195
  return dfIsAfter(toDate(a), toDate(b));
86
196
  },
87
- isSameDay(a, b) {
197
+ isSameDay(a, b, timezone) {
88
198
  if (!a || !b) return false;
199
+ if (timezone) {
200
+ return isSameDayInTimezone(a, b, timezone);
201
+ }
89
202
  const da = toDate(a);
90
203
  const db = toDate(b);
91
204
  return da.getUTCFullYear() === db.getUTCFullYear() && da.getUTCMonth() === db.getUTCMonth() && da.getUTCDate() === db.getUTCDate();
@@ -95,7 +208,10 @@ var DateFnsAdapter = {
95
208
  const db = toDate(b);
96
209
  return da.getUTCFullYear() === db.getUTCFullYear() && da.getUTCMonth() === db.getUTCMonth();
97
210
  },
98
- startOfDay(iso) {
211
+ startOfDay(iso, timezone) {
212
+ if (timezone) {
213
+ return startOfDayInTimezone(iso, timezone);
214
+ }
99
215
  return toISO(utcStartOfDay(toDate(iso)));
100
216
  },
101
217
  startOfMonth(iso) {
@@ -113,13 +229,16 @@ var DateFnsAdapter = {
113
229
  now() {
114
230
  return (/* @__PURE__ */ new Date()).toISOString();
115
231
  },
116
- today() {
232
+ today(timezone) {
233
+ if (timezone) {
234
+ return todayInTimezone(timezone);
235
+ }
117
236
  return toISO(utcStartOfDay(/* @__PURE__ */ new Date()));
118
237
  },
119
238
  isValid(value) {
120
239
  if (!value) return false;
121
240
  const normalized = normalize(value);
122
- const date = parseISO(normalized);
241
+ const date = parseISO2(normalized);
123
242
  return dfIsValid(date);
124
243
  },
125
244
  getYear(iso) {
@@ -145,23 +264,24 @@ function getCalendarDays(monthISO, adapter, options = {}) {
145
264
  focusedDate,
146
265
  disabled = [],
147
266
  range,
148
- rangeHover
267
+ rangeHover,
268
+ timezone
149
269
  } = options;
150
- const todayISO = today ?? adapter.today();
270
+ const todayISO = today ?? adapter.today(timezone);
151
271
  const monthStart = adapter.startOfMonth(monthISO);
152
272
  const gridStart = adapter.startOfWeek(monthStart, weekStartsOn);
153
- const normalizedRange = normalizeRangeForDisplay(range, rangeHover, adapter);
273
+ const normalizedRange = normalizeRangeForDisplay(range, rangeHover, adapter, timezone);
154
274
  const weeks = [];
155
275
  let current = gridStart;
156
276
  for (let week = 0; week < 6; week++) {
157
277
  const days = [];
158
278
  for (let day = 0; day < 7; day++) {
159
279
  const isCurrentMonth = adapter.isSameMonth(current, monthISO);
160
- const isTodayDate = adapter.isSameDay(current, todayISO);
161
- const isSelected_ = selected ? adapter.isSameDay(current, selected) : false;
162
- const isFocused_ = focusedDate ? adapter.isSameDay(current, focusedDate) : false;
280
+ const isTodayDate = adapter.isSameDay(current, todayISO, timezone);
281
+ const isSelected_ = selected ? adapter.isSameDay(current, selected, timezone) : false;
282
+ const isFocused_ = focusedDate ? adapter.isSameDay(current, focusedDate, timezone) : false;
163
283
  const isDisabled_ = isDateDisabled(current, disabled, adapter);
164
- const rangeFlags = computeRangeFlags(current, normalizedRange, adapter);
284
+ const rangeFlags = computeRangeFlags(current, normalizedRange, adapter, timezone);
165
285
  days.push({
166
286
  isoString: current,
167
287
  dayNumber: adapter.getDate(current),
@@ -181,7 +301,7 @@ function getCalendarDays(monthISO, adapter, options = {}) {
181
301
  }
182
302
  return weeks;
183
303
  }
184
- function normalizeRangeForDisplay(range, hover, adapter) {
304
+ function normalizeRangeForDisplay(range, hover, adapter, _timezone) {
185
305
  if (!range) return { start: null, end: null };
186
306
  const { start, end } = range;
187
307
  if (start && end) {
@@ -201,16 +321,16 @@ function normalizeRangeForDisplay(range, hover, adapter) {
201
321
  }
202
322
  return { start: null, end: null };
203
323
  }
204
- function computeRangeFlags(iso, range, adapter) {
324
+ function computeRangeFlags(iso, range, adapter, timezone) {
205
325
  const { start, end } = range;
206
326
  if (!start) {
207
327
  return { isRangeStart: false, isRangeEnd: false, isInRange: false };
208
328
  }
209
- const isRangeStart = adapter.isSameDay(iso, start);
329
+ const isRangeStart = adapter.isSameDay(iso, start, timezone);
210
330
  if (!end) {
211
331
  return { isRangeStart, isRangeEnd: false, isInRange: false };
212
332
  }
213
- const isRangeEnd = adapter.isSameDay(iso, end);
333
+ const isRangeEnd = adapter.isSameDay(iso, end, timezone);
214
334
  const isInRange = !isRangeStart && !isRangeEnd && adapter.isAfter(iso, start) && adapter.isBefore(iso, end);
215
335
  return { isRangeStart, isRangeEnd, isInRange };
216
336
  }
@@ -346,13 +466,13 @@ function formatTimeFromISO(iso, format) {
346
466
  }
347
467
 
348
468
  // src/utils/locale.ts
349
- var formatterCache = /* @__PURE__ */ new Map();
469
+ var formatterCache2 = /* @__PURE__ */ new Map();
350
470
  function getCachedFormatter(locale, options) {
351
471
  const key = `${locale}:${JSON.stringify(options)}`;
352
- let fmt = formatterCache.get(key);
472
+ let fmt = formatterCache2.get(key);
353
473
  if (!fmt) {
354
474
  fmt = new Intl.DateTimeFormat(locale, options);
355
- formatterCache.set(key, fmt);
475
+ formatterCache2.set(key, fmt);
356
476
  }
357
477
  return fmt;
358
478
  }
@@ -397,81 +517,6 @@ function formatFullDate(iso, locale = "en-US") {
397
517
  }).format(date);
398
518
  }
399
519
 
400
- // src/utils/timezone.ts
401
- import { parseISO as parseISO2 } from "date-fns";
402
- var formatterCache2 = /* @__PURE__ */ new Map();
403
- function getCachedPartsFormatter(timeZone) {
404
- const key = `parts:${timeZone}`;
405
- let fmt = formatterCache2.get(key);
406
- if (!fmt) {
407
- fmt = new Intl.DateTimeFormat("en-US", {
408
- timeZone,
409
- year: "numeric",
410
- month: "2-digit",
411
- day: "2-digit",
412
- hour: "2-digit",
413
- minute: "2-digit",
414
- second: "2-digit",
415
- hourCycle: "h23"
416
- });
417
- formatterCache2.set(key, fmt);
418
- }
419
- return fmt;
420
- }
421
- function partsInTimezone(utc, timeZone) {
422
- const dtf = getCachedPartsFormatter(timeZone);
423
- const parts = Object.fromEntries(
424
- dtf.formatToParts(utc).map((p) => [p.type, p.value])
425
- );
426
- return {
427
- year: Number(parts.year),
428
- month: Number(parts.month),
429
- day: Number(parts.day),
430
- // Some locales/engines return '24' instead of '0' at midnight
431
- hour: parts.hour === "24" ? 0 : Number(parts.hour),
432
- minute: Number(parts.minute),
433
- second: Number(parts.second)
434
- };
435
- }
436
- function formatInTimezone(iso, formatStr, timeZone) {
437
- const p = partsInTimezone(parseISO2(iso), timeZone);
438
- const tokens = {
439
- yyyy: String(p.year),
440
- MM: String(p.month).padStart(2, "0"),
441
- dd: String(p.day).padStart(2, "0"),
442
- HH: String(p.hour).padStart(2, "0"),
443
- mm: String(p.minute).padStart(2, "0"),
444
- ss: String(p.second).padStart(2, "0")
445
- };
446
- let result = formatStr;
447
- for (const [token, value] of Object.entries(tokens).sort((a, b) => b[0].length - a[0].length)) {
448
- result = result.split(token).join(value);
449
- }
450
- return result;
451
- }
452
- function getTimezoneOffsetMinutes(iso, timeZone) {
453
- const utc = parseISO2(iso);
454
- const p = partsInTimezone(utc, timeZone);
455
- const asUtcEpoch = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute, p.second);
456
- return Math.round((asUtcEpoch - utc.getTime()) / 6e4);
457
- }
458
- function startOfDayInTimezone(iso, timeZone) {
459
- const utc = parseISO2(iso);
460
- const p = partsInTimezone(utc, timeZone);
461
- const civilMidnightUtc = Date.UTC(p.year, p.month - 1, p.day, 0, 0, 0);
462
- const midnightProbe = new Date(civilMidnightUtc).toISOString();
463
- const offsetMinutes = getTimezoneOffsetMinutes(midnightProbe, timeZone);
464
- return new Date(civilMidnightUtc - offsetMinutes * 6e4).toISOString();
465
- }
466
- function isSameDayInTimezone(a, b, timeZone) {
467
- const pa = partsInTimezone(parseISO2(a), timeZone);
468
- const pb = partsInTimezone(parseISO2(b), timeZone);
469
- return pa.year === pb.year && pa.month === pb.month && pa.day === pb.day;
470
- }
471
- function todayInTimezone(timeZone) {
472
- return startOfDayInTimezone((/* @__PURE__ */ new Date()).toISOString(), timeZone);
473
- }
474
-
475
520
  // src/utils/labels.ts
476
521
  var DEFAULT_DATEPICKER_LABELS = {
477
522
  triggerOpen: "Open calendar",
@@ -510,6 +555,7 @@ export {
510
555
  DEFAULT_RANGEPICKER_LABELS,
511
556
  DEFAULT_TIMEPICKER_LABELS,
512
557
  DateFnsAdapter,
558
+ civilMidnightFromUtcDay,
513
559
  formatFullDate,
514
560
  formatInTimezone,
515
561
  formatMonthYear,
@@ -520,6 +566,7 @@ export {
520
566
  getCalendarDays,
521
567
  getMonthName,
522
568
  getTime,
569
+ getTimeInTimezone,
523
570
  getTimezoneOffsetMinutes,
524
571
  getWeekdayNames,
525
572
  isDateDisabled,
@@ -531,6 +578,7 @@ export {
531
578
  parseInputValue,
532
579
  parseTimeString,
533
580
  setTime,
581
+ setTimeInTimezone,
534
582
  startOfDayInTimezone,
535
583
  to12Hour,
536
584
  to24Hour,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kalyx/core",
3
- "version": "0.3.0",
4
- "description": "Kalyx core — platform-agnostic date logic",
3
+ "version": "1.0.0-rc.0",
4
+ "description": "Kalyx core — platform-agnostic date logic, IANA timezone helpers, and the DateAdapter contract used by @kalyx/react",
5
5
  "license": "MIT",
6
6
  "author": "jiji-hoon96",
7
7
  "homepage": "https://github.com/jiji-hoon96/kalyx#readme",
@@ -18,11 +18,14 @@
18
18
  "datepicker",
19
19
  "calendar",
20
20
  "timezone",
21
+ "iana",
22
+ "dst",
21
23
  "iso8601",
22
24
  "utc",
23
25
  "date-fns"
24
26
  ],
25
27
  "type": "module",
28
+ "sideEffects": false,
26
29
  "main": "./dist/index.cjs",
27
30
  "module": "./dist/index.js",
28
31
  "types": "./dist/index.d.ts",