@juspay/svelte-ui-components 2.28.2 → 2.28.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.
Files changed (34) hide show
  1. package/dist/Banner/Banner.svelte +34 -7
  2. package/dist/Banner/properties.d.ts +2 -0
  3. package/dist/Breadcrumb/Breadcrumb.svelte +58 -0
  4. package/dist/Breadcrumb/Breadcrumb.svelte.d.ts +4 -0
  5. package/dist/Breadcrumb/properties.d.ts +19 -0
  6. package/dist/Breadcrumb/properties.js +1 -0
  7. package/dist/Calendar/Calendar.svelte +10 -4
  8. package/dist/Calendar/properties.d.ts +2 -0
  9. package/dist/DateRangePicker/DateRangePicker.svelte +627 -0
  10. package/dist/DateRangePicker/DateRangePicker.svelte.d.ts +4 -0
  11. package/dist/DateRangePicker/properties.d.ts +74 -0
  12. package/dist/DateRangePicker/properties.js +1 -0
  13. package/dist/EmptyState/EmptyState.svelte +3 -1
  14. package/dist/EmptyState/properties.d.ts +1 -1
  15. package/dist/FileInput/FileInput.svelte +176 -0
  16. package/dist/FileInput/FileInput.svelte.d.ts +4 -0
  17. package/dist/FileInput/properties.d.ts +18 -0
  18. package/dist/FileInput/properties.js +1 -0
  19. package/dist/Modal/Modal.svelte +5 -4
  20. package/dist/Pagination/Pagination.svelte +56 -11
  21. package/dist/Pagination/properties.d.ts +15 -0
  22. package/dist/Pill/Pill.svelte +10 -0
  23. package/dist/Pill/properties.d.ts +7 -0
  24. package/dist/Select/Select.svelte +69 -29
  25. package/dist/Select/Select.svelte.d.ts +1 -1
  26. package/dist/Select/properties.d.ts +8 -1
  27. package/dist/Sheet/Sheet.svelte +16 -0
  28. package/dist/Sheet/properties.d.ts +4 -0
  29. package/dist/Table/Table.svelte +28 -6
  30. package/dist/Table/properties.d.ts +6 -0
  31. package/dist/Tabs/Tabs.svelte +52 -8
  32. package/dist/index.d.ts +6 -0
  33. package/dist/index.js +3 -0
  34. package/package.json +1 -1
@@ -0,0 +1,627 @@
1
+ <script lang="ts">
2
+ import type { DateRangePickerProperties, DateRangePreset } from './properties';
3
+ import { SvelteDate } from 'svelte/reactivity';
4
+ import Calendar from '../Calendar/Calendar.svelte';
5
+ import Button from '../Button/Button.svelte';
6
+ import chevronDownSvg from '../assets/chevron-down.svg?raw';
7
+
8
+ let {
9
+ rangeStart = $bindable(null),
10
+ rangeEnd = $bindable(null),
11
+ value = $bindable(null),
12
+ mode = 'range',
13
+ minDate = null,
14
+ maxDate = null,
15
+ disabledDates = [],
16
+ presets = null,
17
+ placeholder = 'Select date',
18
+ dualMonth,
19
+ timePicker,
20
+ compareStart = $bindable(null),
21
+ compareEnd = $bindable(null),
22
+ compareCalendar,
23
+ weekStartsOn = 0,
24
+ locale,
25
+ testId,
26
+ classes,
27
+ triggerSnippet,
28
+ triggerIcon,
29
+ onapply,
30
+ onapplysingle,
31
+ onapplycompare,
32
+ oncancel,
33
+ onopentoggle
34
+ }: DateRangePickerProperties = $props();
35
+
36
+ const isDualMonth: boolean = $derived(
37
+ typeof dualMonth === 'boolean' ? dualMonth : mode === 'range'
38
+ );
39
+
40
+ // Draft state — only committed on Apply
41
+ let draftStart: Date | null = $state(null);
42
+ let draftEnd: Date | null = $state(null);
43
+ let draftValue: Date | null = $state(null);
44
+ let draftCompareStart: Date | null = $state(null);
45
+ let draftCompareEnd: Date | null = $state(null);
46
+
47
+ let isOpen: boolean = $state(false);
48
+ let panelRef: HTMLDivElement | null = $state(null);
49
+ let triggerRef: HTMLDivElement | null = $state(null);
50
+
51
+ // Dual-month navigation: track the year+month of the left calendar
52
+ let leftYear: number = $state(new SvelteDate().getFullYear());
53
+ let leftMonth: number = $state(new SvelteDate().getMonth());
54
+
55
+ // A key counter — incrementing forces Calendar to re-mount with new initialMonth
56
+ let calendarKey: number = $state(0);
57
+
58
+ const now = new SvelteDate();
59
+
60
+ const leftInitialMonth: Date = $derived(new SvelteDate(leftYear, leftMonth, 1));
61
+ const rightInitialMonth: Date = $derived(new SvelteDate(leftYear, leftMonth + 1, 1));
62
+
63
+ // Right calendar header label (derived from leftInitialMonth)
64
+ const rightMonthLabel: string = $derived(
65
+ rightInitialMonth.toLocaleDateString(locale, { month: 'long', year: 'numeric' })
66
+ );
67
+ const leftMonthLabel: string = $derived(
68
+ leftInitialMonth.toLocaleDateString(locale, { month: 'long', year: 'numeric' })
69
+ );
70
+
71
+ function formatDate(d: Date): string {
72
+ return d.toLocaleDateString(locale, { month: 'short', day: 'numeric', year: 'numeric' });
73
+ }
74
+
75
+ const triggerLabel: string = $derived.by(() => {
76
+ if (mode === 'single') {
77
+ return value !== null ? formatDate(value) : placeholder;
78
+ }
79
+ if (rangeStart !== null && rangeEnd !== null) {
80
+ return `${formatDate(rangeStart)} – ${formatDate(rangeEnd)}`;
81
+ }
82
+ if (rangeStart !== null) {
83
+ return `${formatDate(rangeStart)} – ...`;
84
+ }
85
+ return placeholder;
86
+ });
87
+
88
+ function openPicker(): void {
89
+ // Seed draft from current committed values
90
+ draftStart = rangeStart !== null ? rangeStart : null;
91
+ draftEnd = rangeEnd !== null ? rangeEnd : null;
92
+ draftValue = value !== null ? value : null;
93
+ draftCompareStart = compareStart !== null ? compareStart : null;
94
+ draftCompareEnd = compareEnd !== null ? compareEnd : null;
95
+
96
+ // Navigate left calendar so it shows the committed start month (or today)
97
+ const anchor = rangeStart !== null ? rangeStart : value !== null ? value : now;
98
+ leftYear = anchor.getFullYear();
99
+ leftMonth = anchor.getMonth();
100
+ calendarKey++;
101
+
102
+ isOpen = true;
103
+ onopentoggle?.({ open: true });
104
+ }
105
+
106
+ function closePicker(): void {
107
+ isOpen = false;
108
+ onopentoggle?.({ open: false });
109
+ }
110
+
111
+ function navigateDualMonths(delta: number): void {
112
+ const next = new SvelteDate(leftYear, leftMonth + delta, 1);
113
+ leftYear = next.getFullYear();
114
+ leftMonth = next.getMonth();
115
+ calendarKey++;
116
+ }
117
+
118
+ function handleApply(): void {
119
+ if (mode === 'range') {
120
+ if (draftStart !== null && draftEnd !== null) {
121
+ rangeStart = draftStart;
122
+ rangeEnd = draftEnd;
123
+ onapply?.({ rangeStart: draftStart, rangeEnd: draftEnd });
124
+ }
125
+ if (
126
+ typeof compareCalendar === 'function' &&
127
+ draftCompareStart !== null &&
128
+ draftCompareEnd !== null
129
+ ) {
130
+ compareStart = draftCompareStart;
131
+ compareEnd = draftCompareEnd;
132
+ onapplycompare?.({ compareStart: draftCompareStart, compareEnd: draftCompareEnd });
133
+ }
134
+ } else {
135
+ if (draftValue !== null) {
136
+ value = draftValue;
137
+ onapplysingle?.({ date: draftValue });
138
+ }
139
+ }
140
+ closePicker();
141
+ }
142
+
143
+ function handleCancel(): void {
144
+ oncancel?.();
145
+ closePicker();
146
+ }
147
+
148
+ function handlePreset(preset: DateRangePreset): void {
149
+ const { start, end } = preset.getValue();
150
+ if (mode === 'range') {
151
+ draftStart = start;
152
+ draftEnd = end;
153
+ // Navigate left calendar to show the preset's start month
154
+ leftYear = start.getFullYear();
155
+ leftMonth = start.getMonth();
156
+ calendarKey++;
157
+ } else {
158
+ draftValue = start;
159
+ }
160
+ }
161
+
162
+ function handleRangeSelect(event: { rangeStart: Date; rangeEnd: Date }): void {
163
+ draftStart = event.rangeStart;
164
+ draftEnd = event.rangeEnd;
165
+ }
166
+
167
+ function handleSingleSelect(event: { date: Date }): void {
168
+ draftValue = event.date;
169
+ }
170
+
171
+ // Close on outside-click
172
+ function handleDocumentClick(event: MouseEvent): void {
173
+ if (!isOpen) {
174
+ return;
175
+ }
176
+ const target = event.target;
177
+ if (!(target instanceof Node)) {
178
+ return;
179
+ }
180
+ const clickedInsidePanel = panelRef !== null && panelRef.contains(target);
181
+ const clickedTrigger = triggerRef !== null && triggerRef.contains(target);
182
+ if (!clickedInsidePanel && !clickedTrigger) {
183
+ closePicker();
184
+ }
185
+ }
186
+
187
+ function handleDocumentKeyDown(event: KeyboardEvent): void {
188
+ if (event.key === 'Escape' && isOpen) {
189
+ handleCancel();
190
+ }
191
+ }
192
+
193
+ const canApply: boolean = $derived.by(() => {
194
+ if (mode === 'range') {
195
+ return draftStart !== null && draftEnd !== null;
196
+ }
197
+ return draftValue !== null;
198
+ });
199
+
200
+ function isPresetActive(preset: DateRangePreset): boolean {
201
+ if (mode === 'single') {
202
+ if (draftValue === null) {
203
+ return false;
204
+ }
205
+ const { start } = preset.getValue();
206
+ return isSameDay(draftValue, start);
207
+ }
208
+ if (draftStart === null || draftEnd === null) {
209
+ return false;
210
+ }
211
+ const { start, end } = preset.getValue();
212
+ return isSameDay(draftStart, start) && isSameDay(draftEnd, end);
213
+ }
214
+
215
+ function isSameDay(a: Date, b: Date): boolean {
216
+ return (
217
+ a.getFullYear() === b.getFullYear() &&
218
+ a.getMonth() === b.getMonth() &&
219
+ a.getDate() === b.getDate()
220
+ );
221
+ }
222
+ </script>
223
+
224
+ <svelte:document onclick={handleDocumentClick} onkeydown={handleDocumentKeyDown} />
225
+
226
+ <div class="drp-root {classes ?? ''}" data-pw={testId}>
227
+ <!-- Trigger wrapper — bind:this here so outside-click detection works -->
228
+ <div bind:this={triggerRef} class="drp-trigger-wrapper">
229
+ <Button
230
+ onclick={openPicker}
231
+ ariaLabel="Open date picker"
232
+ classes="drp-trigger {isOpen ? 'drp-trigger-open' : ''}"
233
+ >
234
+ {#if typeof triggerSnippet === 'function'}
235
+ {@render triggerSnippet(triggerLabel)}
236
+ {:else}
237
+ <span class="drp-trigger-label">{triggerLabel}</span>
238
+ <span class="drp-trigger-icon" aria-hidden="true">
239
+ {#if typeof triggerIcon === 'function'}
240
+ {@render triggerIcon()}
241
+ {:else}
242
+ <!-- eslint-disable svelte/no-at-html-tags -->
243
+ {@html chevronDownSvg}
244
+ {/if}
245
+ </span>
246
+ {/if}
247
+ </Button>
248
+ </div>
249
+
250
+ <!-- Dropdown panel -->
251
+ {#if isOpen}
252
+ <div
253
+ bind:this={panelRef}
254
+ class="drp-panel"
255
+ role="dialog"
256
+ aria-label="Date range picker"
257
+ aria-modal="true"
258
+ >
259
+ <div class="drp-panel-inner">
260
+ <!-- Preset sidebar -->
261
+ {#if presets !== null && presets.length > 0}
262
+ <div class="drp-sidebar" role="listbox" aria-label="Date presets">
263
+ {#each presets as preset (preset.label)}
264
+ <button
265
+ type="button"
266
+ class="drp-preset-item"
267
+ class:drp-preset-active={isPresetActive(preset)}
268
+ role="option"
269
+ aria-selected={isPresetActive(preset)}
270
+ onclick={() => handlePreset(preset)}
271
+ >
272
+ {preset.label}
273
+ </button>
274
+ {/each}
275
+ </div>
276
+ {/if}
277
+
278
+ <!-- Calendar area -->
279
+ <div class="drp-calendars">
280
+ {#if isDualMonth}
281
+ <!-- Dual-month layout with shared nav -->
282
+ <div class="drp-dual-header">
283
+ <button
284
+ type="button"
285
+ class="drp-nav-btn"
286
+ onclick={() => navigateDualMonths(-1)}
287
+ aria-label="Previous months"
288
+ >
289
+ <span class="drp-nav-chevron drp-nav-chevron-left" aria-hidden="true"></span>
290
+ </button>
291
+ <div class="drp-dual-month-labels">
292
+ <span class="drp-month-label">{leftMonthLabel}</span>
293
+ <span class="drp-month-label">{rightMonthLabel}</span>
294
+ </div>
295
+ <button
296
+ type="button"
297
+ class="drp-nav-btn"
298
+ onclick={() => navigateDualMonths(1)}
299
+ aria-label="Next months"
300
+ >
301
+ <span class="drp-nav-chevron drp-nav-chevron-right" aria-hidden="true"></span>
302
+ </button>
303
+ </div>
304
+
305
+ <div class="drp-months-row">
306
+ {#key calendarKey}
307
+ <!-- Left month -->
308
+ <Calendar
309
+ mode="range"
310
+ bind:rangeStart={draftStart}
311
+ bind:rangeEnd={draftEnd}
312
+ {weekStartsOn}
313
+ {locale}
314
+ {minDate}
315
+ {maxDate}
316
+ {disabledDates}
317
+ initialMonth={leftInitialMonth}
318
+ onrangeselect={handleRangeSelect}
319
+ classes="drp-calendar-embedded"
320
+ />
321
+ <!-- Right month -->
322
+ <Calendar
323
+ mode="range"
324
+ bind:rangeStart={draftStart}
325
+ bind:rangeEnd={draftEnd}
326
+ {weekStartsOn}
327
+ {locale}
328
+ {minDate}
329
+ {maxDate}
330
+ {disabledDates}
331
+ initialMonth={rightInitialMonth}
332
+ onrangeselect={handleRangeSelect}
333
+ classes="drp-calendar-embedded"
334
+ />
335
+ {/key}
336
+ </div>
337
+ {:else}
338
+ <!-- Single month -->
339
+ <Calendar
340
+ mode={mode === 'range' ? 'range' : 'single'}
341
+ bind:rangeStart={draftStart}
342
+ bind:rangeEnd={draftEnd}
343
+ bind:value={draftValue}
344
+ {weekStartsOn}
345
+ {locale}
346
+ {minDate}
347
+ {maxDate}
348
+ {disabledDates}
349
+ onrangeselect={handleRangeSelect}
350
+ onselect={handleSingleSelect}
351
+ classes="drp-calendar-embedded"
352
+ />
353
+ {/if}
354
+
355
+ <!-- Time picker slot: consumer controls all time UI -->
356
+ {#if typeof timePicker === 'function'}
357
+ <div class="drp-time-row">
358
+ {@render timePicker()}
359
+ </div>
360
+ {/if}
361
+
362
+ <!-- Compare calendar slot: consumer controls all compare UI -->
363
+ {#if typeof compareCalendar === 'function'}
364
+ <div class="drp-compare-section">
365
+ {@render compareCalendar()}
366
+ </div>
367
+ {/if}
368
+ </div>
369
+ </div>
370
+
371
+ <!-- Footer -->
372
+ <div class="drp-footer">
373
+ <Button onclick={handleCancel} ariaLabel="Cancel date selection" classes="drp-btn-cancel">
374
+ Cancel
375
+ </Button>
376
+ <Button
377
+ onclick={handleApply}
378
+ ariaLabel="Apply date selection"
379
+ classes="drp-btn-apply"
380
+ disabled={!canApply}
381
+ >
382
+ Apply
383
+ </Button>
384
+ </div>
385
+ </div>
386
+ {/if}
387
+ </div>
388
+
389
+ <style>
390
+ .drp-root {
391
+ position: relative;
392
+ display: inline-block;
393
+ }
394
+
395
+ /* ── Trigger wrapper ── */
396
+ .drp-trigger-wrapper {
397
+ display: inline-block;
398
+ }
399
+
400
+ /* Bridge drp-trigger CSS vars to Button CSS vars on the wrapper */
401
+ .drp-trigger-wrapper {
402
+ --button-color: var(--drp-trigger-background, inherit);
403
+ --button-border: var(--drp-trigger-border, 1px solid currentColor);
404
+ --button-border-radius: var(--drp-trigger-border-radius, 6px);
405
+ --button-text-color: var(--drp-trigger-color, inherit);
406
+ --button-padding: var(--drp-trigger-padding, 8px 12px);
407
+ --button-min-width: var(--drp-trigger-min-width, 200px);
408
+ --button-gap: var(--drp-trigger-gap, 8px);
409
+ --button-hover-border-color: var(--drp-trigger-hover-border-color, currentColor);
410
+ }
411
+
412
+ :global(.drp-trigger) {
413
+ display: inline-flex !important;
414
+ align-items: center;
415
+ gap: var(--drp-trigger-gap, 8px);
416
+ white-space: nowrap;
417
+ min-width: var(--drp-trigger-min-width, 200px);
418
+ font-family: inherit;
419
+ }
420
+
421
+ :global(.drp-trigger-open) {
422
+ border-color: var(--drp-trigger-open-border-color, #000000) !important;
423
+ box-shadow: var(--drp-trigger-open-shadow, 0 0 0 2px rgba(0, 0, 0, 0.1));
424
+ }
425
+
426
+ .drp-trigger-label {
427
+ flex: 1;
428
+ text-align: left;
429
+ }
430
+
431
+ .drp-trigger-icon {
432
+ display: inline-flex;
433
+ align-items: center;
434
+ color: var(--drp-trigger-icon-color, inherit);
435
+ flex-shrink: 0;
436
+ }
437
+
438
+ /* ── Panel ── */
439
+ .drp-panel {
440
+ position: absolute;
441
+ top: calc(100% + var(--drp-panel-offset, 6px));
442
+ left: 0;
443
+ z-index: var(--drp-panel-z-index, 1000);
444
+ background: var(--drp-panel-background, inherit);
445
+ border: var(--drp-panel-border, 1px solid #e0e0e0);
446
+ border-radius: var(--drp-panel-border-radius, 10px);
447
+ box-shadow: var(--drp-panel-shadow, 0 8px 24px rgba(0, 0, 0, 0.12));
448
+ display: flex;
449
+ flex-direction: column;
450
+ min-width: var(--drp-panel-min-width, 320px);
451
+ max-width: var(--drp-panel-max-width, 760px);
452
+ overflow: hidden;
453
+ }
454
+
455
+ .drp-panel-inner {
456
+ display: flex;
457
+ flex-direction: row;
458
+ }
459
+
460
+ /* ── Sidebar ── */
461
+ .drp-sidebar {
462
+ display: flex;
463
+ flex-direction: column;
464
+ padding: var(--drp-sidebar-padding, 12px 8px);
465
+ border-right: var(--drp-sidebar-border, 1px solid #e8e8e8);
466
+ min-width: var(--drp-sidebar-min-width, 140px);
467
+ gap: 2px;
468
+ overflow-y: auto;
469
+ max-height: var(--drp-sidebar-max-height, 400px);
470
+ }
471
+
472
+ .drp-preset-item {
473
+ display: block;
474
+ width: 100%;
475
+ text-align: left;
476
+ padding: var(--drp-preset-padding, 7px 12px);
477
+ background: none;
478
+ border: none;
479
+ border-radius: var(--drp-preset-border-radius, 5px);
480
+ color: var(--drp-preset-color, inherit);
481
+ cursor: pointer;
482
+ white-space: nowrap;
483
+ transition: background 0.12s ease;
484
+ font-family: inherit;
485
+ }
486
+
487
+ .drp-preset-item:hover {
488
+ background: var(--drp-preset-hover-background, #f5f5f5);
489
+ }
490
+
491
+ .drp-preset-active {
492
+ background: var(--drp-preset-active-background, currentColor);
493
+ color: var(--drp-preset-active-color, #ffffff);
494
+ }
495
+
496
+ .drp-preset-active:hover {
497
+ background: var(--drp-preset-active-hover-background, #333333);
498
+ }
499
+
500
+ /* ── Calendar area ── */
501
+ .drp-calendars {
502
+ display: flex;
503
+ flex-direction: column;
504
+ padding: var(--drp-calendars-padding, 16px);
505
+ gap: var(--drp-calendars-gap, 16px);
506
+ flex: 1;
507
+ }
508
+
509
+ /* Dual-month shared nav header */
510
+ .drp-dual-header {
511
+ display: flex;
512
+ align-items: center;
513
+ justify-content: space-between;
514
+ gap: 8px;
515
+ }
516
+
517
+ .drp-dual-month-labels {
518
+ display: flex;
519
+ flex: 1;
520
+ justify-content: space-around;
521
+ }
522
+
523
+ .drp-month-label {
524
+ color: var(--drp-month-label-color, inherit);
525
+ text-transform: capitalize;
526
+ }
527
+
528
+ .drp-nav-btn {
529
+ display: inline-flex;
530
+ align-items: center;
531
+ justify-content: center;
532
+ width: var(--drp-nav-btn-size, 32px);
533
+ height: var(--drp-nav-btn-size, 32px);
534
+ background: none;
535
+ border: none;
536
+ border-radius: var(--drp-nav-btn-border-radius, 4px);
537
+ cursor: pointer;
538
+ color: var(--drp-nav-btn-color, inherit);
539
+ transition: background 0.12s ease;
540
+ padding: 0;
541
+ }
542
+
543
+ .drp-nav-btn:hover {
544
+ background: var(--drp-nav-btn-hover-background, #f0f0f0);
545
+ }
546
+
547
+ /* CSS-only chevrons for the dual-nav */
548
+ .drp-nav-chevron {
549
+ display: inline-block;
550
+ width: 8px;
551
+ height: 8px;
552
+ border-right: var(--drp-nav-chevron-border, 2px solid currentColor);
553
+ border-top: var(--drp-nav-chevron-border, 2px solid currentColor);
554
+ }
555
+
556
+ .drp-nav-chevron-left {
557
+ transform: rotate(-135deg);
558
+ margin-left: 2px;
559
+ }
560
+
561
+ .drp-nav-chevron-right {
562
+ transform: rotate(45deg);
563
+ margin-right: 2px;
564
+ }
565
+
566
+ .drp-months-row {
567
+ display: flex;
568
+ gap: var(--drp-months-gap, 24px);
569
+ }
570
+
571
+ /* Embedded calendar: strip outer chrome so only the grid shows */
572
+ :global(.drp-calendar-embedded) {
573
+ --calendar-border: none;
574
+ --calendar-box-shadow: none;
575
+ --calendar-background: transparent;
576
+ --calendar-padding: 0;
577
+ /* Suppress Calendar's own header in dual-month context via CSS var */
578
+ --calendar-header-display: none;
579
+ }
580
+
581
+ /* ── Time picker slot ── */
582
+ .drp-time-row {
583
+ display: flex;
584
+ align-items: center;
585
+ gap: var(--drp-time-row-gap, 16px);
586
+ padding-top: var(--drp-time-row-padding-top, 8px);
587
+ border-top: var(--drp-time-divider, 1px solid #e8e8e8);
588
+ flex-wrap: wrap;
589
+ }
590
+
591
+ /* ── Compare calendar slot ── */
592
+ .drp-compare-section {
593
+ display: flex;
594
+ flex-direction: column;
595
+ gap: 8px;
596
+ padding-top: var(--drp-compare-padding-top, 12px);
597
+ border-top: var(--drp-compare-divider, 1px solid #e8e8e8);
598
+ }
599
+
600
+ /* ── Footer ── */
601
+ .drp-footer {
602
+ display: flex;
603
+ justify-content: flex-end;
604
+ align-items: center;
605
+ gap: var(--drp-footer-gap, 8px);
606
+ padding: var(--drp-footer-padding, 12px 16px);
607
+ border-top: var(--drp-footer-border, 1px solid #e8e8e8);
608
+ }
609
+
610
+ /* Cancel button variant via Button's CSS vars */
611
+ :global(.drp-btn-cancel) {
612
+ --button-color: transparent;
613
+ --button-border: 1px solid var(--drp-cancel-border-color, #d0d0d0);
614
+ --button-text-color: var(--drp-cancel-color, inherit);
615
+ --button-hover-color: var(--drp-cancel-hover-background, #f5f5f5);
616
+ }
617
+
618
+ /* Apply button variant */
619
+ :global(.drp-btn-apply) {
620
+ --button-color: var(--drp-apply-background, currentColor);
621
+ --button-border: none;
622
+ --button-text-color: var(--drp-apply-color, #ffffff);
623
+ --button-hover-color: var(--drp-apply-hover-background, #333333);
624
+ --button-disabled-color: var(--drp-apply-disabled-background, #cccccc);
625
+ --button-disabled-text-color: var(--drp-apply-disabled-color, #888888);
626
+ }
627
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { DateRangePickerProperties } from './properties';
2
+ declare const DateRangePicker: import("svelte").Component<DateRangePickerProperties, {}, "value" | "rangeStart" | "rangeEnd" | "compareStart" | "compareEnd">;
3
+ type DateRangePicker = ReturnType<typeof DateRangePicker>;
4
+ export default DateRangePicker;
@@ -0,0 +1,74 @@
1
+ import type { Snippet } from 'svelte';
2
+ export type DateRangePreset = {
3
+ label: string;
4
+ getValue: () => {
5
+ start: Date;
6
+ end: Date;
7
+ };
8
+ };
9
+ export type DateRangePickerMode = 'range' | 'single';
10
+ export type OptionalDateRangePickerProperties = {
11
+ /** Currently selected start of range (bindable). */
12
+ rangeStart?: Date | null;
13
+ /** Currently selected end of range (bindable). */
14
+ rangeEnd?: Date | null;
15
+ /** Selected date when mode='single' (bindable). */
16
+ value?: Date | null;
17
+ /** Whether the picker operates in range or single-date mode. Default: 'range'. */
18
+ mode?: DateRangePickerMode;
19
+ /** Earliest selectable date. */
20
+ minDate?: Date | null;
21
+ /** Latest selectable date. */
22
+ maxDate?: Date | null;
23
+ /** Specific dates to disable, or a predicate. */
24
+ disabledDates?: Date[] | ((date: Date) => boolean);
25
+ /** Preset options shown in the sidebar. Omit to hide the sidebar. */
26
+ presets?: DateRangePreset[] | null;
27
+ /** Placeholder shown when no range is selected. */
28
+ placeholder?: string;
29
+ /** Show two months side by side. Defaults to true for range mode, false for single. */
30
+ dualMonth?: boolean;
31
+ /** Snippet rendered in the time-picker slot. Consumer controls all time UI. */
32
+ timePicker?: Snippet;
33
+ /** Start of compare range (bindable). Used when compareCalendar snippet is provided. */
34
+ compareStart?: Date | null;
35
+ /** End of compare range (bindable). Used when compareCalendar snippet is provided. */
36
+ compareEnd?: Date | null;
37
+ /** Snippet rendered in the compare-calendar slot. Consumer controls all compare UI. */
38
+ compareCalendar?: Snippet;
39
+ /** Which day of the week starts the calendar. 0=Sunday, 1=Monday. */
40
+ weekStartsOn?: 0 | 1;
41
+ /** BCP-47 locale string for date formatting. */
42
+ locale?: string;
43
+ /** Test ID placed on the root wrapper element. */
44
+ testId?: string;
45
+ /** Extra CSS classes applied to the root wrapper. */
46
+ classes?: string;
47
+ /** Custom trigger content snippet. Receives the current label string as its argument. */
48
+ triggerSnippet?: Snippet<[string]>;
49
+ /** Custom icon snippet for the trigger button. */
50
+ triggerIcon?: Snippet;
51
+ };
52
+ export type DateRangePickerEventProperties = {
53
+ /** Fired when the user clicks Apply in range mode. */
54
+ onapply?: (event: {
55
+ rangeStart: Date;
56
+ rangeEnd: Date;
57
+ }) => void;
58
+ /** Fired when the user clicks Apply in single mode. */
59
+ onapplysingle?: (event: {
60
+ date: Date;
61
+ }) => void;
62
+ /** Fired when the compare range is applied. */
63
+ onapplycompare?: (event: {
64
+ compareStart: Date;
65
+ compareEnd: Date;
66
+ }) => void;
67
+ /** Fired when the user dismisses without applying. */
68
+ oncancel?: () => void;
69
+ /** Fired whenever the picker opens or closes. */
70
+ onopentoggle?: (event: {
71
+ open: boolean;
72
+ }) => void;
73
+ };
74
+ export type DateRangePickerProperties = OptionalDateRangePickerProperties & DateRangePickerEventProperties;
@@ -0,0 +1 @@
1
+ export {};