flowbite-svelte 1.6.2 → 1.6.3
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.
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
const dateFormatOptions = $derived(dateFormat ?? dateFormatDefault);
|
|
11
11
|
// Internal state
|
|
12
12
|
let isOpen: boolean = $state(inline);
|
|
13
|
+
let showMonthSelector: boolean = $state(false);
|
|
13
14
|
let inputElement: HTMLInputElement | null = $state(null);
|
|
14
15
|
let datepickerContainerElement: HTMLDivElement;
|
|
15
16
|
let currentMonth: Date = $state(value || defaultDate || new Date());
|
|
@@ -62,6 +63,11 @@
|
|
|
62
63
|
};
|
|
63
64
|
let weekdays = getWeekdayNames();
|
|
64
65
|
|
|
66
|
+
const getMonthNames = (): string[] => {
|
|
67
|
+
return Array.from({ length: 12 }, (_, i) => new Date(2000, i, 1).toLocaleDateString(locale, { month: "short" }));
|
|
68
|
+
};
|
|
69
|
+
let monthNames = getMonthNames();
|
|
70
|
+
|
|
65
71
|
const addMonth = (date: Date, increment: number): Date => new Date(date.getFullYear(), date.getMonth() + increment, 1);
|
|
66
72
|
const addDay = (date: Date, increment: number): Date => new Date(date.getFullYear(), date.getMonth(), date.getDate() + increment);
|
|
67
73
|
|
|
@@ -69,6 +75,21 @@
|
|
|
69
75
|
currentMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + increment, 1);
|
|
70
76
|
}
|
|
71
77
|
|
|
78
|
+
function changeYear(increment: number) {
|
|
79
|
+
currentMonth = new Date(currentMonth.getFullYear() + increment, currentMonth.getMonth(), 1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function selectMonth(monthIndex: number, event: MouseEvent) {
|
|
83
|
+
event.stopPropagation();
|
|
84
|
+
currentMonth = new Date(currentMonth.getFullYear(), monthIndex, 1);
|
|
85
|
+
showMonthSelector = false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function toggleMonthSelector(event: MouseEvent) {
|
|
89
|
+
event.stopPropagation();
|
|
90
|
+
showMonthSelector = !showMonthSelector;
|
|
91
|
+
}
|
|
92
|
+
|
|
72
93
|
function handleDaySelect(day: Date) {
|
|
73
94
|
if (range) {
|
|
74
95
|
if (!rangeFrom || (rangeFrom && rangeTo)) {
|
|
@@ -98,6 +119,7 @@
|
|
|
98
119
|
function handleClickOutside(event: MouseEvent) {
|
|
99
120
|
if (isOpen && datepickerContainerElement && !datepickerContainerElement.contains(event.target as Node)) {
|
|
100
121
|
isOpen = false;
|
|
122
|
+
showMonthSelector = false;
|
|
101
123
|
}
|
|
102
124
|
}
|
|
103
125
|
|
|
@@ -133,6 +155,7 @@
|
|
|
133
155
|
break;
|
|
134
156
|
case "Escape":
|
|
135
157
|
isOpen = false;
|
|
158
|
+
showMonthSelector = false;
|
|
136
159
|
inputElement?.focus();
|
|
137
160
|
break;
|
|
138
161
|
default:
|
|
@@ -180,6 +203,14 @@
|
|
|
180
203
|
</ToolbarButton>
|
|
181
204
|
{/snippet}
|
|
182
205
|
|
|
206
|
+
{#snippet yearNavButton(forward: boolean)}
|
|
207
|
+
<ToolbarButton color="dark" onclick={() => changeYear(forward ? 1 : -1)} size="lg" aria-label={forward ? "Next year" : "Previous year"}>
|
|
208
|
+
<svg class="h-3 w-3 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 10">
|
|
209
|
+
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d={forward ? "M1 5h12m0 0L9 1m4 4L9 9" : "M13 5H1m0 0 4 4M1 5l4-4"}></path>
|
|
210
|
+
</svg>
|
|
211
|
+
</ToolbarButton>
|
|
212
|
+
{/snippet}
|
|
213
|
+
|
|
183
214
|
<div bind:this={datepickerContainerElement} class={["relative", inline && "inline-block"]}>
|
|
184
215
|
{#if !inline}
|
|
185
216
|
<div class="relative">
|
|
@@ -197,25 +228,46 @@
|
|
|
197
228
|
{#if title}
|
|
198
229
|
<h2 class={titleVariant()}>{title}</h2>
|
|
199
230
|
{/if}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
231
|
+
|
|
232
|
+
{#if showMonthSelector}
|
|
233
|
+
<!-- Month/Year Selector View -->
|
|
234
|
+
<div class={nav()}>
|
|
235
|
+
{@render yearNavButton(false)}
|
|
236
|
+
<h3 class={polite()} aria-live="polite">
|
|
237
|
+
{currentMonth.getFullYear()}
|
|
238
|
+
</h3>
|
|
239
|
+
{@render yearNavButton(true)}
|
|
240
|
+
</div>
|
|
241
|
+
<div class="grid grid-cols-4 gap-2 p-4">
|
|
242
|
+
{#each monthNames as month, index}
|
|
243
|
+
<button type="button" class="rounded-lg px-3 py-2 text-sm hover:bg-gray-100 focus:ring-2 focus:ring-blue-500 dark:hover:bg-gray-700 {currentMonth.getMonth() === index ? 'bg-blue-500 text-white' : 'text-gray-700 dark:text-gray-300'}" onclick={(event) => selectMonth(index, event)}>
|
|
244
|
+
{month}
|
|
245
|
+
</button>
|
|
246
|
+
{/each}
|
|
247
|
+
</div>
|
|
248
|
+
{:else}
|
|
249
|
+
<!-- Regular Calendar View -->
|
|
250
|
+
<div class={nav()}>
|
|
251
|
+
{@render navButton(false)}
|
|
252
|
+
<button type="button" class={cn(polite(), "cursor-pointer rounded px-2 py-1 hover:bg-gray-100 dark:hover:bg-gray-700")} aria-live="polite" onclick={(event) => toggleMonthSelector(event)}>
|
|
253
|
+
{currentMonth.toLocaleString(locale, { month: "long", year: "numeric" })}
|
|
215
254
|
</button>
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
255
|
+
{@render navButton(true)}
|
|
256
|
+
</div>
|
|
257
|
+
<div class={grid()} role="grid">
|
|
258
|
+
{#each weekdays as day}
|
|
259
|
+
<div class={columnHeader()} role="columnheader">{day}</div>
|
|
260
|
+
{/each}
|
|
261
|
+
{#each daysInMonth as day}
|
|
262
|
+
{@const current = day.getMonth() !== currentMonth.getMonth()}
|
|
263
|
+
<button type="button" color={isSelected(day) ? color : "alternative"} class={dayButton({ current, today: isToday(day), color: isInRange(day) ? color : undefined })} onclick={() => handleDaySelect(day)} onkeydown={handleCalendarKeydown} aria-label={day.toLocaleDateString(locale, { weekday: "long", year: "numeric", month: "long", day: "numeric" })} aria-selected={isSelected(day)} role="gridcell">
|
|
264
|
+
{day.getDate()}
|
|
265
|
+
</button>
|
|
266
|
+
{/each}
|
|
267
|
+
</div>
|
|
268
|
+
{/if}
|
|
269
|
+
|
|
270
|
+
{#if showActionButtons && !showMonthSelector}
|
|
219
271
|
<div class={actionButtons()}>
|
|
220
272
|
<Button onclick={() => handleDaySelect(new Date())} {color} size="sm">Today</Button>
|
|
221
273
|
<Button onclick={handleClear} color="red" size="sm">Clear</Button>
|