compote-ui 0.50.0 → 0.51.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/components/date-field/date-field.svelte +11 -1
- package/dist/components/date-field/types.d.ts +1 -0
- package/dist/components/date-picker/date-picker-calendar.svelte +80 -14
- package/dist/components/date-picker/date-picker-calendar.svelte.d.ts +1 -0
- package/dist/components/date-picker/date-picker.svelte +11 -2
- package/dist/components/date-picker/types.d.ts +1 -0
- package/dist/components/date-range-field/date-range-field.svelte +2 -0
- package/dist/components/date-range-field/types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -21,12 +21,21 @@
|
|
|
21
21
|
invalid,
|
|
22
22
|
timeZone,
|
|
23
23
|
granularity,
|
|
24
|
+
hourCycle,
|
|
24
25
|
onValueChange
|
|
25
26
|
}: DateFieldProps = $props();
|
|
26
27
|
|
|
27
28
|
const locale = useLocaleContext();
|
|
28
29
|
const id = $props.id();
|
|
29
30
|
const showTimeInput = $derived(!!granularity && granularity !== 'day');
|
|
31
|
+
const resolvedHourCycle = $derived(
|
|
32
|
+
hourCycle ??
|
|
33
|
+
(new Intl.DateTimeFormat(locale().locale, { hour: 'numeric' })
|
|
34
|
+
.formatToParts(new Date(2024, 0, 1, 14))
|
|
35
|
+
.some((p) => p.type === 'dayPeriod')
|
|
36
|
+
? 12
|
|
37
|
+
: 24)
|
|
38
|
+
);
|
|
30
39
|
|
|
31
40
|
const datePicker = useDatePicker(() => ({
|
|
32
41
|
id,
|
|
@@ -60,6 +69,7 @@
|
|
|
60
69
|
id,
|
|
61
70
|
locale: locale().locale,
|
|
62
71
|
granularity: granularity ?? 'day',
|
|
72
|
+
hourCycle,
|
|
63
73
|
value: datePicker().value,
|
|
64
74
|
min,
|
|
65
75
|
max,
|
|
@@ -102,7 +112,7 @@
|
|
|
102
112
|
<PhCalendarBlank class="size-4" />
|
|
103
113
|
</DatePicker.Trigger>
|
|
104
114
|
</DatePicker.Control>
|
|
105
|
-
<DatePickerCalendar {showTimeInput} />
|
|
115
|
+
<DatePickerCalendar {showTimeInput} hourCycle={resolvedHourCycle} />
|
|
106
116
|
</DatePicker.RootProvider>
|
|
107
117
|
</DateInput.Control>
|
|
108
118
|
<DateInput.HiddenInput {name} />
|
|
@@ -4,13 +4,25 @@
|
|
|
4
4
|
import { CalendarDateTime } from '@internationalized/date';
|
|
5
5
|
import { PhArrowLeft, PhArrowRight } from '../../icons';
|
|
6
6
|
import type { DateValue } from '@ark-ui/svelte/date-picker';
|
|
7
|
+
import Select from '../select/select.svelte';
|
|
7
8
|
|
|
8
|
-
let { showTimeInput = false }: { showTimeInput?: boolean } =
|
|
9
|
+
let { showTimeInput = false, hourCycle = 24 }: { showTimeInput?: boolean; hourCycle?: 12 | 24 } =
|
|
10
|
+
$props();
|
|
9
11
|
|
|
10
|
-
function
|
|
11
|
-
if (!v || !('hour' in v)) return
|
|
12
|
-
const
|
|
13
|
-
return
|
|
12
|
+
function getHour(v: DateValue | undefined): number {
|
|
13
|
+
if (!v || !('hour' in v)) return 0;
|
|
14
|
+
const h = (v as CalendarDateTime).hour;
|
|
15
|
+
return hourCycle === 12 ? h % 12 || 12 : h;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getMinute(v: DateValue | undefined): number {
|
|
19
|
+
if (!v || !('hour' in v)) return 0;
|
|
20
|
+
return (v as CalendarDateTime).minute;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isPM(v: DateValue | undefined): boolean {
|
|
24
|
+
if (!v || !('hour' in v)) return false;
|
|
25
|
+
return (v as CalendarDateTime).hour >= 12;
|
|
14
26
|
}
|
|
15
27
|
|
|
16
28
|
function setTime(v: DateValue | undefined, hours: number, minutes: number): CalendarDateTime {
|
|
@@ -18,6 +30,32 @@
|
|
|
18
30
|
const d = v ?? new CalendarDateTime(new Date().getFullYear(), 1, 1, 0, 0);
|
|
19
31
|
return new CalendarDateTime(d.year, d.month, d.day, hours, minutes);
|
|
20
32
|
}
|
|
33
|
+
|
|
34
|
+
function updateHour(v: DateValue | undefined, displayHour: number): CalendarDateTime {
|
|
35
|
+
let h = displayHour;
|
|
36
|
+
if (hourCycle === 12) {
|
|
37
|
+
const pm = isPM(v);
|
|
38
|
+
h = pm ? (displayHour % 12) + 12 : displayHour % 12;
|
|
39
|
+
}
|
|
40
|
+
return setTime(v, h, getMinute(v));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function togglePeriod(v: DateValue | undefined): CalendarDateTime {
|
|
44
|
+
const cur = v && 'hour' in v ? (v as CalendarDateTime).hour : 0;
|
|
45
|
+
return setTime(v, cur >= 12 ? cur - 12 : cur + 12, getMinute(v));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const minuteItems = Array.from({ length: 60 }, (_, m) => ({
|
|
49
|
+
value: m,
|
|
50
|
+
label: String(m).padStart(2, '0')
|
|
51
|
+
}));
|
|
52
|
+
|
|
53
|
+
const hourItems = $derived(
|
|
54
|
+
Array.from({ length: hourCycle === 12 ? 12 : 24 }, (_, i) => {
|
|
55
|
+
const h = hourCycle === 12 ? i + 1 : i;
|
|
56
|
+
return { value: h, label: String(h).padStart(2, '0') };
|
|
57
|
+
})
|
|
58
|
+
);
|
|
21
59
|
</script>
|
|
22
60
|
|
|
23
61
|
<Portal>
|
|
@@ -74,15 +112,43 @@
|
|
|
74
112
|
</DatePicker.TableBody>
|
|
75
113
|
</DatePicker.Table>
|
|
76
114
|
{#if showTimeInput}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
115
|
+
{@const cur = datePicker().value[0]}
|
|
116
|
+
<div class="mt-3 flex items-center justify-center gap-1">
|
|
117
|
+
<Select
|
|
118
|
+
items={hourItems}
|
|
119
|
+
value={getHour(cur)}
|
|
120
|
+
size="sm"
|
|
121
|
+
placeholder="HH"
|
|
122
|
+
onValueChange={(d) =>
|
|
123
|
+
datePicker().setValue([updateHour(cur, Number(d.items[0]?.value))])}
|
|
124
|
+
/>
|
|
125
|
+
<span class="text-ink-dim">:</span>
|
|
126
|
+
<Select
|
|
127
|
+
items={minuteItems}
|
|
128
|
+
value={getMinute(cur)}
|
|
129
|
+
size="sm"
|
|
130
|
+
placeholder="mm"
|
|
131
|
+
onValueChange={(d) => {
|
|
132
|
+
const m = Number(d.items[0]?.value);
|
|
133
|
+
const h24 =
|
|
134
|
+
hourCycle === 12
|
|
135
|
+
? isPM(cur)
|
|
136
|
+
? (getHour(cur) % 12) + 12
|
|
137
|
+
: getHour(cur) % 12
|
|
138
|
+
: getHour(cur);
|
|
139
|
+
datePicker().setValue([setTime(cur, h24, m)]);
|
|
140
|
+
}}
|
|
141
|
+
/>
|
|
142
|
+
{#if hourCycle === 12}
|
|
143
|
+
<button
|
|
144
|
+
type="button"
|
|
145
|
+
onclick={() => datePicker().setValue([togglePeriod(cur)])}
|
|
146
|
+
class="h-8 rounded-md border border-border bg-surface-1 px-2 text-sm shadow-sm hover:bg-surface-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
147
|
+
>
|
|
148
|
+
{isPM(cur) ? 'PM' : 'AM'}
|
|
149
|
+
</button>
|
|
150
|
+
{/if}
|
|
151
|
+
</div>
|
|
86
152
|
{/if}
|
|
87
153
|
{/snippet}
|
|
88
154
|
</DatePicker.Context>
|
|
@@ -14,12 +14,21 @@
|
|
|
14
14
|
placeholder,
|
|
15
15
|
name,
|
|
16
16
|
granularity,
|
|
17
|
+
hourCycle,
|
|
17
18
|
onValueChange,
|
|
18
19
|
...restProps
|
|
19
20
|
}: DatePickerProps = $props();
|
|
20
21
|
|
|
21
22
|
const locale = useLocaleContext();
|
|
22
23
|
const showTimeInput = $derived(!!granularity && granularity !== 'day');
|
|
24
|
+
const resolvedHourCycle = $derived(
|
|
25
|
+
hourCycle ??
|
|
26
|
+
(new Intl.DateTimeFormat(locale().locale, { hour: 'numeric' })
|
|
27
|
+
.formatToParts(new Date(2024, 0, 1, 14))
|
|
28
|
+
.some((p) => p.type === 'dayPeriod')
|
|
29
|
+
? 12
|
|
30
|
+
: 24)
|
|
31
|
+
);
|
|
23
32
|
</script>
|
|
24
33
|
|
|
25
34
|
<DatePicker.Root
|
|
@@ -30,7 +39,7 @@
|
|
|
30
39
|
defaultValue={defaultValue ? [defaultValue] : undefined}
|
|
31
40
|
onValueChange={(details) => {
|
|
32
41
|
const picked = details.value[0] ?? null;
|
|
33
|
-
if (picked && showTimeInput) {
|
|
42
|
+
if (picked && showTimeInput && !('hour' in picked)) {
|
|
34
43
|
const h = value && 'hour' in value ? (value as CalendarDateTime).hour : 0;
|
|
35
44
|
const m = value && 'hour' in value ? (value as CalendarDateTime).minute : 0;
|
|
36
45
|
value = new CalendarDateTime(picked.year, picked.month, picked.day, h, m);
|
|
@@ -62,7 +71,7 @@
|
|
|
62
71
|
<PhX class="size-3.5" />
|
|
63
72
|
</DatePicker.ClearTrigger>
|
|
64
73
|
</DatePicker.Control>
|
|
65
|
-
<DatePickerCalendar {showTimeInput} />
|
|
74
|
+
<DatePickerCalendar {showTimeInput} hourCycle={resolvedHourCycle} />
|
|
66
75
|
{#if name}
|
|
67
76
|
<input type="hidden" {name} value={value ?? ''} />
|
|
68
77
|
{/if}
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
required,
|
|
20
20
|
invalid,
|
|
21
21
|
timeZone,
|
|
22
|
+
hourCycle,
|
|
22
23
|
onValueChange
|
|
23
24
|
}: DateRangeFieldProps = $props();
|
|
24
25
|
|
|
@@ -48,6 +49,7 @@
|
|
|
48
49
|
id,
|
|
49
50
|
locale: locale().locale,
|
|
50
51
|
selectionMode: 'range',
|
|
52
|
+
hourCycle,
|
|
51
53
|
value: datePicker().value,
|
|
52
54
|
min,
|
|
53
55
|
max,
|