@dreamstack-us/kaal 0.0.4 → 0.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.
Files changed (34) hide show
  1. package/lib/module/components/CalendarGrid/CalendarGrid.js +1 -1
  2. package/lib/module/components/CalendarGrid/CalendarGrid.js.map +1 -1
  3. package/lib/module/components/CalendarGrid/CalendarGrid.web.js +1 -1
  4. package/lib/module/components/CalendarGrid/CalendarGrid.web.js.map +1 -1
  5. package/lib/module/components/CalendarGrid/DayCell.js +81 -36
  6. package/lib/module/components/CalendarGrid/DayCell.js.map +1 -1
  7. package/lib/module/components/CalendarGrid/DayCell.web.js +80 -36
  8. package/lib/module/components/CalendarGrid/DayCell.web.js.map +1 -1
  9. package/lib/module/components/TimePicker/MaterialTimePicker.web.js +67 -15
  10. package/lib/module/components/TimePicker/MaterialTimePicker.web.js.map +1 -1
  11. package/lib/module/components/WheelPicker/WheelPicker.web.js +14 -14
  12. package/lib/module/components/WheelPicker/WheelPicker.web.js.map +1 -1
  13. package/lib/module/hooks/useCalendar.js +1 -1
  14. package/lib/module/hooks/useCalendar.js.map +1 -1
  15. package/lib/module/utils/date.js +25 -21
  16. package/lib/module/utils/date.js.map +1 -1
  17. package/lib/module/utils/validation.js +3 -3
  18. package/lib/module/utils/validation.js.map +1 -1
  19. package/lib/typescript/components/CalendarGrid/DayCell.d.ts.map +1 -1
  20. package/lib/typescript/components/CalendarGrid/DayCell.web.d.ts.map +1 -1
  21. package/lib/typescript/components/TimePicker/MaterialTimePicker.web.d.ts.map +1 -1
  22. package/lib/typescript/components/WheelPicker/WheelPicker.web.d.ts.map +1 -1
  23. package/lib/typescript/utils/date.d.ts +7 -3
  24. package/lib/typescript/utils/date.d.ts.map +1 -1
  25. package/package.json +8 -9
  26. package/src/components/CalendarGrid/CalendarGrid.tsx +2 -2
  27. package/src/components/CalendarGrid/CalendarGrid.web.tsx +2 -2
  28. package/src/components/CalendarGrid/DayCell.tsx +98 -47
  29. package/src/components/CalendarGrid/DayCell.web.tsx +105 -47
  30. package/src/components/TimePicker/MaterialTimePicker.web.tsx +150 -13
  31. package/src/components/WheelPicker/WheelPicker.web.tsx +15 -25
  32. package/src/hooks/useCalendar.ts +2 -2
  33. package/src/utils/date.ts +34 -27
  34. package/src/utils/validation.ts +5 -5
@@ -1,11 +1,27 @@
1
1
  /// <reference lib="dom" />
2
2
  import type React from 'react';
3
- import { memo, useCallback, useState } from 'react';
3
+ import { memo, useCallback, useMemo, useState } from 'react';
4
4
  import { Pressable, StyleSheet, Text, View } from 'react-native';
5
+ import { useTimePickerOverrides } from '../../context/ThemeOverrideContext';
5
6
  import { to12Hour, to24Hour } from '../../hooks/useTimePicker';
6
7
  import type { ClockMode, TimePeriod, TimeValue } from '../../types/timepicker';
7
8
  import { ClockFace } from './ClockFace';
8
9
 
10
+ // Default colors (dark theme)
11
+ const DEFAULT_COLORS = {
12
+ containerBackground: '#2C2C2E',
13
+ headerColor: '#8E8E93',
14
+ timeFieldBackground: '#3A3A3C',
15
+ timeFieldActiveBackground: '#007AFF',
16
+ textColor: '#FFFFFF',
17
+ separatorColor: '#FFFFFF',
18
+ borderColor: '#48484A',
19
+ periodActiveBackground: 'rgba(0, 122, 255, 0.2)',
20
+ periodTextColor: '#8E8E93',
21
+ periodTextActiveColor: '#007AFF',
22
+ actionButtonColor: '#007AFF',
23
+ };
24
+
9
25
  interface MaterialTimePickerProps {
10
26
  value: TimeValue;
11
27
  onChange: (time: TimeValue) => void;
@@ -127,6 +143,7 @@ const webStyles = StyleSheet.create({
127
143
 
128
144
  export const MaterialTimePicker: React.FC<MaterialTimePickerProps> = memo(
129
145
  ({ value, onChange, is24Hour = false, onCancel, onConfirm }) => {
146
+ const overrides = useTimePickerOverrides();
130
147
  const [mode, setMode] = useState<ClockMode>('hours');
131
148
  const { hour: hour12, period } = to12Hour(value.hours);
132
149
 
@@ -155,9 +172,95 @@ export const MaterialTimePicker: React.FC<MaterialTimePickerProps> = memo(
155
172
  : hour12.toString().padStart(2, '0');
156
173
  const displayMinute = value.minutes.toString().padStart(2, '0');
157
174
 
175
+ // Build override styles from themeOverrides
176
+ const containerStyle = useMemo(
177
+ () => ({
178
+ backgroundColor:
179
+ overrides?.containerBackground ?? DEFAULT_COLORS.containerBackground,
180
+ }),
181
+ [overrides],
182
+ );
183
+
184
+ const headerStyle = useMemo(
185
+ () => ({
186
+ color: overrides?.headerColor ?? DEFAULT_COLORS.headerColor,
187
+ }),
188
+ [overrides],
189
+ );
190
+
191
+ const timeFieldStyle = useMemo(
192
+ () => ({
193
+ backgroundColor:
194
+ overrides?.timeFieldBackground ?? DEFAULT_COLORS.timeFieldBackground,
195
+ }),
196
+ [overrides],
197
+ );
198
+
199
+ const timeFieldActiveStyle = useMemo(
200
+ () => ({
201
+ backgroundColor:
202
+ overrides?.timeFieldActiveBackground ??
203
+ DEFAULT_COLORS.timeFieldActiveBackground,
204
+ }),
205
+ [overrides],
206
+ );
207
+
208
+ const textStyle = useMemo(
209
+ () => ({
210
+ color: overrides?.textColor ?? DEFAULT_COLORS.textColor,
211
+ }),
212
+ [overrides],
213
+ );
214
+
215
+ const separatorStyle = useMemo(
216
+ () => ({
217
+ color: overrides?.separatorColor ?? DEFAULT_COLORS.separatorColor,
218
+ }),
219
+ [overrides],
220
+ );
221
+
222
+ const periodContainerStyle = useMemo(
223
+ () => ({
224
+ borderColor: overrides?.periodBorderColor ?? DEFAULT_COLORS.borderColor,
225
+ }),
226
+ [overrides],
227
+ );
228
+
229
+ const periodActiveStyle = useMemo(
230
+ () => ({
231
+ backgroundColor:
232
+ overrides?.periodActiveBackground ??
233
+ DEFAULT_COLORS.periodActiveBackground,
234
+ }),
235
+ [overrides],
236
+ );
237
+
238
+ const periodTextStyle = useMemo(
239
+ () => ({
240
+ color: overrides?.periodTextColor ?? DEFAULT_COLORS.periodTextColor,
241
+ }),
242
+ [overrides],
243
+ );
244
+
245
+ const periodTextActiveStyle = useMemo(
246
+ () => ({
247
+ color:
248
+ overrides?.periodTextActiveColor ??
249
+ DEFAULT_COLORS.periodTextActiveColor,
250
+ }),
251
+ [overrides],
252
+ );
253
+
254
+ const actionButtonTextStyle = useMemo(
255
+ () => ({
256
+ color: overrides?.actionButtonColor ?? DEFAULT_COLORS.actionButtonColor,
257
+ }),
258
+ [overrides],
259
+ );
260
+
158
261
  return (
159
- <View style={webStyles.materialContainer}>
160
- <Text style={webStyles.materialHeader}>Select time</Text>
262
+ <View style={[webStyles.materialContainer, containerStyle]}>
263
+ <Text style={[webStyles.materialHeader, headerStyle]}>Select time</Text>
161
264
 
162
265
  <View style={webStyles.timeInputContainer}>
163
266
  <View style={webStyles.timeFieldsContainer}>
@@ -165,12 +268,17 @@ export const MaterialTimePicker: React.FC<MaterialTimePickerProps> = memo(
165
268
  onPress={handleHourPress}
166
269
  style={[
167
270
  webStyles.timeField,
168
- mode === 'hours' && webStyles.timeFieldActive,
271
+ timeFieldStyle,
272
+ mode === 'hours' && [
273
+ webStyles.timeFieldActive,
274
+ timeFieldActiveStyle,
275
+ ],
169
276
  ]}
170
277
  >
171
278
  <Text
172
279
  style={[
173
280
  webStyles.timeFieldText,
281
+ textStyle,
174
282
  mode === 'hours' && webStyles.timeFieldTextActive,
175
283
  ]}
176
284
  >
@@ -178,18 +286,23 @@ export const MaterialTimePicker: React.FC<MaterialTimePickerProps> = memo(
178
286
  </Text>
179
287
  </Pressable>
180
288
 
181
- <Text style={webStyles.timeSeparator}>:</Text>
289
+ <Text style={[webStyles.timeSeparator, separatorStyle]}>:</Text>
182
290
 
183
291
  <Pressable
184
292
  onPress={handleMinutePress}
185
293
  style={[
186
294
  webStyles.timeField,
187
- mode === 'minutes' && webStyles.timeFieldActive,
295
+ timeFieldStyle,
296
+ mode === 'minutes' && [
297
+ webStyles.timeFieldActive,
298
+ timeFieldActiveStyle,
299
+ ],
188
300
  ]}
189
301
  >
190
302
  <Text
191
303
  style={[
192
304
  webStyles.timeFieldText,
305
+ textStyle,
193
306
  mode === 'minutes' && webStyles.timeFieldTextActive,
194
307
  ]}
195
308
  >
@@ -199,19 +312,28 @@ export const MaterialTimePicker: React.FC<MaterialTimePickerProps> = memo(
199
312
  </View>
200
313
 
201
314
  {!is24Hour && (
202
- <View style={webStyles.periodToggleContainer}>
315
+ <View
316
+ style={[webStyles.periodToggleContainer, periodContainerStyle]}
317
+ >
203
318
  <Pressable
204
319
  onPress={() => handlePeriodChange('AM')}
205
320
  style={[
206
321
  webStyles.periodButton,
207
322
  webStyles.periodButtonTop,
208
- period === 'AM' && webStyles.periodButtonActive,
323
+ period === 'AM' && [
324
+ webStyles.periodButtonActive,
325
+ periodActiveStyle,
326
+ ],
209
327
  ]}
210
328
  >
211
329
  <Text
212
330
  style={[
213
331
  webStyles.periodButtonText,
214
- period === 'AM' && webStyles.periodButtonTextActive,
332
+ periodTextStyle,
333
+ period === 'AM' && [
334
+ webStyles.periodButtonTextActive,
335
+ periodTextActiveStyle,
336
+ ],
215
337
  ]}
216
338
  >
217
339
  AM
@@ -221,13 +343,20 @@ export const MaterialTimePicker: React.FC<MaterialTimePickerProps> = memo(
221
343
  onPress={() => handlePeriodChange('PM')}
222
344
  style={[
223
345
  webStyles.periodButton,
224
- period === 'PM' && webStyles.periodButtonActive,
346
+ period === 'PM' && [
347
+ webStyles.periodButtonActive,
348
+ periodActiveStyle,
349
+ ],
225
350
  ]}
226
351
  >
227
352
  <Text
228
353
  style={[
229
354
  webStyles.periodButtonText,
230
- period === 'PM' && webStyles.periodButtonTextActive,
355
+ periodTextStyle,
356
+ period === 'PM' && [
357
+ webStyles.periodButtonTextActive,
358
+ periodTextActiveStyle,
359
+ ],
231
360
  ]}
232
361
  >
233
362
  PM
@@ -253,12 +382,20 @@ export const MaterialTimePicker: React.FC<MaterialTimePickerProps> = memo(
253
382
  <View style={webStyles.actionButtonsContainer}>
254
383
  {onCancel && (
255
384
  <Pressable style={webStyles.actionButton} onPress={onCancel}>
256
- <Text style={webStyles.actionButtonText}>Cancel</Text>
385
+ <Text
386
+ style={[webStyles.actionButtonText, actionButtonTextStyle]}
387
+ >
388
+ Cancel
389
+ </Text>
257
390
  </Pressable>
258
391
  )}
259
392
  {onConfirm && (
260
393
  <Pressable style={webStyles.actionButton} onPress={onConfirm}>
261
- <Text style={webStyles.actionButtonText}>OK</Text>
394
+ <Text
395
+ style={[webStyles.actionButtonText, actionButtonTextStyle]}
396
+ >
397
+ OK
398
+ </Text>
262
399
  </Pressable>
263
400
  )}
264
401
  </View>
@@ -15,7 +15,7 @@ interface WheelPickerProps {
15
15
  }
16
16
 
17
17
  const getDaysInMonth = (year: number, month: number): number => {
18
- return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
18
+ return new Date(year, month + 1, 0).getDate();
19
19
  };
20
20
 
21
21
  const generateDateItems = (
@@ -26,8 +26,8 @@ const generateDateItems = (
26
26
  ) => {
27
27
  if (type === 'day') {
28
28
  const daysInMonth = getDaysInMonth(
29
- currentDate.getUTCFullYear(),
30
- currentDate.getUTCMonth(),
29
+ currentDate.getFullYear(),
30
+ currentDate.getMonth(),
31
31
  );
32
32
  return Array.from({ length: daysInMonth }, (_, i) => ({
33
33
  value: i + 1,
@@ -40,10 +40,8 @@ const generateDateItems = (
40
40
  label: new Date(2000, i).toLocaleString('en-US', { month: 'short' }),
41
41
  }));
42
42
  }
43
- const minYear =
44
- minDate?.getUTCFullYear() ?? currentDate.getUTCFullYear() - 100;
45
- const maxYear =
46
- maxDate?.getUTCFullYear() ?? currentDate.getUTCFullYear() + 10;
43
+ const minYear = minDate?.getFullYear() ?? currentDate.getFullYear() - 100;
44
+ const maxYear = maxDate?.getFullYear() ?? currentDate.getFullYear() + 10;
47
45
  return Array.from({ length: maxYear - minYear + 1 }, (_, i) => ({
48
46
  value: minYear + i,
49
47
  label: String(minYear + i),
@@ -234,9 +232,7 @@ export const WheelPicker: React.FC<WheelPickerProps> = ({
234
232
  (index: number) => {
235
233
  const newDay = days[index]?.value;
236
234
  if (newDay !== undefined) {
237
- const newDate = new Date(
238
- Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), newDay),
239
- );
235
+ const newDate = new Date(value.getFullYear(), value.getMonth(), newDay);
240
236
  onChange(newDate);
241
237
  }
242
238
  },
@@ -247,11 +243,9 @@ export const WheelPicker: React.FC<WheelPickerProps> = ({
247
243
  (index: number) => {
248
244
  const newMonth = months[index]?.value;
249
245
  if (newMonth !== undefined) {
250
- const daysInNewMonth = getDaysInMonth(value.getUTCFullYear(), newMonth);
251
- const newDay = Math.min(value.getUTCDate(), daysInNewMonth);
252
- const newDate = new Date(
253
- Date.UTC(value.getUTCFullYear(), newMonth, newDay),
254
- );
246
+ const daysInNewMonth = getDaysInMonth(value.getFullYear(), newMonth);
247
+ const newDay = Math.min(value.getDate(), daysInNewMonth);
248
+ const newDate = new Date(value.getFullYear(), newMonth, newDay);
255
249
  onChange(newDate);
256
250
  }
257
251
  },
@@ -262,11 +256,9 @@ export const WheelPicker: React.FC<WheelPickerProps> = ({
262
256
  (index: number) => {
263
257
  const newYear = years[index]?.value;
264
258
  if (newYear !== undefined) {
265
- const daysInNewMonth = getDaysInMonth(newYear, value.getUTCMonth());
266
- const newDay = Math.min(value.getUTCDate(), daysInNewMonth);
267
- const newDate = new Date(
268
- Date.UTC(newYear, value.getUTCMonth(), newDay),
269
- );
259
+ const daysInNewMonth = getDaysInMonth(newYear, value.getMonth());
260
+ const newDay = Math.min(value.getDate(), daysInNewMonth);
261
+ const newDate = new Date(newYear, value.getMonth(), newDay);
270
262
  onChange(newDate);
271
263
  }
272
264
  },
@@ -277,21 +269,19 @@ export const WheelPicker: React.FC<WheelPickerProps> = ({
277
269
  <View style={webStyles.container}>
278
270
  <WheelColumn
279
271
  items={months}
280
- selectedIndex={value.getUTCMonth()}
272
+ selectedIndex={value.getMonth()}
281
273
  onSelect={handleMonthChange}
282
274
  label="Month"
283
275
  />
284
276
  <WheelColumn
285
277
  items={days}
286
- selectedIndex={value.getUTCDate() - 1}
278
+ selectedIndex={value.getDate() - 1}
287
279
  onSelect={handleDayChange}
288
280
  label="Day"
289
281
  />
290
282
  <WheelColumn
291
283
  items={years}
292
- selectedIndex={years.findIndex(
293
- (y) => y.value === value.getUTCFullYear(),
294
- )}
284
+ selectedIndex={years.findIndex((y) => y.value === value.getFullYear())}
295
285
  onSelect={handleYearChange}
296
286
  label="Year"
297
287
  />
@@ -37,8 +37,8 @@ export const useCalendar = (initialDate?: Date) => {
37
37
  }
38
38
 
39
39
  const monthDays = getMonthDays(
40
- currentMonth.getUTCFullYear(),
41
- currentMonth.getUTCMonth(),
40
+ currentMonth.getFullYear(),
41
+ currentMonth.getMonth(),
42
42
  );
43
43
  for (const day of monthDays) {
44
44
  days.push(day);
package/src/utils/date.ts CHANGED
@@ -1,15 +1,19 @@
1
1
  /**
2
2
  * Date utilities using native Date and Intl APIs
3
3
  * Replaces @js-temporal/polyfill for lighter bundle size
4
+ *
5
+ * All date-only values use LOCAL time (not UTC). This ensures that
6
+ * dates displayed in the calendar match what consumers read with
7
+ * standard .getDate(), .getMonth(), .getFullYear() methods.
4
8
  */
5
9
 
6
10
  /**
7
- * Converts a Date to ISO date string (YYYY-MM-DD)
11
+ * Converts a Date to ISO date string (YYYY-MM-DD) using local time
8
12
  */
9
13
  export const toISODateString = (date: Date): string => {
10
- const year = date.getUTCFullYear();
11
- const month = String(date.getUTCMonth() + 1).padStart(2, '0');
12
- const day = String(date.getUTCDate()).padStart(2, '0');
14
+ const year = date.getFullYear();
15
+ const month = String(date.getMonth() + 1).padStart(2, '0');
16
+ const day = String(date.getDate()).padStart(2, '0');
13
17
  return `${year}-${month}-${day}`;
14
18
  };
15
19
 
@@ -34,11 +38,11 @@ export const toISODateTimeString = (date: Date, timeZone?: string): string => {
34
38
  };
35
39
 
36
40
  /**
37
- * Parses an ISO date string (YYYY-MM-DD) to Date
41
+ * Parses an ISO date string (YYYY-MM-DD) to a local Date
38
42
  */
39
43
  export const parseISODate = (iso: string): Date => {
40
44
  const parts = iso.split('-').map(Number) as [number, number, number];
41
- return new Date(Date.UTC(parts[0], parts[1] - 1, parts[2]));
45
+ return new Date(parts[0], parts[1] - 1, parts[2]);
42
46
  };
43
47
 
44
48
  /**
@@ -67,7 +71,7 @@ export const getDateRange = (start: Date, end: Date): Date[] => {
67
71
 
68
72
  while (current.getTime() <= end.getTime()) {
69
73
  dates.push(new Date(current.getTime()));
70
- current.setUTCDate(current.getUTCDate() + 1);
74
+ current.setDate(current.getDate() + 1);
71
75
  }
72
76
 
73
77
  return dates;
@@ -99,7 +103,7 @@ export const getUserTimezone = (): string => {
99
103
  */
100
104
  export const addDays = (date: Date, days: number): Date => {
101
105
  const result = new Date(date.getTime());
102
- result.setUTCDate(result.getUTCDate() + days);
106
+ result.setDate(result.getDate() + days);
103
107
  return result;
104
108
  };
105
109
 
@@ -108,13 +112,15 @@ export const addDays = (date: Date, days: number): Date => {
108
112
  */
109
113
  export const addMonths = (date: Date, months: number): Date => {
110
114
  const result = new Date(date.getTime());
111
- const dayOfMonth = result.getUTCDate();
112
- result.setUTCDate(1);
113
- result.setUTCMonth(result.getUTCMonth() + months);
115
+ const dayOfMonth = result.getDate();
116
+ result.setDate(1);
117
+ result.setMonth(result.getMonth() + months);
114
118
  const daysInMonth = new Date(
115
- Date.UTC(result.getUTCFullYear(), result.getUTCMonth() + 1, 0),
116
- ).getUTCDate();
117
- result.setUTCDate(Math.min(dayOfMonth, daysInMonth));
119
+ result.getFullYear(),
120
+ result.getMonth() + 1,
121
+ 0,
122
+ ).getDate();
123
+ result.setDate(Math.min(dayOfMonth, daysInMonth));
118
124
  return result;
119
125
  };
120
126
 
@@ -137,10 +143,7 @@ export const isSameDay = (a: Date, b: Date): boolean => {
137
143
  * Checks if two dates are the same month
138
144
  */
139
145
  export const isSameMonth = (a: Date, b: Date): boolean => {
140
- return (
141
- a.getUTCFullYear() === b.getUTCFullYear() &&
142
- a.getUTCMonth() === b.getUTCMonth()
143
- );
146
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
144
147
  };
145
148
 
146
149
  /**
@@ -148,9 +151,9 @@ export const isSameMonth = (a: Date, b: Date): boolean => {
148
151
  */
149
152
  export const getMonthDays = (year: number, month: number): Date[] => {
150
153
  const days: Date[] = [];
151
- const daysInMonth = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
154
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
152
155
  for (let day = 1; day <= daysInMonth; day++) {
153
- days.push(new Date(Date.UTC(year, month, day)));
156
+ days.push(new Date(year, month, day));
154
157
  }
155
158
  return days;
156
159
  };
@@ -161,21 +164,21 @@ export const getMonthDays = (year: number, month: number): Date[] => {
161
164
  */
162
165
  export const getFirstDayOfMonth = (date: Date | null | undefined): Date => {
163
166
  const d = date ?? today();
164
- return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1));
167
+ return new Date(d.getFullYear(), d.getMonth(), 1);
165
168
  };
166
169
 
167
170
  /**
168
171
  * Gets the last day of the month
169
172
  */
170
173
  export const getLastDayOfMonth = (date: Date): Date => {
171
- return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0));
174
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0);
172
175
  };
173
176
 
174
177
  /**
175
178
  * Gets the day of week (0 = Sunday, 6 = Saturday)
176
179
  */
177
180
  export const getDayOfWeek = (date: Date): number => {
178
- return date.getUTCDay();
181
+ return date.getDay();
179
182
  };
180
183
 
181
184
  /**
@@ -186,7 +189,9 @@ export const formatMonth = (
186
189
  locale = 'en-US',
187
190
  style: 'long' | 'short' | 'narrow' = 'long',
188
191
  ): string => {
189
- return new Intl.DateTimeFormat(locale, { month: style }).format(date);
192
+ return new Intl.DateTimeFormat(locale, {
193
+ month: style,
194
+ }).format(date);
190
195
  };
191
196
 
192
197
  /**
@@ -197,7 +202,9 @@ export const formatWeekday = (
197
202
  locale = 'en-US',
198
203
  style: 'long' | 'short' | 'narrow' = 'short',
199
204
  ): string => {
200
- return new Intl.DateTimeFormat(locale, { weekday: style }).format(date);
205
+ return new Intl.DateTimeFormat(locale, {
206
+ weekday: style,
207
+ }).format(date);
201
208
  };
202
209
 
203
210
  /**
@@ -211,9 +218,9 @@ export const formatYearMonth = (date: Date, locale = 'en-US'): string => {
211
218
  };
212
219
 
213
220
  /**
214
- * Gets today's date at midnight UTC
221
+ * Gets today's date at local midnight
215
222
  */
216
223
  export const today = (): Date => {
217
224
  const now = new Date();
218
- return new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()));
225
+ return new Date(now.getFullYear(), now.getMonth(), now.getDate());
219
226
  };
@@ -19,12 +19,12 @@ export function isValidISODate(value: string): boolean {
19
19
  number,
20
20
  number,
21
21
  ];
22
- const date = new Date(Date.UTC(year, month - 1, day));
22
+ const date = new Date(year, month - 1, day);
23
23
 
24
24
  return (
25
- date.getUTCFullYear() === year &&
26
- date.getUTCMonth() === month - 1 &&
27
- date.getUTCDate() === day
25
+ date.getFullYear() === year &&
26
+ date.getMonth() === month - 1 &&
27
+ date.getDate() === day
28
28
  );
29
29
  }
30
30
 
@@ -70,7 +70,7 @@ export function parseISODateSafe(value: string): Date | null {
70
70
  number,
71
71
  number,
72
72
  ];
73
- return new Date(Date.UTC(year, month - 1, day));
73
+ return new Date(year, month - 1, day);
74
74
  }
75
75
 
76
76
  // Types for date picker values