@aiaiai-pt/design-system 0.4.3 → 0.5.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/components/Calendar.svelte +971 -0
- package/components/Calendar.svelte.d.ts +50 -0
- package/components/DatePicker.svelte +473 -0
- package/components/DatePicker.svelte.d.ts +59 -0
- package/components/DateRangePicker.svelte +558 -0
- package/components/DateRangePicker.svelte.d.ts +55 -0
- package/components/DateTimePicker.svelte +275 -0
- package/components/DateTimePicker.svelte.d.ts +55 -0
- package/components/FilterPanel.svelte +53 -8
- package/components/MapCluster.svelte +220 -0
- package/components/MapCluster.svelte.d.ts +39 -0
- package/components/MapDisplay.svelte +139 -0
- package/components/MapDisplay.svelte.d.ts +35 -0
- package/components/MapHeatmap.svelte +164 -0
- package/components/MapHeatmap.svelte.d.ts +50 -0
- package/components/MapPicker.svelte +243 -0
- package/components/MapPicker.svelte.d.ts +49 -0
- package/components/MapPopup.svelte +101 -0
- package/components/MapPopup.svelte.d.ts +30 -0
- package/components/StatCard.svelte +195 -0
- package/components/StatCard.svelte.d.ts +42 -0
- package/components/StatGrid.svelte +39 -0
- package/components/StatGrid.svelte.d.ts +29 -0
- package/components/index.d.ts +12 -0
- package/components/index.js +17 -0
- package/components/map-utils.d.ts +100 -0
- package/components/map-utils.js +338 -0
- package/package.json +8 -1
- package/tokens/components.css +215 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export default Calendar;
|
|
2
|
+
type Calendar = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Calendar
|
|
8
|
+
*
|
|
9
|
+
* Full-page scheduling calendar with month, week, and day views.
|
|
10
|
+
* Events rendered as colored blocks with title, time, and optional status.
|
|
11
|
+
* Navigation with prev/next, today button, and view switcher.
|
|
12
|
+
* Consumes --calendar-* tokens from components.css.
|
|
13
|
+
*
|
|
14
|
+
* @example Basic month view
|
|
15
|
+
* <Calendar events={events} oneventclick={(ev) => console.log(ev)} />
|
|
16
|
+
*
|
|
17
|
+
* @example Week view with locale
|
|
18
|
+
* <Calendar view="week" events={events} locale={pt} />
|
|
19
|
+
*
|
|
20
|
+
* @example Custom event rendering
|
|
21
|
+
* <Calendar events={events}>
|
|
22
|
+
* {#snippet event(ev)}
|
|
23
|
+
* <span>{ev.title}</span>
|
|
24
|
+
* <Badge>{ev.status}</Badge>
|
|
25
|
+
* {/snippet}
|
|
26
|
+
* </Calendar>
|
|
27
|
+
*/
|
|
28
|
+
declare const Calendar: import("svelte").Component<{
|
|
29
|
+
view?: string;
|
|
30
|
+
date?: any;
|
|
31
|
+
events?: any[];
|
|
32
|
+
maxVisible?: number;
|
|
33
|
+
locale?: typeof enUS;
|
|
34
|
+
oneventclick?: any;
|
|
35
|
+
ondateclick?: any;
|
|
36
|
+
event?: any;
|
|
37
|
+
class?: string;
|
|
38
|
+
} & Record<string, any>, {}, "view" | "date">;
|
|
39
|
+
type $$ComponentProps = {
|
|
40
|
+
view?: string;
|
|
41
|
+
date?: any;
|
|
42
|
+
events?: any[];
|
|
43
|
+
maxVisible?: number;
|
|
44
|
+
locale?: typeof enUS;
|
|
45
|
+
oneventclick?: any;
|
|
46
|
+
ondateclick?: any;
|
|
47
|
+
event?: any;
|
|
48
|
+
class?: string;
|
|
49
|
+
} & Record<string, any>;
|
|
50
|
+
import { enUS } from 'date-fns/locale';
|
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component DatePicker
|
|
3
|
+
|
|
4
|
+
Calendar dropdown for date selection. Values displayed in Berkeley Mono (data font).
|
|
5
|
+
Locale-aware formatting via date-fns. Follows Input patterns for label, help, error.
|
|
6
|
+
Consumes --datepicker-* and --input-* tokens from components.css.
|
|
7
|
+
|
|
8
|
+
@example Basic
|
|
9
|
+
<DatePicker label="START DATE" bind:value={startDate} />
|
|
10
|
+
|
|
11
|
+
@example With constraints
|
|
12
|
+
<DatePicker label="BIRTH DATE" min={new Date(1900, 0, 1)} max={new Date()} />
|
|
13
|
+
|
|
14
|
+
@example Error
|
|
15
|
+
<DatePicker label="DUE DATE" error="Date is required" />
|
|
16
|
+
|
|
17
|
+
@example Locale
|
|
18
|
+
<DatePicker label="DATA" locale={pt} />
|
|
19
|
+
-->
|
|
20
|
+
<script module>
|
|
21
|
+
let _datepickerUid = 0;
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<script>
|
|
25
|
+
import { format, startOfMonth, endOfMonth, startOfWeek, endOfWeek, addDays, addMonths, subMonths, isSameDay, isSameMonth, isBefore, isAfter } from 'date-fns';
|
|
26
|
+
import { enUS } from 'date-fns/locale';
|
|
27
|
+
import Popover from './Popover.svelte';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {'sm' | 'md' | 'lg'} Size
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
let {
|
|
34
|
+
/** @type {Date | null} */
|
|
35
|
+
value = $bindable(null),
|
|
36
|
+
/** @type {string | undefined} */
|
|
37
|
+
label = undefined,
|
|
38
|
+
/** @type {string | undefined} */
|
|
39
|
+
placeholder = 'Select date',
|
|
40
|
+
/** @type {string | undefined} */
|
|
41
|
+
help = undefined,
|
|
42
|
+
/** @type {string | undefined} */
|
|
43
|
+
error = undefined,
|
|
44
|
+
/** @type {Size} */
|
|
45
|
+
size = 'md',
|
|
46
|
+
/** @type {boolean} */
|
|
47
|
+
disabled = false,
|
|
48
|
+
/** @type {boolean} */
|
|
49
|
+
readonly = false,
|
|
50
|
+
/** @type {Date | undefined} */
|
|
51
|
+
min = undefined,
|
|
52
|
+
/** @type {Date | undefined} */
|
|
53
|
+
max = undefined,
|
|
54
|
+
/** @type {string} */
|
|
55
|
+
displayFormat = 'dd/MM/yyyy',
|
|
56
|
+
/** @type {import('date-fns').Locale} */
|
|
57
|
+
locale = enUS,
|
|
58
|
+
/** @type {((date: Date) => void) | undefined} */
|
|
59
|
+
onchange = undefined,
|
|
60
|
+
/** @type {string | undefined} */
|
|
61
|
+
id = undefined,
|
|
62
|
+
/** @type {string} */
|
|
63
|
+
class: className = '',
|
|
64
|
+
...rest
|
|
65
|
+
} = $props();
|
|
66
|
+
|
|
67
|
+
const fallbackId = `datepicker-${_datepickerUid++}`;
|
|
68
|
+
const inputId = $derived(id ?? fallbackId);
|
|
69
|
+
const hintId = $derived(`${inputId}-hint`);
|
|
70
|
+
const hasHint = $derived(!!error || !!help);
|
|
71
|
+
|
|
72
|
+
let open = $state(false);
|
|
73
|
+
/** @type {HTMLElement | undefined} */
|
|
74
|
+
let triggerEl = $state();
|
|
75
|
+
let viewDate = $state(value ?? new Date());
|
|
76
|
+
|
|
77
|
+
const displayValue = $derived(value ? format(value, displayFormat, { locale }) : '');
|
|
78
|
+
|
|
79
|
+
const weekdays = $derived(getWeekdays(locale));
|
|
80
|
+
const calendarDays = $derived(getCalendarDays(viewDate, locale));
|
|
81
|
+
|
|
82
|
+
/** @param {import('date-fns').Locale} loc */
|
|
83
|
+
function getWeekdays(loc) {
|
|
84
|
+
const start = startOfWeek(new Date(), { locale: loc });
|
|
85
|
+
return Array.from({ length: 7 }, (_, i) =>
|
|
86
|
+
format(addDays(start, i), 'EEEEEE', { locale: loc })
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** @param {Date} month @param {import('date-fns').Locale} loc */
|
|
91
|
+
function getCalendarDays(month, loc) {
|
|
92
|
+
const monthStart = startOfMonth(month);
|
|
93
|
+
const monthEnd = endOfMonth(month);
|
|
94
|
+
const calStart = startOfWeek(monthStart, { locale: loc });
|
|
95
|
+
const calEnd = endOfWeek(monthEnd, { locale: loc });
|
|
96
|
+
|
|
97
|
+
/** @type {Date[]} */
|
|
98
|
+
const days = [];
|
|
99
|
+
let cursor = calStart;
|
|
100
|
+
while (isBefore(cursor, calEnd) || isSameDay(cursor, calEnd)) {
|
|
101
|
+
days.push(cursor);
|
|
102
|
+
cursor = addDays(cursor, 1);
|
|
103
|
+
}
|
|
104
|
+
return days;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** @param {Date} date */
|
|
108
|
+
function isDisabledDate(date) {
|
|
109
|
+
if (min && isBefore(date, min)) return true;
|
|
110
|
+
if (max && isAfter(date, max)) return true;
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** @param {Date} date */
|
|
115
|
+
function selectDate(date) {
|
|
116
|
+
if (isDisabledDate(date)) return;
|
|
117
|
+
value = date;
|
|
118
|
+
open = false;
|
|
119
|
+
onchange?.(date);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function prevMonth() {
|
|
123
|
+
viewDate = subMonths(viewDate, 1);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function nextMonth() {
|
|
127
|
+
viewDate = addMonths(viewDate, 1);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function handleTriggerClick() {
|
|
131
|
+
if (disabled || readonly) return;
|
|
132
|
+
open = !open;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** @param {KeyboardEvent} e */
|
|
136
|
+
function handleTriggerKeydown(e) {
|
|
137
|
+
if (disabled || readonly) return;
|
|
138
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
open = !open;
|
|
141
|
+
}
|
|
142
|
+
if (e.key === 'ArrowDown') {
|
|
143
|
+
e.preventDefault();
|
|
144
|
+
open = true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** @param {KeyboardEvent} e @param {Date} date */
|
|
149
|
+
function handleDayKeydown(e, date) {
|
|
150
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
151
|
+
e.preventDefault();
|
|
152
|
+
selectDate(date);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Sync viewDate when value changes externally
|
|
157
|
+
$effect(() => {
|
|
158
|
+
if (value) {
|
|
159
|
+
viewDate = value;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
</script>
|
|
163
|
+
|
|
164
|
+
<div class="datepicker {className}" {...rest}>
|
|
165
|
+
{#if label}
|
|
166
|
+
<label class="datepicker-label" for={inputId}>{label}</label>
|
|
167
|
+
{/if}
|
|
168
|
+
|
|
169
|
+
<button
|
|
170
|
+
bind:this={triggerEl}
|
|
171
|
+
id={inputId}
|
|
172
|
+
type="button"
|
|
173
|
+
class="datepicker-trigger datepicker-trigger-{size}"
|
|
174
|
+
class:datepicker-trigger-error={!!error}
|
|
175
|
+
class:datepicker-trigger-readonly={readonly}
|
|
176
|
+
aria-haspopup="dialog"
|
|
177
|
+
aria-expanded={open}
|
|
178
|
+
aria-invalid={error ? true : undefined}
|
|
179
|
+
aria-describedby={hasHint ? hintId : undefined}
|
|
180
|
+
{disabled}
|
|
181
|
+
onclick={handleTriggerClick}
|
|
182
|
+
onkeydown={handleTriggerKeydown}
|
|
183
|
+
>
|
|
184
|
+
<span class="datepicker-value" class:datepicker-placeholder={!value}>
|
|
185
|
+
{displayValue || placeholder}
|
|
186
|
+
</span>
|
|
187
|
+
<svg class="datepicker-icon" viewBox="0 0 256 256" fill="none" aria-hidden="true">
|
|
188
|
+
<rect x="40" y="40" width="176" height="176" rx="8" stroke="currentColor" stroke-width="16" fill="none" />
|
|
189
|
+
<line x1="176" y1="24" x2="176" y2="56" stroke="currentColor" stroke-width="16" stroke-linecap="round" />
|
|
190
|
+
<line x1="80" y1="24" x2="80" y2="56" stroke="currentColor" stroke-width="16" stroke-linecap="round" />
|
|
191
|
+
<line x1="40" y1="88" x2="216" y2="88" stroke="currentColor" stroke-width="16" stroke-linecap="round" />
|
|
192
|
+
</svg>
|
|
193
|
+
</button>
|
|
194
|
+
|
|
195
|
+
<Popover bind:open anchor={triggerEl} placement="bottom-start" onclose={() => (open = false)}>
|
|
196
|
+
<div class="datepicker-calendar" role="application" aria-label="Calendar">
|
|
197
|
+
<div class="datepicker-nav">
|
|
198
|
+
<button type="button" class="datepicker-nav-btn" onclick={prevMonth} aria-label="Previous month">
|
|
199
|
+
<svg viewBox="0 0 256 256" aria-hidden="true">
|
|
200
|
+
<polyline points="160,208 80,128 160,48" fill="none" stroke="currentColor" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" />
|
|
201
|
+
</svg>
|
|
202
|
+
</button>
|
|
203
|
+
<span class="datepicker-nav-title">
|
|
204
|
+
{format(viewDate, 'LLLL yyyy', { locale })}
|
|
205
|
+
</span>
|
|
206
|
+
<button type="button" class="datepicker-nav-btn" onclick={nextMonth} aria-label="Next month">
|
|
207
|
+
<svg viewBox="0 0 256 256" aria-hidden="true">
|
|
208
|
+
<polyline points="96,48 176,128 96,208" fill="none" stroke="currentColor" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" />
|
|
209
|
+
</svg>
|
|
210
|
+
</button>
|
|
211
|
+
</div>
|
|
212
|
+
|
|
213
|
+
<div class="datepicker-grid" role="grid" aria-label="Calendar dates">
|
|
214
|
+
<div class="datepicker-weekdays" role="row">
|
|
215
|
+
{#each weekdays as day}
|
|
216
|
+
<span class="datepicker-weekday" role="columnheader">{day}</span>
|
|
217
|
+
{/each}
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
<div class="datepicker-days" role="rowgroup">
|
|
221
|
+
{#each calendarDays as date}
|
|
222
|
+
{@const isSelected = value && isSameDay(date, value)}
|
|
223
|
+
{@const isToday = isSameDay(date, new Date())}
|
|
224
|
+
{@const isOutside = !isSameMonth(date, viewDate)}
|
|
225
|
+
{@const isDisabled = isDisabledDate(date)}
|
|
226
|
+
<button
|
|
227
|
+
type="button"
|
|
228
|
+
class="datepicker-day"
|
|
229
|
+
class:datepicker-day-selected={isSelected}
|
|
230
|
+
class:datepicker-day-today={isToday && !isSelected}
|
|
231
|
+
class:datepicker-day-outside={isOutside}
|
|
232
|
+
role="gridcell"
|
|
233
|
+
aria-selected={isSelected}
|
|
234
|
+
aria-disabled={isDisabled}
|
|
235
|
+
tabindex={isSelected || (!value && isToday) ? 0 : -1}
|
|
236
|
+
disabled={isDisabled}
|
|
237
|
+
onclick={() => selectDate(date)}
|
|
238
|
+
onkeydown={(e) => handleDayKeydown(e, date)}
|
|
239
|
+
>
|
|
240
|
+
{date.getDate()}
|
|
241
|
+
</button>
|
|
242
|
+
{/each}
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
</Popover>
|
|
247
|
+
|
|
248
|
+
{#if error}
|
|
249
|
+
<span id={hintId} class="datepicker-error-text" role="alert">{error}</span>
|
|
250
|
+
{:else if help}
|
|
251
|
+
<span id={hintId} class="datepicker-help">{help}</span>
|
|
252
|
+
{/if}
|
|
253
|
+
</div>
|
|
254
|
+
|
|
255
|
+
<style>
|
|
256
|
+
.datepicker {
|
|
257
|
+
display: flex;
|
|
258
|
+
flex-direction: column;
|
|
259
|
+
gap: var(--input-label-gap);
|
|
260
|
+
width: 100%;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.datepicker-label {
|
|
264
|
+
font-family: var(--input-label-font);
|
|
265
|
+
font-size: var(--input-label-size);
|
|
266
|
+
letter-spacing: var(--input-label-tracking);
|
|
267
|
+
color: var(--input-label-color);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/* ─── Trigger ─── */
|
|
271
|
+
.datepicker-trigger {
|
|
272
|
+
display: flex;
|
|
273
|
+
align-items: center;
|
|
274
|
+
justify-content: space-between;
|
|
275
|
+
gap: var(--space-xs);
|
|
276
|
+
font-family: var(--input-font);
|
|
277
|
+
font-size: var(--input-font-size);
|
|
278
|
+
border: var(--input-border);
|
|
279
|
+
border-radius: var(--input-radius);
|
|
280
|
+
background: var(--input-bg);
|
|
281
|
+
color: var(--input-text);
|
|
282
|
+
cursor: pointer;
|
|
283
|
+
width: 100%;
|
|
284
|
+
text-align: left;
|
|
285
|
+
transition: border var(--input-transition);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.datepicker-trigger-sm {
|
|
289
|
+
height: var(--input-sm-height);
|
|
290
|
+
padding: 0 var(--input-sm-padding-x);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.datepicker-trigger-md {
|
|
294
|
+
height: var(--input-md-height);
|
|
295
|
+
padding: 0 var(--input-md-padding-x);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.datepicker-trigger-lg {
|
|
299
|
+
height: var(--input-lg-height);
|
|
300
|
+
padding: 0 var(--input-lg-padding-x);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.datepicker-trigger:focus {
|
|
304
|
+
outline: none;
|
|
305
|
+
border: var(--input-border-focus);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.datepicker-trigger:disabled {
|
|
309
|
+
opacity: 0.5;
|
|
310
|
+
cursor: not-allowed;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.datepicker-trigger-readonly {
|
|
314
|
+
background: var(--color-surface-secondary);
|
|
315
|
+
cursor: default;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.datepicker-trigger-error {
|
|
319
|
+
border-color: var(--input-error-border-color);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.datepicker-value {
|
|
323
|
+
flex: 1;
|
|
324
|
+
min-width: 0;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.datepicker-placeholder {
|
|
328
|
+
color: var(--datepicker-placeholder-color);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.datepicker-icon {
|
|
332
|
+
flex-shrink: 0;
|
|
333
|
+
width: var(--datepicker-icon-size);
|
|
334
|
+
height: var(--datepicker-icon-size);
|
|
335
|
+
color: var(--datepicker-icon-color);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* ─── Calendar ─── */
|
|
339
|
+
.datepicker-calendar {
|
|
340
|
+
padding: var(--datepicker-calendar-padding);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.datepicker-nav {
|
|
344
|
+
display: flex;
|
|
345
|
+
align-items: center;
|
|
346
|
+
justify-content: space-between;
|
|
347
|
+
margin-bottom: var(--space-sm);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.datepicker-nav-title {
|
|
351
|
+
font-family: var(--datepicker-nav-font);
|
|
352
|
+
font-size: var(--datepicker-nav-size);
|
|
353
|
+
letter-spacing: var(--datepicker-nav-tracking);
|
|
354
|
+
color: var(--datepicker-nav-color);
|
|
355
|
+
text-transform: uppercase;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.datepicker-nav-btn {
|
|
359
|
+
display: flex;
|
|
360
|
+
align-items: center;
|
|
361
|
+
justify-content: center;
|
|
362
|
+
width: var(--datepicker-nav-btn-size);
|
|
363
|
+
height: var(--datepicker-nav-btn-size);
|
|
364
|
+
border: none;
|
|
365
|
+
border-radius: var(--datepicker-nav-btn-radius);
|
|
366
|
+
background: transparent;
|
|
367
|
+
color: var(--color-text-secondary);
|
|
368
|
+
cursor: pointer;
|
|
369
|
+
transition: background var(--duration-instant) var(--easing-default);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.datepicker-nav-btn:hover {
|
|
373
|
+
background: var(--datepicker-nav-btn-hover-bg);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.datepicker-nav-btn svg {
|
|
377
|
+
width: var(--icon-size-xs);
|
|
378
|
+
height: var(--icon-size-xs);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* ─── Grid ─── */
|
|
382
|
+
.datepicker-grid {
|
|
383
|
+
display: flex;
|
|
384
|
+
flex-direction: column;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.datepicker-weekdays {
|
|
388
|
+
display: grid;
|
|
389
|
+
grid-template-columns: repeat(7, 1fr);
|
|
390
|
+
margin-bottom: var(--space-2xs);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.datepicker-weekday {
|
|
394
|
+
display: flex;
|
|
395
|
+
align-items: center;
|
|
396
|
+
justify-content: center;
|
|
397
|
+
height: var(--datepicker-day-size);
|
|
398
|
+
font-family: var(--datepicker-weekday-font);
|
|
399
|
+
font-size: var(--datepicker-weekday-size);
|
|
400
|
+
letter-spacing: var(--datepicker-weekday-tracking);
|
|
401
|
+
color: var(--datepicker-weekday-color);
|
|
402
|
+
text-transform: uppercase;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
.datepicker-days {
|
|
406
|
+
display: grid;
|
|
407
|
+
grid-template-columns: repeat(7, 1fr);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.datepicker-day {
|
|
411
|
+
display: flex;
|
|
412
|
+
align-items: center;
|
|
413
|
+
justify-content: center;
|
|
414
|
+
width: var(--datepicker-day-size);
|
|
415
|
+
height: var(--datepicker-day-size);
|
|
416
|
+
font-family: var(--datepicker-day-font);
|
|
417
|
+
font-size: var(--datepicker-day-font-size);
|
|
418
|
+
border: none;
|
|
419
|
+
border-radius: var(--datepicker-day-radius);
|
|
420
|
+
background: transparent;
|
|
421
|
+
color: var(--color-text);
|
|
422
|
+
cursor: pointer;
|
|
423
|
+
transition: background var(--duration-instant) var(--easing-default);
|
|
424
|
+
margin: 0 auto;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.datepicker-day:hover:not(:disabled) {
|
|
428
|
+
background: var(--datepicker-day-hover-bg);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.datepicker-day-selected {
|
|
432
|
+
background: var(--datepicker-day-selected-bg);
|
|
433
|
+
color: var(--datepicker-day-selected-text);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.datepicker-day-selected:hover:not(:disabled) {
|
|
437
|
+
background: var(--datepicker-day-selected-bg);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.datepicker-day-today {
|
|
441
|
+
border: var(--datepicker-day-today-border);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.datepicker-day-outside {
|
|
445
|
+
opacity: var(--datepicker-day-outside-opacity);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.datepicker-day:disabled {
|
|
449
|
+
opacity: var(--datepicker-day-disabled-opacity);
|
|
450
|
+
cursor: not-allowed;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/* ─── Hint / Error ─── */
|
|
454
|
+
.datepicker-help {
|
|
455
|
+
font-family: var(--input-help-font);
|
|
456
|
+
font-size: var(--input-help-size);
|
|
457
|
+
color: var(--input-help-color);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.datepicker-error-text {
|
|
461
|
+
font-family: var(--input-help-font);
|
|
462
|
+
font-size: var(--input-help-size);
|
|
463
|
+
color: var(--input-error-text);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
@media (prefers-reduced-motion: reduce) {
|
|
467
|
+
.datepicker-trigger,
|
|
468
|
+
.datepicker-nav-btn,
|
|
469
|
+
.datepicker-day {
|
|
470
|
+
transition: none;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
</style>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export default DatePicker;
|
|
2
|
+
type DatePicker = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* DatePicker
|
|
8
|
+
*
|
|
9
|
+
* Calendar dropdown for date selection. Values displayed in Berkeley Mono (data font).
|
|
10
|
+
* Locale-aware formatting via date-fns. Follows Input patterns for label, help, error.
|
|
11
|
+
* Consumes --datepicker-* and --input-* tokens from components.css.
|
|
12
|
+
*
|
|
13
|
+
* @example Basic
|
|
14
|
+
* <DatePicker label="START DATE" bind:value={startDate} />
|
|
15
|
+
*
|
|
16
|
+
* @example With constraints
|
|
17
|
+
* <DatePicker label="BIRTH DATE" min={new Date(1900, 0, 1)} max={new Date()} />
|
|
18
|
+
*
|
|
19
|
+
* @example Error
|
|
20
|
+
* <DatePicker label="DUE DATE" error="Date is required" />
|
|
21
|
+
*
|
|
22
|
+
* @example Locale
|
|
23
|
+
* <DatePicker label="DATA" locale={pt} />
|
|
24
|
+
*/
|
|
25
|
+
declare const DatePicker: import("svelte").Component<{
|
|
26
|
+
value?: any;
|
|
27
|
+
label?: any;
|
|
28
|
+
placeholder?: string;
|
|
29
|
+
help?: any;
|
|
30
|
+
error?: any;
|
|
31
|
+
size?: string;
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
readonly?: boolean;
|
|
34
|
+
min?: any;
|
|
35
|
+
max?: any;
|
|
36
|
+
displayFormat?: string;
|
|
37
|
+
locale?: typeof enUS;
|
|
38
|
+
onchange?: any;
|
|
39
|
+
id?: any;
|
|
40
|
+
class?: string;
|
|
41
|
+
} & Record<string, any>, {}, "value">;
|
|
42
|
+
type $$ComponentProps = {
|
|
43
|
+
value?: any;
|
|
44
|
+
label?: any;
|
|
45
|
+
placeholder?: string;
|
|
46
|
+
help?: any;
|
|
47
|
+
error?: any;
|
|
48
|
+
size?: string;
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
readonly?: boolean;
|
|
51
|
+
min?: any;
|
|
52
|
+
max?: any;
|
|
53
|
+
displayFormat?: string;
|
|
54
|
+
locale?: typeof enUS;
|
|
55
|
+
onchange?: any;
|
|
56
|
+
id?: any;
|
|
57
|
+
class?: string;
|
|
58
|
+
} & Record<string, any>;
|
|
59
|
+
import { enUS } from 'date-fns/locale';
|