@juspay/svelte-ui-components 2.9.0 → 2.11.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 (189) hide show
  1. package/README.md +337 -77
  2. package/dist/Accordion/Accordion.svelte +4 -2
  3. package/dist/Accordion/Accordion.svelte.d.ts +2 -4
  4. package/dist/Accordion/properties.d.ts +6 -0
  5. package/dist/Accordion/properties.js +1 -0
  6. package/dist/Animations/ModalAnimation.svelte +11 -9
  7. package/dist/Avatar/Avatar.svelte +122 -0
  8. package/dist/Avatar/Avatar.svelte.d.ts +4 -0
  9. package/dist/Avatar/properties.d.ts +15 -0
  10. package/dist/Avatar/properties.js +1 -0
  11. package/dist/Badge/Badge.svelte +2 -2
  12. package/dist/Badge/properties.d.ts +1 -0
  13. package/dist/Banner/Banner.svelte +132 -48
  14. package/dist/Banner/Banner.svelte.d.ts +1 -1
  15. package/dist/Banner/properties.d.ts +8 -3
  16. package/dist/Book/Book.svelte +281 -0
  17. package/dist/Book/Book.svelte.d.ts +4 -0
  18. package/dist/Book/properties.d.ts +24 -0
  19. package/dist/Book/properties.js +1 -0
  20. package/dist/BrandLoader/BrandLoader.svelte +3 -3
  21. package/dist/BrandLoader/properties.d.ts +1 -0
  22. package/dist/Browser/Browser.svelte +193 -0
  23. package/dist/Browser/Browser.svelte.d.ts +3 -0
  24. package/dist/Browser/properties.d.ts +16 -0
  25. package/dist/Browser/properties.js +1 -0
  26. package/dist/Button/Button.svelte +20 -7
  27. package/dist/Button/properties.d.ts +7 -4
  28. package/dist/Calendar/Calendar.svelte +476 -0
  29. package/dist/Calendar/Calendar.svelte.d.ts +4 -0
  30. package/dist/Calendar/properties.d.ts +30 -0
  31. package/dist/Calendar/properties.js +1 -0
  32. package/dist/Carousel/Carousel.svelte +19 -16
  33. package/dist/Carousel/properties.d.ts +1 -0
  34. package/dist/CheckListItem/CheckListItem.svelte +31 -26
  35. package/dist/CheckListItem/properties.d.ts +4 -1
  36. package/dist/Checkbox/Checkbox.svelte +157 -0
  37. package/dist/Checkbox/Checkbox.svelte.d.ts +4 -0
  38. package/dist/Checkbox/properties.d.ts +17 -0
  39. package/dist/Checkbox/properties.js +1 -0
  40. package/dist/Choicebox/Choicebox.svelte +85 -0
  41. package/dist/Choicebox/Choicebox.svelte.d.ts +4 -0
  42. package/dist/Choicebox/properties.d.ts +14 -0
  43. package/dist/Choicebox/properties.js +1 -0
  44. package/dist/CommandMenu/CommandMenu.svelte +452 -0
  45. package/dist/CommandMenu/CommandMenu.svelte.d.ts +4 -0
  46. package/dist/CommandMenu/properties.d.ts +26 -0
  47. package/dist/CommandMenu/properties.js +1 -0
  48. package/dist/ContextMenu/ContextMenu.svelte +308 -0
  49. package/dist/ContextMenu/ContextMenu.svelte.d.ts +4 -0
  50. package/dist/ContextMenu/properties.d.ts +26 -0
  51. package/dist/ContextMenu/properties.js +1 -0
  52. package/dist/Gauge/Gauge.svelte +70 -0
  53. package/dist/Gauge/Gauge.svelte.d.ts +4 -0
  54. package/dist/Gauge/properties.d.ts +9 -0
  55. package/dist/Gauge/properties.js +1 -0
  56. package/dist/GridItem/GridItem.svelte +5 -4
  57. package/dist/GridItem/properties.d.ts +1 -0
  58. package/dist/Icon/Icon.svelte +3 -3
  59. package/dist/Icon/properties.d.ts +1 -0
  60. package/dist/IconStack/IconStack.svelte +3 -3
  61. package/dist/IconStack/properties.d.ts +1 -0
  62. package/dist/Img/Img.svelte +5 -3
  63. package/dist/Img/properties.d.ts +5 -1
  64. package/dist/Input/Input.svelte +12 -6
  65. package/dist/Input/properties.d.ts +1 -0
  66. package/dist/InputButton/InputButton.svelte +4 -3
  67. package/dist/InputButton/properties.d.ts +5 -6
  68. package/dist/KeyboardInput/KeyboardInput.svelte +93 -0
  69. package/dist/KeyboardInput/KeyboardInput.svelte.d.ts +4 -0
  70. package/dist/KeyboardInput/properties.d.ts +12 -0
  71. package/dist/KeyboardInput/properties.js +1 -0
  72. package/dist/ListItem/ListItem.svelte +31 -28
  73. package/dist/ListItem/properties.d.ts +1 -0
  74. package/dist/Loader/Loader.svelte +10 -6
  75. package/dist/Loader/Loader.svelte.d.ts +3 -25
  76. package/dist/Loader/properties.d.ts +3 -0
  77. package/dist/Loader/properties.js +1 -0
  78. package/dist/LoadingDots/LoadingDots.svelte +64 -0
  79. package/dist/LoadingDots/LoadingDots.svelte.d.ts +3 -0
  80. package/dist/LoadingDots/properties.d.ts +8 -0
  81. package/dist/LoadingDots/properties.js +1 -0
  82. package/dist/Menu/Menu.svelte +349 -0
  83. package/dist/Menu/Menu.svelte.d.ts +4 -0
  84. package/dist/Menu/properties.d.ts +24 -0
  85. package/dist/Menu/properties.js +1 -0
  86. package/dist/Modal/Modal.svelte +10 -9
  87. package/dist/Modal/properties.d.ts +1 -0
  88. package/dist/Pagination/Pagination.svelte +152 -0
  89. package/dist/Pagination/Pagination.svelte.d.ts +4 -0
  90. package/dist/Pagination/properties.d.ts +14 -0
  91. package/dist/Pagination/properties.js +1 -0
  92. package/dist/Phone/Phone.svelte +234 -0
  93. package/dist/Phone/Phone.svelte.d.ts +3 -0
  94. package/dist/Phone/properties.d.ts +11 -0
  95. package/dist/Phone/properties.js +1 -0
  96. package/dist/Pill/Pill.svelte +130 -0
  97. package/dist/Pill/Pill.svelte.d.ts +4 -0
  98. package/dist/Pill/properties.d.ts +16 -0
  99. package/dist/Pill/properties.js +1 -0
  100. package/dist/Progress/Progress.svelte +68 -0
  101. package/dist/Progress/Progress.svelte.d.ts +4 -0
  102. package/dist/Progress/properties.d.ts +10 -0
  103. package/dist/Progress/properties.js +1 -0
  104. package/dist/Radio/Radio.svelte +128 -0
  105. package/dist/Radio/Radio.svelte.d.ts +4 -0
  106. package/dist/Radio/properties.d.ts +15 -0
  107. package/dist/Radio/properties.js +1 -0
  108. package/dist/RelativeTime/RelativeTime.svelte +117 -0
  109. package/dist/RelativeTime/RelativeTime.svelte.d.ts +4 -0
  110. package/dist/RelativeTime/properties.d.ts +13 -0
  111. package/dist/RelativeTime/properties.js +1 -0
  112. package/dist/Scroller/Scroller.svelte +389 -0
  113. package/dist/Scroller/Scroller.svelte.d.ts +4 -0
  114. package/dist/Scroller/properties.d.ts +30 -0
  115. package/dist/Scroller/properties.js +1 -0
  116. package/dist/Select/Select.svelte +382 -344
  117. package/dist/Select/Select.svelte.d.ts +1 -1
  118. package/dist/Select/properties.d.ts +16 -26
  119. package/dist/Sheet/Sheet.svelte +264 -0
  120. package/dist/Sheet/Sheet.svelte.d.ts +4 -0
  121. package/dist/Sheet/properties.d.ts +19 -0
  122. package/dist/Sheet/properties.js +1 -0
  123. package/dist/Shimmer/Shimmer.svelte +44 -0
  124. package/dist/Shimmer/Shimmer.svelte.d.ts +4 -0
  125. package/dist/Shimmer/properties.d.ts +4 -0
  126. package/dist/Shimmer/properties.js +1 -0
  127. package/dist/Slider/Slider.svelte +144 -0
  128. package/dist/Slider/Slider.svelte.d.ts +4 -0
  129. package/dist/Slider/properties.d.ts +17 -0
  130. package/dist/Slider/properties.js +1 -0
  131. package/dist/Snippet/Snippet.svelte +123 -0
  132. package/dist/Snippet/Snippet.svelte.d.ts +4 -0
  133. package/dist/Snippet/properties.d.ts +15 -0
  134. package/dist/Snippet/properties.js +1 -0
  135. package/dist/SplitButton/SplitButton.svelte +135 -0
  136. package/dist/SplitButton/SplitButton.svelte.d.ts +4 -0
  137. package/dist/SplitButton/properties.d.ts +17 -0
  138. package/dist/SplitButton/properties.js +1 -0
  139. package/dist/Status/Status.svelte +5 -3
  140. package/dist/Status/properties.d.ts +1 -0
  141. package/dist/Stepper/Step.svelte +3 -3
  142. package/dist/Stepper/Stepper.svelte +3 -3
  143. package/dist/Stepper/properties.d.ts +2 -0
  144. package/dist/Table/Table.svelte +15 -8
  145. package/dist/Table/properties.d.ts +1 -0
  146. package/dist/Tabs/Tabs.svelte +240 -0
  147. package/dist/Tabs/Tabs.svelte.d.ts +4 -0
  148. package/dist/Tabs/properties.d.ts +16 -0
  149. package/dist/Tabs/properties.js +1 -0
  150. package/dist/ThemeSwitcher/ThemeSwitcher.svelte +249 -0
  151. package/dist/ThemeSwitcher/ThemeSwitcher.svelte.d.ts +4 -0
  152. package/dist/ThemeSwitcher/properties.d.ts +19 -0
  153. package/dist/ThemeSwitcher/properties.js +1 -0
  154. package/dist/Toast/Toast.svelte +25 -30
  155. package/dist/Toast/properties.d.ts +1 -0
  156. package/dist/Toggle/Toggle.svelte +2 -2
  157. package/dist/Toggle/properties.d.ts +1 -0
  158. package/dist/Toolbar/Toolbar.svelte +8 -7
  159. package/dist/Toolbar/properties.d.ts +1 -0
  160. package/dist/Tooltip/Tooltip.svelte +153 -0
  161. package/dist/Tooltip/Tooltip.svelte.d.ts +4 -0
  162. package/dist/Tooltip/properties.d.ts +13 -0
  163. package/dist/Tooltip/properties.js +1 -0
  164. package/dist/assets/battery.svg +5 -0
  165. package/dist/assets/checkmark.svg +3 -0
  166. package/dist/assets/chevron-down-sm.svg +3 -0
  167. package/dist/assets/chevron-down.svg +3 -0
  168. package/dist/assets/chevron-left-lg.svg +3 -0
  169. package/dist/assets/chevron-left.svg +3 -0
  170. package/dist/assets/chevron-right-lg.svg +3 -0
  171. package/dist/assets/chevron-right.svg +3 -0
  172. package/dist/assets/chevron-up.svg +3 -0
  173. package/dist/assets/close.svg +4 -0
  174. package/dist/assets/copy.svg +4 -0
  175. package/dist/assets/error-circle.svg +5 -0
  176. package/dist/assets/lock.svg +3 -0
  177. package/dist/assets/minus.svg +3 -0
  178. package/dist/assets/monitor.svg +5 -0
  179. package/dist/assets/moon.svg +3 -0
  180. package/dist/assets/palette.svg +7 -0
  181. package/dist/assets/search.svg +4 -0
  182. package/dist/assets/signal.svg +6 -0
  183. package/dist/assets/sun.svg +11 -0
  184. package/dist/assets/wifi.svg +3 -0
  185. package/dist/index.d.ts +55 -0
  186. package/dist/index.js +27 -0
  187. package/dist/utils.d.ts +2 -0
  188. package/dist/utils.js +18 -4
  189. package/package.json +26 -1
@@ -0,0 +1,476 @@
1
+ <script lang="ts">
2
+ import type { CalendarProperties } from './properties';
3
+ import { SvelteDate } from 'svelte/reactivity';
4
+ import { tick } from 'svelte';
5
+ import chevronLeftSvg from '../assets/chevron-left.svg?raw';
6
+ import chevronRightSvg from '../assets/chevron-right.svg?raw';
7
+ import Button from '../Button/Button.svelte';
8
+
9
+ let {
10
+ value = $bindable(null),
11
+ rangeStart = $bindable(null),
12
+ rangeEnd = $bindable(null),
13
+ mode = 'single',
14
+ minDate = null,
15
+ maxDate = null,
16
+ disabledDates = [],
17
+ weekStartsOn = 0,
18
+ locale,
19
+ testId,
20
+ previousMonthIcon,
21
+ nextMonthIcon,
22
+ onselect,
23
+ onrangeselect,
24
+ onmonthchange,
25
+ classes
26
+ }: CalendarProperties = $props();
27
+
28
+ const now = new SvelteDate();
29
+ let displayDate = new SvelteDate(now.getFullYear(), now.getMonth(), 1);
30
+ let focusedDay: number | null = $state(null);
31
+
32
+ let gridRef: HTMLElement | null = $state(null);
33
+
34
+ async function focusDayCell(): Promise<void> {
35
+ await tick();
36
+ if (focusedDay !== null && gridRef !== null) {
37
+ const btn = gridRef.querySelector(`[data-day="${focusedDay}"]`);
38
+ if (btn instanceof HTMLElement) {
39
+ btn.focus();
40
+ }
41
+ }
42
+ }
43
+
44
+ const dayNameFormatter = $derived(new Intl.DateTimeFormat(locale, { weekday: 'short' }));
45
+
46
+ const monthYearFormatter = $derived(
47
+ new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' })
48
+ );
49
+
50
+ let dayNames: string[] = $derived(
51
+ Array.from({ length: 7 }, (_, i) => {
52
+ const d = new SvelteDate(2024, 0, 7 + weekStartsOn + i);
53
+ return dayNameFormatter.format(d);
54
+ })
55
+ );
56
+
57
+ let headerLabel: string = $derived(monthYearFormatter.format(displayDate));
58
+
59
+ let calendarDays = $derived.by(() => {
60
+ const displayYear = displayDate.getFullYear();
61
+ const displayMonth = displayDate.getMonth();
62
+ const firstOfMonth = new SvelteDate(displayYear, displayMonth, 1);
63
+ const lastOfMonth = new SvelteDate(displayYear, displayMonth + 1, 0);
64
+
65
+ let startDayOfWeek = firstOfMonth.getDay() - weekStartsOn;
66
+ if (startDayOfWeek < 0) {
67
+ startDayOfWeek += 7;
68
+ }
69
+
70
+ const totalDaysInMonth = lastOfMonth.getDate();
71
+ const today = new SvelteDate();
72
+ today.setHours(0, 0, 0, 0);
73
+
74
+ const normStart = rangeStart !== null ? normalizeDate(rangeStart) : null;
75
+ const normEnd = rangeEnd !== null ? normalizeDate(rangeEnd) : null;
76
+
77
+ type DayInfo = {
78
+ date: Date;
79
+ day: number;
80
+ isCurrentMonth: boolean;
81
+ isToday: boolean;
82
+ isDisabled: boolean;
83
+ isSelected: boolean;
84
+ isRangeStart: boolean;
85
+ isRangeEnd: boolean;
86
+ isInRange: boolean;
87
+ };
88
+
89
+ function fillerDay(year: number, month: number, day: number): DayInfo {
90
+ const date = new SvelteDate(year, month, day);
91
+ date.setHours(0, 0, 0, 0);
92
+ return {
93
+ date,
94
+ day,
95
+ isCurrentMonth: false,
96
+ isToday: false,
97
+ isDisabled: true,
98
+ isSelected: false,
99
+ isRangeStart: false,
100
+ isRangeEnd: false,
101
+ isInRange: false
102
+ };
103
+ }
104
+
105
+ const days: DayInfo[] = [];
106
+
107
+ const prevMonthDays = new SvelteDate(displayYear, displayMonth, 0).getDate();
108
+ for (let i = startDayOfWeek - 1; i >= 0; i--) {
109
+ days.push(fillerDay(displayYear, displayMonth - 1, prevMonthDays - i));
110
+ }
111
+
112
+ for (let day = 1; day <= totalDaysInMonth; day++) {
113
+ const date = new SvelteDate(displayYear, displayMonth, day);
114
+ date.setHours(0, 0, 0, 0);
115
+ const time = date.getTime();
116
+
117
+ days.push({
118
+ date,
119
+ day,
120
+ isCurrentMonth: true,
121
+ isToday: time === today.getTime(),
122
+ isDisabled: isDateDisabled(date),
123
+ isSelected: mode === 'single' && value !== null && isSameDay(date, value),
124
+ isRangeStart: mode === 'range' && normStart !== null && isSameDay(date, normStart),
125
+ isRangeEnd: mode === 'range' && normEnd !== null && isSameDay(date, normEnd),
126
+ isInRange:
127
+ mode === 'range' &&
128
+ normStart !== null &&
129
+ normEnd !== null &&
130
+ time > normStart.getTime() &&
131
+ time < normEnd.getTime()
132
+ });
133
+ }
134
+
135
+ const remainder = days.length % 7;
136
+ if (remainder > 0) {
137
+ for (let i = 1; i <= 7 - remainder; i++) {
138
+ days.push(fillerDay(displayYear, displayMonth + 1, i));
139
+ }
140
+ }
141
+
142
+ return days;
143
+ });
144
+
145
+ function normalizeDate(d: Date): Date {
146
+ const n = new SvelteDate(d);
147
+ n.setHours(0, 0, 0, 0);
148
+ return n;
149
+ }
150
+
151
+ function isSameDay(a: Date, b: Date): boolean {
152
+ return (
153
+ a.getFullYear() === b.getFullYear() &&
154
+ a.getMonth() === b.getMonth() &&
155
+ a.getDate() === b.getDate()
156
+ );
157
+ }
158
+
159
+ function isDateDisabled(date: Date): boolean {
160
+ const time = date.getTime();
161
+
162
+ if (minDate !== null && time < normalizeDate(minDate).getTime()) {
163
+ return true;
164
+ }
165
+ if (maxDate !== null && time > normalizeDate(maxDate).getTime()) {
166
+ return true;
167
+ }
168
+ if (typeof disabledDates === 'function') {
169
+ return disabledDates(date);
170
+ }
171
+ if (Array.isArray(disabledDates)) {
172
+ return disabledDates.some((d) => isSameDay(d, date));
173
+ }
174
+
175
+ return false;
176
+ }
177
+
178
+ function navigateMonth(delta: number): void {
179
+ displayDate.setMonth(displayDate.getMonth() + delta);
180
+ focusedDay = null;
181
+ onmonthchange?.({ year: displayDate.getFullYear(), month: displayDate.getMonth() });
182
+ }
183
+
184
+ function selectDate(date: Date): void {
185
+ if (isDateDisabled(date)) {
186
+ return;
187
+ }
188
+
189
+ focusedDay = date.getDate();
190
+
191
+ if (mode === 'single') {
192
+ value = date;
193
+ onselect?.({ date });
194
+ } else {
195
+ if (rangeStart === null || rangeEnd !== null) {
196
+ rangeStart = date;
197
+ rangeEnd = null;
198
+ } else {
199
+ const start = rangeStart;
200
+ if (date.getTime() < normalizeDate(start).getTime()) {
201
+ rangeEnd = start;
202
+ rangeStart = date;
203
+ } else {
204
+ rangeEnd = date;
205
+ }
206
+ onrangeselect?.({ rangeStart, rangeEnd });
207
+ }
208
+ }
209
+ }
210
+
211
+ function daysInMonth(year: number, month: number): number {
212
+ return new SvelteDate(year, month + 1, 0).getDate();
213
+ }
214
+
215
+ function handleKeyDown(event: KeyboardEvent): void {
216
+ const year = displayDate.getFullYear();
217
+ const month = displayDate.getMonth();
218
+ const totalDays = daysInMonth(year, month);
219
+
220
+ if (focusedDay === null) {
221
+ if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key)) {
222
+ event.preventDefault();
223
+ focusedDay = 1;
224
+ focusDayCell();
225
+ return;
226
+ }
227
+ }
228
+
229
+ switch (event.key) {
230
+ case 'ArrowRight':
231
+ event.preventDefault();
232
+ if (focusedDay !== null && focusedDay < totalDays) {
233
+ focusedDay++;
234
+ } else if (focusedDay === totalDays) {
235
+ navigateMonth(1);
236
+ focusedDay = 1;
237
+ }
238
+ focusDayCell();
239
+ break;
240
+ case 'ArrowLeft':
241
+ event.preventDefault();
242
+ if (focusedDay !== null && focusedDay > 1) {
243
+ focusedDay--;
244
+ } else if (focusedDay === 1) {
245
+ navigateMonth(-1);
246
+ focusedDay = daysInMonth(displayDate.getFullYear(), displayDate.getMonth());
247
+ }
248
+ focusDayCell();
249
+ break;
250
+ case 'ArrowDown':
251
+ event.preventDefault();
252
+ if (focusedDay !== null) {
253
+ if (focusedDay + 7 <= totalDays) {
254
+ focusedDay += 7;
255
+ } else {
256
+ const overflow = focusedDay + 7 - totalDays;
257
+ navigateMonth(1);
258
+ focusedDay = overflow;
259
+ }
260
+ }
261
+ focusDayCell();
262
+ break;
263
+ case 'ArrowUp':
264
+ event.preventDefault();
265
+ if (focusedDay !== null) {
266
+ if (focusedDay - 7 >= 1) {
267
+ focusedDay -= 7;
268
+ } else {
269
+ const currentDay = focusedDay;
270
+ const prevTotal = daysInMonth(year, month - 1);
271
+ navigateMonth(-1);
272
+ focusedDay = prevTotal + (currentDay - 7);
273
+ }
274
+ }
275
+ focusDayCell();
276
+ break;
277
+ case 'Enter':
278
+ case ' ':
279
+ event.preventDefault();
280
+ if (focusedDay !== null) {
281
+ const date = new SvelteDate(year, month, focusedDay);
282
+ date.setHours(0, 0, 0, 0);
283
+ selectDate(date);
284
+ }
285
+ break;
286
+ }
287
+ }
288
+ </script>
289
+
290
+ <div class="calendar {classes ?? ''}" data-pw={testId} role="application" aria-label="Calendar">
291
+ <div class="header">
292
+ <div class="nav-button nav-prev">
293
+ <Button onclick={() => navigateMonth(-1)} ariaLabel="Previous month">
294
+ {#if typeof previousMonthIcon === 'function'}
295
+ {@render previousMonthIcon()}
296
+ {:else}
297
+ <!-- eslint-disable svelte/no-at-html-tags -->
298
+ {@html chevronLeftSvg}
299
+ {/if}
300
+ </Button>
301
+ </div>
302
+ <span class="header-label">{headerLabel}</span>
303
+ <div class="nav-button nav-next">
304
+ <Button onclick={() => navigateMonth(1)} ariaLabel="Next month">
305
+ {#if typeof nextMonthIcon === 'function'}
306
+ {@render nextMonthIcon()}
307
+ {:else}
308
+ <!-- eslint-disable svelte/no-at-html-tags -->
309
+ {@html chevronRightSvg}
310
+ {/if}
311
+ </Button>
312
+ </div>
313
+ </div>
314
+
315
+ <div class="day-names">
316
+ {#each dayNames as name (name)}
317
+ <div class="day-name">{name}</div>
318
+ {/each}
319
+ </div>
320
+
321
+ <div class="grid" bind:this={gridRef} tabindex="0" role="grid" onkeydown={handleKeyDown}>
322
+ {#each calendarDays as dayInfo (dayInfo.date.getTime())}
323
+ {#if dayInfo.isCurrentMonth}
324
+ <button
325
+ type="button"
326
+ class="cell"
327
+ class:today={dayInfo.isToday}
328
+ class:selected={dayInfo.isSelected}
329
+ class:range-start={dayInfo.isRangeStart}
330
+ class:range-end={dayInfo.isRangeEnd}
331
+ class:in-range={dayInfo.isInRange}
332
+ class:disabled={dayInfo.isDisabled}
333
+ data-day={dayInfo.day}
334
+ disabled={dayInfo.isDisabled}
335
+ tabindex={focusedDay === dayInfo.day ? 0 : -1}
336
+ aria-label={dayInfo.date.toLocaleDateString(locale)}
337
+ onclick={() => selectDate(dayInfo.date)}
338
+ >
339
+ {dayInfo.day}
340
+ </button>
341
+ {:else}
342
+ <span class="cell outside-month">{dayInfo.day}</span>
343
+ {/if}
344
+ {/each}
345
+ </div>
346
+ </div>
347
+
348
+ <style>
349
+ .calendar {
350
+ font-family: var(--calendar-font-family, inherit);
351
+ width: var(--calendar-width, 280px);
352
+ padding: var(--calendar-padding, 16px);
353
+ background-color: var(--calendar-background, #ffffff);
354
+ border: var(--calendar-border, 1px solid #e0e0e0);
355
+ border-radius: var(--calendar-border-radius, 8px);
356
+ box-shadow: var(--calendar-box-shadow, none);
357
+ box-sizing: border-box;
358
+ user-select: none;
359
+ }
360
+
361
+ .header {
362
+ display: flex;
363
+ align-items: center;
364
+ justify-content: space-between;
365
+ margin-bottom: var(--calendar-header-margin-bottom, 12px);
366
+ }
367
+
368
+ .header-label {
369
+ font-size: var(--calendar-header-font-size, 16px);
370
+ font-weight: var(--calendar-header-font-weight, 600);
371
+ color: var(--calendar-header-color, #000000);
372
+ text-transform: capitalize;
373
+ }
374
+
375
+ .nav-button {
376
+ display: flex;
377
+ align-items: center;
378
+ justify-content: center;
379
+
380
+ --button-width: var(--calendar-nav-button-size, 32px);
381
+ --button-height: var(--calendar-nav-button-size, 32px);
382
+ --button-border: none;
383
+ --button-color: transparent;
384
+ --button-border-radius: var(--calendar-nav-button-border-radius, 4px);
385
+ --button-text-color: var(--calendar-nav-button-color, #666666);
386
+ --button-padding: 0;
387
+ --button-hover-color: var(--calendar-nav-button-hover-background, #f0f0f0);
388
+ }
389
+
390
+ .day-names {
391
+ display: grid;
392
+ grid-template-columns: repeat(7, 1fr);
393
+ text-align: center;
394
+ }
395
+
396
+ .day-name {
397
+ font-size: var(--calendar-day-name-font-size, 12px);
398
+ font-weight: var(--calendar-day-name-font-weight, 600);
399
+ color: var(--calendar-day-name-color, #999999);
400
+ padding: var(--calendar-day-name-padding, 4px 0);
401
+ }
402
+
403
+ .grid {
404
+ display: grid;
405
+ grid-template-columns: repeat(7, 1fr);
406
+ justify-items: center;
407
+ row-gap: 2px;
408
+ }
409
+
410
+ .cell {
411
+ display: flex;
412
+ align-items: center;
413
+ justify-content: center;
414
+ width: var(--calendar-cell-size, 36px);
415
+ height: var(--calendar-cell-size, 36px);
416
+ font-family: inherit;
417
+ font-size: var(--calendar-cell-font-size, 14px);
418
+ border-radius: var(--calendar-cell-border-radius, 50%);
419
+ color: var(--calendar-cell-color, #000000);
420
+ border: none;
421
+ background: none;
422
+ cursor: pointer;
423
+ padding: 0;
424
+ outline: none;
425
+ }
426
+
427
+ .cell:hover:not(.disabled, .outside-month, .selected, .range-start, .range-end) {
428
+ background-color: var(--calendar-cell-hover-background, #f0f0f0);
429
+ }
430
+
431
+ .cell:focus-visible {
432
+ outline: 2px solid var(--calendar-focus-ring-color, #000000);
433
+ outline-offset: -2px;
434
+ }
435
+
436
+ .today {
437
+ border: var(--calendar-today-border, 1px solid #000000);
438
+ font-weight: var(--calendar-today-font-weight, 700);
439
+ }
440
+
441
+ .selected {
442
+ background-color: var(--calendar-selected-background, #000000);
443
+ color: var(--calendar-selected-color, #ffffff);
444
+ }
445
+
446
+ .range-start {
447
+ background-color: var(--calendar-range-start-background, #000000);
448
+ color: var(--calendar-range-start-color, #ffffff);
449
+ border-radius: 50% 0 0 50%;
450
+ }
451
+
452
+ .range-end {
453
+ background-color: var(--calendar-range-end-background, #000000);
454
+ color: var(--calendar-range-end-color, #ffffff);
455
+ border-radius: 0 50% 50% 0;
456
+ }
457
+
458
+ .range-start.range-end {
459
+ border-radius: var(--calendar-cell-border-radius, 50%);
460
+ }
461
+
462
+ .in-range {
463
+ background-color: var(--calendar-range-background, #e8e8e8);
464
+ border-radius: 0;
465
+ }
466
+
467
+ .disabled {
468
+ color: var(--calendar-disabled-color, #cccccc);
469
+ cursor: var(--calendar-disabled-cursor, not-allowed);
470
+ }
471
+
472
+ .outside-month {
473
+ color: var(--calendar-outside-month-color, #cccccc);
474
+ cursor: default;
475
+ }
476
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { CalendarProperties } from './properties';
2
+ declare const Calendar: import("svelte").Component<CalendarProperties, {}, "value" | "rangeStart" | "rangeEnd">;
3
+ type Calendar = ReturnType<typeof Calendar>;
4
+ export default Calendar;
@@ -0,0 +1,30 @@
1
+ import type { Snippet } from 'svelte';
2
+ export type CalendarProperties = OptionalCalendarProperties & CalendarEventProperties;
3
+ export type OptionalCalendarProperties = {
4
+ value?: Date | null;
5
+ rangeStart?: Date | null;
6
+ rangeEnd?: Date | null;
7
+ mode?: 'single' | 'range';
8
+ minDate?: Date | null;
9
+ maxDate?: Date | null;
10
+ disabledDates?: Date[] | ((date: Date) => boolean);
11
+ weekStartsOn?: 0 | 1;
12
+ locale?: string;
13
+ testId?: string;
14
+ previousMonthIcon?: Snippet;
15
+ nextMonthIcon?: Snippet;
16
+ classes?: string;
17
+ };
18
+ export type CalendarEventProperties = {
19
+ onselect?: (event: {
20
+ date: Date;
21
+ }) => void;
22
+ onrangeselect?: (event: {
23
+ rangeStart: Date;
24
+ rangeEnd: Date;
25
+ }) => void;
26
+ onmonthchange?: (event: {
27
+ year: number;
28
+ month: number;
29
+ }) => void;
30
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -8,17 +8,18 @@
8
8
  autoplayInterval = 1000,
9
9
  showDots = false,
10
10
  isScrollableLast = false,
11
- onkeydown
11
+ onkeydown,
12
+ classes
12
13
  }: CarouselProperties = $props();
13
14
 
14
- let slidesDiv: HTMLDivElement | undefined = $state();
15
+ let slidesDiv: HTMLDivElement | null = $state(null);
15
16
  let intervalId: number;
16
17
  let endTouch: number;
17
18
  let startTouch: number;
18
19
  let startMouse: number;
19
20
  let endMouse: number;
20
21
  let carouselWidth: string;
21
- let carouselDiv: HTMLDivElement | undefined = $state();
22
+ let carouselDiv: HTMLDivElement | null = $state(null);
22
23
  let activeSlideIndex = $state(0);
23
24
  let widthUnits: string;
24
25
 
@@ -66,17 +67,19 @@
66
67
  }
67
68
 
68
69
  function handleTouchStart(event: TouchEvent) {
69
- if (event.touches && Object.keys(event.touches).length > 0) {
70
- if (event.touches[0] && typeof event.changedTouches[0].clientX !== 'undefined') {
71
- startTouch = event.touches[0].clientX;
70
+ if (event.touches.length > 0) {
71
+ const touch = event.touches.item(0);
72
+ if (touch !== null) {
73
+ startTouch = touch.clientX;
72
74
  }
73
75
  }
74
76
  }
75
77
 
76
78
  function handleTouchEnd(event: TouchEvent) {
77
- if (event.changedTouches && Object.keys(event.changedTouches).length > 0) {
78
- if (event.changedTouches[0] && typeof event.changedTouches[0].clientX !== 'undefined') {
79
- endTouch = event.changedTouches[0].clientX;
79
+ if (event.changedTouches.length > 0) {
80
+ const changedTouch = event.changedTouches.item(0);
81
+ if (changedTouch !== null) {
82
+ endTouch = changedTouch.clientX;
80
83
  if (startTouch - endTouch > 20) {
81
84
  nextSlide();
82
85
  } else {
@@ -89,13 +92,13 @@
89
92
  }
90
93
 
91
94
  function handleMouseDown(event: MouseEvent) {
92
- if (event && Object.keys(event).length > 0 && typeof event.clientX !== 'undefined') {
95
+ if (typeof event.clientX !== 'undefined') {
93
96
  startMouse = event.clientX;
94
97
  }
95
98
  }
96
99
 
97
100
  function handeMouseUp(event: MouseEvent) {
98
- if (event && Object.keys(event).length > 0 && typeof event.clientX !== 'undefined') {
101
+ if (typeof event.clientX !== 'undefined') {
99
102
  endMouse = event.clientX;
100
103
  if (startMouse - endMouse > 20) {
101
104
  nextSlide();
@@ -109,7 +112,7 @@
109
112
 
110
113
  function setWidthUnit(carouselWidth: string) {
111
114
  widthUnits = carouselWidth.slice(-3);
112
- if (/^-?\d+$/.test(widthUnits[0])) {
115
+ if (/^-?\d+$/.test(widthUnits.at(0) ?? '')) {
113
116
  widthUnits = widthUnits.slice(-2);
114
117
  }
115
118
  }
@@ -135,13 +138,13 @@
135
138
  });
136
139
  </script>
137
140
 
138
- <div class="carousel-container">
139
- {#if views.length}
141
+ <div class="carousel-container {classes ?? ''}">
142
+ {#if views.length > 0}
140
143
  <div class="carousel" bind:this={carouselDiv}>
141
144
  <div class="slidesDiv" bind:this={slidesDiv}>
142
- {#each views as view}
145
+ {#each views as view, index (index)}
143
146
  <div class="current-slide">
144
- {#if view.properties}
147
+ {#if typeof view.properties === 'object'}
145
148
  <view.component properties={view.properties} />
146
149
  {:else}
147
150
  <view.component />
@@ -12,6 +12,7 @@ export type OptionalCarouselProperties = {
12
12
  autoplayInterval?: number;
13
13
  showDots?: boolean;
14
14
  isScrollableLast?: boolean;
15
+ classes?: string;
15
16
  };
16
17
  export type CarouselEventProperties = {
17
18
  onkeydown?: (event: KeyboardEvent) => void;
@@ -1,30 +1,37 @@
1
1
  <script lang="ts">
2
2
  import type { CheckListItemProperties } from './properties';
3
+ import Checkbox from '../Checkbox/Checkbox.svelte';
3
4
 
4
5
  let {
5
6
  text,
6
7
  checked = $bindable(false),
8
+ disabled = false,
7
9
  checkboxLabel,
8
- onclick
10
+ testId,
11
+ onclick,
12
+ classes
9
13
  }: CheckListItemProperties = $props();
10
14
 
11
- function handleCheckboxClick(e: MouseEvent): void {
12
- if (e.target instanceof HTMLInputElement && typeof e.target.checked === 'boolean') {
13
- checked = e.target.checked;
14
- }
15
+ function handleClick(value: boolean): void {
16
+ checked = value;
15
17
  onclick?.(checked);
16
18
  }
17
19
  </script>
18
20
 
19
- <div class="container">
20
- <input type="checkbox" class="checkbox" bind:checked onclick={handleCheckboxClick} />
21
- {#if checkboxLabel}
22
- {@render checkboxLabel?.()}
21
+ <div class="container {classes ?? ''}" class:disabled data-pw={testId}>
22
+ <div class="checkbox-wrapper">
23
+ <Checkbox
24
+ text=""
25
+ bind:checked
26
+ {disabled}
27
+ onclick={handleClick}
28
+ {...typeof testId === 'string' ? { testId: `${testId}-checkbox` } : {}}
29
+ />
30
+ </div>
31
+ {#if typeof checkboxLabel === 'function'}
32
+ {@render checkboxLabel()}
23
33
  {:else}
24
- <span class="text" class:checked>
25
- <!-- eslint-disable-next-line -->
26
- {@html text}
27
- </span>
34
+ <span class="text" class:checked>{text}</span>
28
35
  {/if}
29
36
  </div>
30
37
 
@@ -34,11 +41,20 @@
34
41
  align-items: var(--check-list-item-align-items, center);
35
42
  width: var(--check-list-item-width, 100%);
36
43
  padding: var(--check-list-item-padding);
44
+ gap: var(--check-list-item-gap, 8px);
45
+ }
46
+
47
+ .container.disabled {
48
+ opacity: var(--check-list-item-disabled-opacity, 0.4);
49
+ cursor: not-allowed;
50
+ }
51
+
52
+ .checkbox-wrapper {
53
+ flex-shrink: 0;
37
54
  }
38
55
 
39
56
  .text {
40
- margin: var(--check-list-item-margin, 0px 0px 0px 8px);
41
- font-size: var(--check-list-item-text-size, 12px);
57
+ font-size: var(--check-list-item-text-size, 14px);
42
58
  color: var(--check-list-item-text-color);
43
59
  }
44
60
 
@@ -46,15 +62,4 @@
46
62
  color: var(--check-list-item-checked-text-color);
47
63
  font-weight: var(--check-list-item-checked-font-weight);
48
64
  }
49
-
50
- input.checkbox {
51
- accent-color: var(--checkbox-accent-color, #000);
52
- border: 5px solid red;
53
- height: var(--checkbox-height, 24px);
54
- width: var(--checkbox-width, 24px);
55
- margin: var(--checkbox-margin);
56
- padding: var(--checkbox-padding);
57
- border-radius: var(--checkbox-border-radius);
58
- visibility: var(--checkbox-visibility);
59
- }
60
65
  </style>