svseeds 0.6.0 → 0.8.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 (132) hide show
  1. package/README.md +2 -2
  2. package/_svseeds/Accordion.svelte +123 -82
  3. package/_svseeds/Accordion.svelte.d.ts +56 -27
  4. package/_svseeds/Button.svelte +116 -0
  5. package/_svseeds/Button.svelte.d.ts +55 -0
  6. package/_svseeds/Calendar.svelte +371 -0
  7. package/_svseeds/Calendar.svelte.d.ts +115 -0
  8. package/_svseeds/CheckField.svelte +232 -0
  9. package/_svseeds/CheckField.svelte.d.ts +80 -0
  10. package/_svseeds/ColorPicker.svelte +127 -0
  11. package/_svseeds/ColorPicker.svelte.d.ts +59 -0
  12. package/_svseeds/ComboBox.svelte +276 -0
  13. package/_svseeds/ComboBox.svelte.d.ts +72 -0
  14. package/_svseeds/ContextMenu.svelte +129 -0
  15. package/_svseeds/ContextMenu.svelte.d.ts +53 -0
  16. package/_svseeds/DarkToggle.svelte +127 -54
  17. package/_svseeds/DarkToggle.svelte.d.ts +38 -18
  18. package/_svseeds/DateField.svelte +275 -0
  19. package/_svseeds/DateField.svelte.d.ts +93 -0
  20. package/_svseeds/DateInput.svelte +350 -0
  21. package/_svseeds/DateInput.svelte.d.ts +111 -0
  22. package/_svseeds/Disclosure.svelte +243 -0
  23. package/_svseeds/Disclosure.svelte.d.ts +76 -0
  24. package/_svseeds/Drawer.svelte +178 -0
  25. package/_svseeds/Drawer.svelte.d.ts +61 -0
  26. package/_svseeds/FileField.svelte +280 -0
  27. package/_svseeds/FileField.svelte.d.ts +95 -0
  28. package/_svseeds/FileInput.svelte +271 -0
  29. package/_svseeds/FileInput.svelte.d.ts +103 -0
  30. package/_svseeds/HotkeyCapture.svelte +190 -0
  31. package/_svseeds/HotkeyCapture.svelte.d.ts +74 -0
  32. package/_svseeds/Image.svelte +211 -0
  33. package/_svseeds/Image.svelte.d.ts +83 -0
  34. package/_svseeds/MenuGroup.svelte +80 -0
  35. package/_svseeds/MenuGroup.svelte.d.ts +52 -0
  36. package/_svseeds/MenuItem.svelte +120 -0
  37. package/_svseeds/MenuItem.svelte.d.ts +63 -0
  38. package/_svseeds/MenuList.svelte +227 -0
  39. package/_svseeds/MenuList.svelte.d.ts +92 -0
  40. package/_svseeds/MenuSeparator.svelte +70 -0
  41. package/_svseeds/MenuSeparator.svelte.d.ts +44 -0
  42. package/_svseeds/Modal.svelte +123 -0
  43. package/_svseeds/Modal.svelte.d.ts +54 -0
  44. package/_svseeds/MonthPicker.svelte +172 -0
  45. package/_svseeds/MonthPicker.svelte.d.ts +66 -0
  46. package/_svseeds/NumberField.svelte +210 -0
  47. package/_svseeds/NumberField.svelte.d.ts +79 -0
  48. package/_svseeds/NumberInput.svelte +381 -0
  49. package/_svseeds/NumberInput.svelte.d.ts +85 -0
  50. package/_svseeds/Pagination.svelte +269 -0
  51. package/_svseeds/Pagination.svelte.d.ts +81 -0
  52. package/_svseeds/Popover.svelte +261 -0
  53. package/_svseeds/Popover.svelte.d.ts +80 -0
  54. package/_svseeds/ProgressTracker.svelte +124 -0
  55. package/_svseeds/{_ProgressTracker.svelte.d.ts → ProgressTracker.svelte.d.ts} +23 -12
  56. package/_svseeds/SelectField.svelte +210 -0
  57. package/_svseeds/{_SelectField.svelte.d.ts → SelectField.svelte.d.ts} +31 -20
  58. package/_svseeds/Slider.svelte +139 -0
  59. package/_svseeds/Slider.svelte.d.ts +75 -0
  60. package/_svseeds/Sortable.svelte +836 -0
  61. package/_svseeds/Sortable.svelte.d.ts +169 -0
  62. package/_svseeds/SortableGroup.svelte +90 -0
  63. package/_svseeds/SortableGroup.svelte.d.ts +55 -0
  64. package/_svseeds/Splitter.svelte +194 -0
  65. package/_svseeds/Splitter.svelte.d.ts +71 -0
  66. package/_svseeds/Tabs.svelte +233 -0
  67. package/_svseeds/Tabs.svelte.d.ts +75 -0
  68. package/_svseeds/TagsInput.svelte +250 -0
  69. package/_svseeds/TagsInput.svelte.d.ts +103 -0
  70. package/_svseeds/TagsInputField.svelte +120 -89
  71. package/_svseeds/TagsInputField.svelte.d.ts +31 -35
  72. package/_svseeds/TextField.svelte +235 -0
  73. package/_svseeds/TextField.svelte.d.ts +93 -0
  74. package/_svseeds/Toast.svelte +322 -0
  75. package/_svseeds/Toast.svelte.d.ts +109 -0
  76. package/_svseeds/Toggle.svelte +131 -0
  77. package/_svseeds/Toggle.svelte.d.ts +57 -0
  78. package/_svseeds/ToggleGroup.svelte +229 -0
  79. package/_svseeds/ToggleGroup.svelte.d.ts +79 -0
  80. package/_svseeds/ToggleGroupField.svelte +150 -78
  81. package/_svseeds/ToggleGroupField.svelte.d.ts +57 -35
  82. package/_svseeds/Tooltip.svelte +347 -0
  83. package/_svseeds/Tooltip.svelte.d.ts +74 -0
  84. package/_svseeds/WheelPicker.svelte +334 -0
  85. package/_svseeds/WheelPicker.svelte.d.ts +84 -0
  86. package/_svseeds/ZSortableA11y.svelte +1082 -0
  87. package/_svseeds/ZSortableA11y.svelte.d.ts +182 -0
  88. package/_svseeds/_core.d.ts +275 -0
  89. package/_svseeds/_core.js +359 -0
  90. package/index.d.ts +44 -25
  91. package/index.js +41 -22
  92. package/package.json +4 -4
  93. package/_svseeds/_Button.svelte +0 -92
  94. package/_svseeds/_Button.svelte.d.ts +0 -49
  95. package/_svseeds/_CheckField.svelte +0 -182
  96. package/_svseeds/_CheckField.svelte.d.ts +0 -71
  97. package/_svseeds/_ColorPicker.svelte +0 -114
  98. package/_svseeds/_ColorPicker.svelte.d.ts +0 -17
  99. package/_svseeds/_ComboBox.svelte +0 -163
  100. package/_svseeds/_ComboBox.svelte.d.ts +0 -52
  101. package/_svseeds/_ContextMenu.svelte +0 -82
  102. package/_svseeds/_ContextMenu.svelte.d.ts +0 -37
  103. package/_svseeds/_Disclosure.svelte +0 -152
  104. package/_svseeds/_Disclosure.svelte.d.ts +0 -48
  105. package/_svseeds/_Drawer.svelte +0 -136
  106. package/_svseeds/_Drawer.svelte.d.ts +0 -48
  107. package/_svseeds/_HotkeyCapture.svelte +0 -113
  108. package/_svseeds/_HotkeyCapture.svelte.d.ts +0 -34
  109. package/_svseeds/_Modal.svelte +0 -107
  110. package/_svseeds/_Modal.svelte.d.ts +0 -44
  111. package/_svseeds/_ProgressTracker.svelte +0 -101
  112. package/_svseeds/_SelectField.svelte +0 -190
  113. package/_svseeds/_Slider.svelte +0 -104
  114. package/_svseeds/_Slider.svelte.d.ts +0 -62
  115. package/_svseeds/_Sortable.svelte +0 -795
  116. package/_svseeds/_Sortable.svelte.d.ts +0 -111
  117. package/_svseeds/_Tabs.svelte +0 -118
  118. package/_svseeds/_Tabs.svelte.d.ts +0 -42
  119. package/_svseeds/_TagsInput.svelte +0 -155
  120. package/_svseeds/_TagsInput.svelte.d.ts +0 -81
  121. package/_svseeds/_TextField.svelte +0 -206
  122. package/_svseeds/_TextField.svelte.d.ts +0 -81
  123. package/_svseeds/_Toast.svelte +0 -258
  124. package/_svseeds/_Toast.svelte.d.ts +0 -14
  125. package/_svseeds/_Toggle.svelte +0 -112
  126. package/_svseeds/_Toggle.svelte.d.ts +0 -51
  127. package/_svseeds/_ToggleGroup.svelte +0 -102
  128. package/_svseeds/_ToggleGroup.svelte.d.ts +0 -49
  129. package/_svseeds/_Tooltip.svelte +0 -312
  130. package/_svseeds/_Tooltip.svelte.d.ts +0 -28
  131. package/_svseeds/core.d.ts +0 -229
  132. package/_svseeds/core.js +0 -1
@@ -0,0 +1,371 @@
1
+ <!--
2
+ @component
3
+ ### Usage
4
+ Use standalone.
5
+ ```svelte
6
+ <Calendar {...props} />
7
+ ```
8
+ ### Types
9
+ default value: *`(value)`*
10
+ ```ts
11
+ interface CalendarProps {
12
+ value?: Temporal.PlainDate; // bindable; selected date
13
+ display?: Temporal.PlainYearMonth; // bindable; shown month
14
+ picking?: boolean; // bindable (false)
15
+ min?: Temporal.PlainDate;
16
+ max?: Temporal.PlainDate;
17
+ isDisabled?: (d: Temporal.PlainDate) => boolean;
18
+ outsideDays?: boolean; // (false)
19
+ fixedWeeks?: boolean; // (false)
20
+ firstDayOfWeek?: number; // (0=Sun)
21
+ locale?: string;
22
+ label?: Snippet<[Temporal.PlainYearMonth, string, boolean]>;
23
+ left?: Snippet<[string]>;
24
+ right?: Snippet<[string]>;
25
+ weekday?: Snippet<[number, string]>;
26
+ day?: Snippet<[DayCtx]>;
27
+ bottom?: Snippet<[string, () => void]>;
28
+ monthPicker?: Omit<MonthPickerProps, "value" | "min" | "max" | "variant">;
29
+ transition?: TransitionProp;
30
+ styling?: SVSClass;
31
+ variant?: SVSVariant; // (VARIANT.NEUTRAL)
32
+ }
33
+ type DayCtx = {
34
+ date: Temporal.PlainDate;
35
+ variant: string;
36
+ weekday: number;
37
+ today: boolean;
38
+ selected: boolean;
39
+ outside: boolean;
40
+ disabled: boolean;
41
+ };
42
+ type TransitionProp = {
43
+ fn?: (node: HTMLElement, params: any, options: { direction: "in" | "out" | "both" }) => import("svelte/transition").TransitionConfig;
44
+ params?: unknown;
45
+ };
46
+ ```
47
+ ### Anatomy
48
+ ```svelte
49
+ <div class="whole" role="group">
50
+ <div class="top">
51
+ <button class="left" />
52
+ <button class="label" />
53
+ <button class="right" />
54
+ </div>
55
+ <div class="middle">
56
+ <div class="main" role="grid">
57
+ <div class="aux" role="row">weekday headers</div>
58
+ day cells
59
+ </div>
60
+ MonthPicker while picking
61
+ </div>
62
+ <div class="bottom" conditional>{bottom}</div>
63
+ </div>
64
+ ```
65
+ ### Behavior
66
+ - Prev/next page `display`; the label toggles an embedded `_MonthPicker`.
67
+ - Enabled day clicks and Enter/Space select a single `Temporal.PlainDate`.
68
+ - Day cells expose `data-today`, `data-selected`, `data-outside`, `data-disabled`, and `data-weekday`.
69
+ - Arrow, Home/End, PageUp/PageDown, and Shift+PageUp/PageDown update roving focus.
70
+ -->
71
+ <script module lang="ts">
72
+ export interface CalendarProps {
73
+ value?: Temporal.PlainDate;
74
+ display?: Temporal.PlainYearMonth;
75
+ picking?: boolean;
76
+ min?: Temporal.PlainDate;
77
+ max?: Temporal.PlainDate;
78
+ isDisabled?: (d: Temporal.PlainDate) => boolean;
79
+ outsideDays?: boolean;
80
+ fixedWeeks?: boolean;
81
+ firstDayOfWeek?: number;
82
+ locale?: string;
83
+ label?: Snippet<[Temporal.PlainYearMonth, string, boolean]>;
84
+ left?: Snippet<[string]>;
85
+ right?: Snippet<[string]>;
86
+ weekday?: Snippet<[number, string]>;
87
+ day?: Snippet<[DayCtx]>;
88
+ bottom?: Snippet<[string, () => void]>;
89
+ monthPicker?: Omit<MonthPickerProps, "value" | "min" | "max" | "variant">;
90
+ transition?: TransitionProp;
91
+ styling?: SVSClass;
92
+ variant?: SVSVariant;
93
+ }
94
+ export type DayCtx = {
95
+ date: Temporal.PlainDate;
96
+ variant: string;
97
+ weekday: number;
98
+ today: boolean;
99
+ selected: boolean;
100
+ outside: boolean;
101
+ disabled: boolean;
102
+ };
103
+ export type TransitionProp = {
104
+ fn?: (node: HTMLElement, params: any, options: { direction: "in" | "out" | "both" }) => import("svelte/transition").TransitionConfig;
105
+ params?: unknown;
106
+ };
107
+ export type CalendarReqdProps = never;
108
+ export type CalendarBindProps = "value" | "display" | "picking";
109
+
110
+ export const _CALENDAR_PRESET = "svs-calendar";
111
+
112
+ import { tick, untrack } from "svelte";
113
+ import { VARIANT, PARTS, _fnClass, shouldReduceMotion } from "./_core";
114
+ import MonthPicker from "./MonthPicker.svelte";
115
+ import type { Snippet } from "svelte";
116
+ import type { KeyboardEventHandler, MouseEventHandler } from "svelte/elements";
117
+ import type { SVSClass, SVSVariant } from "./_core";
118
+ import type { MonthPickerProps } from "./MonthPicker.svelte";
119
+ </script>
120
+
121
+ <script lang="ts">
122
+ // prettier-ignore
123
+ let { value = $bindable(), display = $bindable(), picking = $bindable(false), min, max, isDisabled, outsideDays = false, fixedWeeks = false, firstDayOfWeek = 0, locale, label, left, right, weekday, day, bottom, monthPicker, transition, styling, variant = VARIANT.NEUTRAL }: CalendarProps = $props();
124
+
125
+ // *** Initialize *** //
126
+ const cls = $derived(_fnClass(_CALENDAR_PRESET, styling));
127
+ const uid = $props.id();
128
+ const idCaption = `${uid}-caption`;
129
+ // svelte-ignore state_referenced_locally
130
+ if (display === undefined) display = (value ?? Temporal.Now.plainDateISO()).toPlainYearMonth();
131
+ const today = $derived(Temporal.Now.plainDateISO());
132
+
133
+ // *** States *** //
134
+ const initialDisplay = display as Temporal.PlainYearMonth;
135
+ let focused = $state(value && sameMonth(value, initialDisplay) ? value : firstOf(initialDisplay));
136
+ let cells = $state<Record<string, HTMLElement>>({});
137
+ const firstWeekday = $derived(normWeekday(firstDayOfWeek));
138
+ const monthStart = $derived(firstOf(currentDisplay()));
139
+ const captionText = $derived(monthStart.toLocaleString(locale, { year: "numeric", month: "long" }));
140
+ const appLabel = $derived(`Calendar, ${captionText}`);
141
+ const weekdayLabels = $derived.by(() => {
142
+ const short = new Intl.DateTimeFormat(locale, { weekday: "narrow" });
143
+ const long = new Intl.DateTimeFormat(locale, { weekday: "long" });
144
+ return Array.from({ length: 7 }, (_, i) => {
145
+ const weekday = (firstWeekday + i) % 7;
146
+ const d = dateForWeekday(weekday);
147
+ return { weekday, text: short.format(d), full: long.format(d) };
148
+ });
149
+ });
150
+ const weeks = $derived.by(() => {
151
+ const first = monthStart;
152
+ const lead = (weekdayOf(first) - firstWeekday + 7) % 7;
153
+ const rows = fixedWeeks ? 6 : Math.ceil((lead + first.daysInMonth) / 7);
154
+ const start = first.subtract({ days: lead });
155
+ return Array.from({ length: rows }, (_, r) => Array.from({ length: 7 }, (_, c) => start.add({ days: r * 7 + c })));
156
+ });
157
+ const cellKeys = $derived.by(() => {
158
+ const shown = currentDisplay();
159
+ const keys = new Set<string>();
160
+ for (const week of weeks) {
161
+ for (const cell of week) {
162
+ if (outsideDays || sameMonth(cell, shown)) keys.add(cell.toString());
163
+ }
164
+ }
165
+ return keys;
166
+ });
167
+ const reduced = $derived(shouldReduceMotion());
168
+ const tfn = $derived(!reduced && transition?.fn ? transition.fn : noop);
169
+ const tparams = $derived(transition?.params as any);
170
+
171
+ // *** Reactive Handlers *** //
172
+ $effect.pre(() => {
173
+ display;
174
+ value;
175
+ untrack(() => syncFocus());
176
+ });
177
+ $effect.pre(() => {
178
+ cellKeys;
179
+ untrack(() => trimCells(cellKeys));
180
+ });
181
+
182
+ function syncFocus() {
183
+ const shown = currentDisplay();
184
+ if (sameMonth(focused, shown)) return;
185
+ focused = value && sameMonth(value, shown) ? value : firstOf(shown);
186
+ }
187
+ function currentDisplay(): Temporal.PlainYearMonth {
188
+ return display ?? initialDisplay;
189
+ }
190
+ function noop() {
191
+ return {};
192
+ }
193
+ function firstOf(ym: Temporal.PlainYearMonth): Temporal.PlainDate {
194
+ return Temporal.PlainDate.from({ year: ym.year, month: ym.month, day: 1 });
195
+ }
196
+ function normWeekday(n: number): number {
197
+ return ((Math.trunc(n) % 7) + 7) % 7;
198
+ }
199
+ function weekdayOf(d: Temporal.PlainDate): number {
200
+ return d.dayOfWeek % 7;
201
+ }
202
+ function sameMonth(d: Temporal.PlainDate, ym: Temporal.PlainYearMonth): boolean {
203
+ return d.year === ym.year && d.month === ym.month;
204
+ }
205
+ function dateForWeekday(weekday: number): Date {
206
+ return new Date(Date.UTC(2023, 0, 1 + weekday));
207
+ }
208
+ function inRange(d: Temporal.PlainDate): boolean {
209
+ if (min && Temporal.PlainDate.compare(d, min) < 0) return false;
210
+ if (max && Temporal.PlainDate.compare(d, max) > 0) return false;
211
+ return true;
212
+ }
213
+ function disabled(d: Temporal.PlainDate): boolean {
214
+ return !inRange(d) || !!isDisabled?.(d);
215
+ }
216
+ function selected(d: Temporal.PlainDate): boolean {
217
+ return !!value?.equals(d);
218
+ }
219
+ function variantOf(d: Temporal.PlainDate): string {
220
+ if (disabled(d)) return VARIANT.INACTIVE;
221
+ if (selected(d)) return VARIANT.ACTIVE;
222
+ return VARIANT.NEUTRAL;
223
+ }
224
+ function ctx(d: Temporal.PlainDate): DayCtx {
225
+ return {
226
+ date: d,
227
+ variant: variantOf(d),
228
+ weekday: weekdayOf(d),
229
+ today: today.equals(d),
230
+ selected: selected(d),
231
+ outside: !sameMonth(d, currentDisplay()),
232
+ disabled: disabled(d),
233
+ };
234
+ }
235
+ function labelOf(d: Temporal.PlainDate): string {
236
+ return d.toLocaleString(locale, { dateStyle: "long" });
237
+ }
238
+ function displayOf(d: Temporal.PlainDate) {
239
+ display = d.toPlainYearMonth();
240
+ }
241
+ function prevMonth() {
242
+ display = currentDisplay().subtract({ months: 1 });
243
+ }
244
+ function nextMonth() {
245
+ display = currentDisplay().add({ months: 1 });
246
+ }
247
+ function select(d: Temporal.PlainDate) {
248
+ if (disabled(d)) return;
249
+ value = d;
250
+ focused = d;
251
+ if (!sameMonth(d, currentDisplay())) displayOf(d);
252
+ }
253
+ function setToday() {
254
+ displayOf(today);
255
+ select(today);
256
+ }
257
+ function move(d: Temporal.PlainDate) {
258
+ focused = d;
259
+ if (!sameMonth(d, currentDisplay())) displayOf(d);
260
+ tick().then(() => focusDate(d));
261
+ }
262
+ function focusDate(d: Temporal.PlainDate) {
263
+ cells[d.toString()]?.focus();
264
+ }
265
+ function trimCells(keys: Set<string>) {
266
+ for (const key of Object.keys(cells)) {
267
+ if (!keys.has(key)) delete cells[key];
268
+ }
269
+ }
270
+ function weekEdge(toEnd: boolean): Temporal.PlainDate {
271
+ const offset = (weekdayOf(focused) - firstWeekday + 7) % 7;
272
+ return focused.add({ days: toEnd ? 6 - offset : -offset });
273
+ }
274
+
275
+ // *** Event Handlers *** //
276
+ const hprev: MouseEventHandler<HTMLButtonElement> = () => prevMonth();
277
+ const hnext: MouseEventHandler<HTMLButtonElement> = () => nextMonth();
278
+ const hlabel: MouseEventHandler<HTMLButtonElement> = () => (picking = !picking);
279
+ const hkeydown: KeyboardEventHandler<HTMLDivElement> = (ev) => {
280
+ let next: Temporal.PlainDate | undefined;
281
+ if (ev.key === "ArrowLeft") next = focused.subtract({ days: 1 });
282
+ else if (ev.key === "ArrowRight") next = focused.add({ days: 1 });
283
+ else if (ev.key === "ArrowUp") next = focused.subtract({ days: 7 });
284
+ else if (ev.key === "ArrowDown") next = focused.add({ days: 7 });
285
+ else if (ev.key === "Home") next = weekEdge(false);
286
+ else if (ev.key === "End") next = weekEdge(true);
287
+ else if (ev.key === "PageUp") next = focused.subtract(ev.shiftKey ? { years: 1 } : { months: 1 });
288
+ else if (ev.key === "PageDown") next = focused.add(ev.shiftKey ? { years: 1 } : { months: 1 });
289
+ else if (ev.key === "Enter" || ev.key === " ") select(focused);
290
+ else return;
291
+ ev.preventDefault();
292
+ if (next) move(next);
293
+ };
294
+ </script>
295
+
296
+ <!---------------------------------------->
297
+
298
+ <div class={cls(PARTS.WHOLE, variant)} role="group" aria-label={appLabel} data-svs-calendar={uid}>
299
+ <div class={cls(PARTS.TOP, variant)}>
300
+ <button class={cls(PARTS.LEFT, variant)} type="button" onclick={hprev}
301
+ >{#if left}{@render left(variant)}{:else}Previous{/if}</button
302
+ >
303
+ <button id={idCaption} class={cls(PARTS.LABEL, variant)} type="button" aria-expanded={picking} onclick={hlabel}>
304
+ {#if label}{@render label(currentDisplay(), variant, picking)}{:else}{captionText}{/if}
305
+ </button>
306
+ <button class={cls(PARTS.RIGHT, variant)} type="button" onclick={hnext}
307
+ >{#if right}{@render right(variant)}{:else}Next{/if}</button
308
+ >
309
+ </div>
310
+
311
+ {#if picking}
312
+ <div class={cls(PARTS.MIDDLE, variant)} transition:tfn|local={tparams}>
313
+ <MonthPicker
314
+ {...monthPicker}
315
+ bind:value={() => currentDisplay(), (v) => (display = v)}
316
+ min={min?.toPlainYearMonth()}
317
+ max={max?.toPlainYearMonth()}
318
+ {variant}
319
+ />
320
+ </div>
321
+ {:else}
322
+ <div class={cls(PARTS.MIDDLE, variant)} transition:tfn|local={tparams}>
323
+ <div class={cls(PARTS.MAIN, variant)} role="grid" tabindex="-1" aria-labelledby={idCaption} onkeydown={hkeydown}>
324
+ <div class={cls(PARTS.AUX, variant)} role="row">
325
+ {#each weekdayLabels as wl}
326
+ <span class={cls(PARTS.EXTRA, VARIANT.NEUTRAL)} role="columnheader" data-weekday={wl.weekday} aria-label={wl.full}>
327
+ {#if weekday}{@render weekday(wl.weekday, variant)}{:else}{wl.text}{/if}
328
+ </span>
329
+ {/each}
330
+ </div>
331
+ {#each weeks as week}
332
+ <div role="row">
333
+ {#each week as cell}
334
+ {@const outside = !sameMonth(cell, currentDisplay())}
335
+ {#if outside && !outsideDays}
336
+ <span class={cls(PARTS.EXTRA, VARIANT.NEUTRAL)} role="gridcell" aria-hidden="true"></span>
337
+ {:else}
338
+ {@const c = ctx(cell)}
339
+ <button
340
+ class={cls(PARTS.EXTRA, c.variant)}
341
+ type="button"
342
+ role="gridcell"
343
+ tabindex={cell.equals(focused) ? 0 : -1}
344
+ bind:this={cells[cell.toString()]}
345
+ aria-selected={c.selected}
346
+ aria-disabled={c.disabled || undefined}
347
+ aria-current={c.today ? "date" : undefined}
348
+ aria-label={labelOf(cell)}
349
+ data-date={cell.toString()}
350
+ data-today={c.today || undefined}
351
+ data-selected={c.selected || undefined}
352
+ data-outside={c.outside || undefined}
353
+ data-disabled={c.disabled || undefined}
354
+ data-weekday={c.weekday}
355
+ onfocus={() => (focused = cell)}
356
+ onclick={() => select(cell)}
357
+ >
358
+ {#if day}{@render day(c)}{:else}{cell.day}{/if}
359
+ </button>
360
+ {/if}
361
+ {/each}
362
+ </div>
363
+ {/each}
364
+ </div>
365
+ </div>
366
+ {/if}
367
+
368
+ {#if bottom}
369
+ <div class={cls(PARTS.BOTTOM, variant)}>{@render bottom(variant, setToday)}</div>
370
+ {/if}
371
+ </div>
@@ -0,0 +1,115 @@
1
+ export interface CalendarProps {
2
+ value?: Temporal.PlainDate;
3
+ display?: Temporal.PlainYearMonth;
4
+ picking?: boolean;
5
+ min?: Temporal.PlainDate;
6
+ max?: Temporal.PlainDate;
7
+ isDisabled?: (d: Temporal.PlainDate) => boolean;
8
+ outsideDays?: boolean;
9
+ fixedWeeks?: boolean;
10
+ firstDayOfWeek?: number;
11
+ locale?: string;
12
+ label?: Snippet<[Temporal.PlainYearMonth, string, boolean]>;
13
+ left?: Snippet<[string]>;
14
+ right?: Snippet<[string]>;
15
+ weekday?: Snippet<[number, string]>;
16
+ day?: Snippet<[DayCtx]>;
17
+ bottom?: Snippet<[string, () => void]>;
18
+ monthPicker?: Omit<MonthPickerProps, "value" | "min" | "max" | "variant">;
19
+ transition?: TransitionProp;
20
+ styling?: SVSClass;
21
+ variant?: SVSVariant;
22
+ }
23
+ export type DayCtx = {
24
+ date: Temporal.PlainDate;
25
+ variant: string;
26
+ weekday: number;
27
+ today: boolean;
28
+ selected: boolean;
29
+ outside: boolean;
30
+ disabled: boolean;
31
+ };
32
+ export type TransitionProp = {
33
+ fn?: (node: HTMLElement, params: any, options: {
34
+ direction: "in" | "out" | "both";
35
+ }) => import("svelte/transition").TransitionConfig;
36
+ params?: unknown;
37
+ };
38
+ export type CalendarReqdProps = never;
39
+ export type CalendarBindProps = "value" | "display" | "picking";
40
+ export declare const _CALENDAR_PRESET = "svs-calendar";
41
+ import type { Snippet } from "svelte";
42
+ import type { SVSClass, SVSVariant } from "./_core";
43
+ import type { MonthPickerProps } from "./MonthPicker.svelte";
44
+ /**
45
+ * ### Usage
46
+ * Use standalone.
47
+ * ```svelte
48
+ * <Calendar {...props} />
49
+ * ```
50
+ * ### Types
51
+ * default value: *`(value)`*
52
+ * ```ts
53
+ * interface CalendarProps {
54
+ * value?: Temporal.PlainDate; // bindable; selected date
55
+ * display?: Temporal.PlainYearMonth; // bindable; shown month
56
+ * picking?: boolean; // bindable (false)
57
+ * min?: Temporal.PlainDate;
58
+ * max?: Temporal.PlainDate;
59
+ * isDisabled?: (d: Temporal.PlainDate) => boolean;
60
+ * outsideDays?: boolean; // (false)
61
+ * fixedWeeks?: boolean; // (false)
62
+ * firstDayOfWeek?: number; // (0=Sun)
63
+ * locale?: string;
64
+ * label?: Snippet<[Temporal.PlainYearMonth, string, boolean]>;
65
+ * left?: Snippet<[string]>;
66
+ * right?: Snippet<[string]>;
67
+ * weekday?: Snippet<[number, string]>;
68
+ * day?: Snippet<[DayCtx]>;
69
+ * bottom?: Snippet<[string, () => void]>;
70
+ * monthPicker?: Omit<MonthPickerProps, "value" | "min" | "max" | "variant">;
71
+ * transition?: TransitionProp;
72
+ * styling?: SVSClass;
73
+ * variant?: SVSVariant; // (VARIANT.NEUTRAL)
74
+ * }
75
+ * type DayCtx = {
76
+ * date: Temporal.PlainDate;
77
+ * variant: string;
78
+ * weekday: number;
79
+ * today: boolean;
80
+ * selected: boolean;
81
+ * outside: boolean;
82
+ * disabled: boolean;
83
+ * };
84
+ * type TransitionProp = {
85
+ * fn?: (node: HTMLElement, params: any, options: { direction: "in" | "out" | "both" }) => import("svelte/transition").TransitionConfig;
86
+ * params?: unknown;
87
+ * };
88
+ * ```
89
+ * ### Anatomy
90
+ * ```svelte
91
+ * <div class="whole" role="group">
92
+ * <div class="top">
93
+ * <button class="left" />
94
+ * <button class="label" />
95
+ * <button class="right" />
96
+ * </div>
97
+ * <div class="middle">
98
+ * <div class="main" role="grid">
99
+ * <div class="aux" role="row">weekday headers</div>
100
+ * day cells
101
+ * </div>
102
+ * MonthPicker while picking
103
+ * </div>
104
+ * <div class="bottom" conditional>{bottom}</div>
105
+ * </div>
106
+ * ```
107
+ * ### Behavior
108
+ * - Prev/next page `display`; the label toggles an embedded `_MonthPicker`.
109
+ * - Enabled day clicks and Enter/Space select a single `Temporal.PlainDate`.
110
+ * - Day cells expose `data-today`, `data-selected`, `data-outside`, `data-disabled`, and `data-weekday`.
111
+ * - Arrow, Home/End, PageUp/PageDown, and Shift+PageUp/PageDown update roving focus.
112
+ */
113
+ declare const Calendar: import("svelte").Component<CalendarProps, {}, "display" | "value" | "picking">;
114
+ type Calendar = ReturnType<typeof Calendar>;
115
+ export default Calendar;