noph-ui 0.36.1 → 0.37.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 (83) hide show
  1. package/README.md +1 -0
  2. package/dist/autocomplete/AutoComplete.svelte +1 -1
  3. package/dist/autocomplete/AutoComplete.svelte.d.ts +1 -1
  4. package/dist/autocomplete/types.d.ts +1 -1
  5. package/dist/button/Button.svelte +1 -2
  6. package/dist/button/IconButton.svelte +1 -1
  7. package/dist/button/SegmentedButton.svelte +1 -1
  8. package/dist/card/Card.svelte +1 -1
  9. package/dist/checkbox/Checkbox.svelte +1 -1
  10. package/dist/chip/AssistChip.svelte +1 -1
  11. package/dist/chip/ChipSet.svelte +1 -1
  12. package/dist/chip/FilterChip.svelte +1 -1
  13. package/dist/chip/FilterChip.svelte.d.ts +1 -1
  14. package/dist/chip/InputChip.svelte +1 -3
  15. package/dist/chip/types.d.ts +1 -1
  16. package/dist/date-picker/Calendar.svelte +487 -0
  17. package/dist/date-picker/Calendar.svelte.d.ts +4 -0
  18. package/dist/date-picker/CalendarHeader.svelte +229 -0
  19. package/dist/date-picker/CalendarHeader.svelte.d.ts +27 -0
  20. package/dist/date-picker/DatePickerDialog.svelte +481 -0
  21. package/dist/date-picker/DatePickerDialog.svelte.d.ts +4 -0
  22. package/dist/date-picker/DateRangePicker.svelte +351 -0
  23. package/dist/date-picker/DateRangePicker.svelte.d.ts +4 -0
  24. package/dist/date-picker/DockedDatePicker.svelte +518 -5
  25. package/dist/date-picker/DockedDatePicker.svelte.d.ts +3 -17
  26. package/dist/date-picker/SelectionList.svelte +148 -0
  27. package/dist/date-picker/SelectionList.svelte.d.ts +14 -0
  28. package/dist/date-picker/YearGrid.svelte +195 -0
  29. package/dist/date-picker/YearGrid.svelte.d.ts +11 -0
  30. package/dist/date-picker/dateUtils.d.ts +41 -0
  31. package/dist/date-picker/dateUtils.js +153 -0
  32. package/dist/date-picker/enterAnimation.d.ts +1 -0
  33. package/dist/date-picker/enterAnimation.js +10 -0
  34. package/dist/date-picker/index.d.ts +6 -0
  35. package/dist/date-picker/index.js +6 -0
  36. package/dist/date-picker/types.d.ts +107 -0
  37. package/dist/date-picker/types.js +1 -0
  38. package/dist/dialog/Dialog.svelte +17 -12
  39. package/dist/dialog/types.d.ts +1 -1
  40. package/dist/divider/Divider.svelte +1 -1
  41. package/dist/icons/ArrowDropDownIcon.svelte +3 -0
  42. package/dist/icons/ArrowDropDownIcon.svelte.d.ts +26 -0
  43. package/dist/icons/ChevronLeftIcon.svelte +3 -0
  44. package/dist/icons/ChevronLeftIcon.svelte.d.ts +26 -0
  45. package/dist/icons/ChevronRightIcon.svelte +3 -0
  46. package/dist/icons/ChevronRightIcon.svelte.d.ts +26 -0
  47. package/dist/icons/EditCalendarIcon.svelte +5 -0
  48. package/dist/icons/EditCalendarIcon.svelte.d.ts +26 -0
  49. package/dist/icons/index.d.ts +5 -1
  50. package/dist/icons/index.js +5 -1
  51. package/dist/index.d.ts +1 -0
  52. package/dist/index.js +1 -0
  53. package/dist/list/Item.svelte +1 -1
  54. package/dist/list/List.svelte +1 -1
  55. package/dist/list/ListItem.svelte +1 -1
  56. package/dist/loading-indicator/LoadingIndicator.svelte +2 -2
  57. package/dist/menu/Menu.svelte +3 -3
  58. package/dist/menu/MenuItem.svelte +1 -1
  59. package/dist/menu/types.d.ts +1 -1
  60. package/dist/navigation-drawer/NavigationDrawer.svelte +1 -1
  61. package/dist/navigation-drawer/NavigationDrawerItem.svelte +1 -1
  62. package/dist/navigation-rail/NavigationRail.svelte +1 -1
  63. package/dist/navigation-rail/NavigationRailItem.svelte +1 -1
  64. package/dist/progress/CircularProgress.svelte +1 -1
  65. package/dist/progress/LinearProgress.svelte +1 -4
  66. package/dist/radio/Radio.svelte +1 -1
  67. package/dist/ripple/Ripple.svelte +1 -1
  68. package/dist/select/Select.svelte +1 -1
  69. package/dist/select/Select.svelte.d.ts +1 -1
  70. package/dist/select/VirtualList.svelte +3 -4
  71. package/dist/slider/Slider.svelte +2 -6
  72. package/dist/slider/Slider.svelte.d.ts +1 -1
  73. package/dist/snackbar/Snackbar.svelte +3 -3
  74. package/dist/switch/Switch.svelte +1 -1
  75. package/dist/tabs/Tab.svelte +1 -1
  76. package/dist/tabs/Tabs.svelte +1 -1
  77. package/dist/tabs/Tabs.svelte.d.ts +1 -1
  78. package/dist/text-field/TextField.svelte +3 -3
  79. package/dist/text-field/TextField.svelte.d.ts +1 -1
  80. package/dist/tooltip/Tooltip.svelte +1 -1
  81. package/dist/types.d.ts +1 -0
  82. package/dist/types.js +23 -22
  83. package/package.json +14 -11
package/README.md CHANGED
@@ -60,6 +60,7 @@ Beta
60
60
  - Cards
61
61
  - Checkbox
62
62
  - Chips
63
+ - DatePicker
63
64
  - Dialogs
64
65
  - Divider
65
66
  - Icon buttons
@@ -3,7 +3,7 @@
3
3
  import Menu from '../menu/Menu.svelte'
4
4
  import VirtualList from '../select/VirtualList.svelte'
5
5
  import TextField from '../text-field/TextField.svelte'
6
- import type { AutoCompleteOption, AutoCompleteProps } from './types.ts'
6
+ import type { AutoCompleteOption, AutoCompleteProps } from './types.js'
7
7
 
8
8
  let {
9
9
  options = [],
@@ -1,4 +1,4 @@
1
1
  import type { AutoCompleteProps } from './types.ts';
2
- declare const AutoComplete: import("svelte").Component<AutoCompleteProps, {}, "element" | "value" | "menuOpen">;
2
+ declare const AutoComplete: import("svelte").Component<AutoCompleteProps, {}, "value" | "element" | "menuOpen">;
3
3
  type AutoComplete = ReturnType<typeof AutoComplete>;
4
4
  export default AutoComplete;
@@ -1,4 +1,4 @@
1
- import type { TextFieldProps } from '../types.ts';
1
+ import type { TextFieldProps } from '../types.js';
2
2
  import type { Snippet } from 'svelte';
3
3
  export interface AutoCompleteOption {
4
4
  value?: string | number;
@@ -4,7 +4,7 @@
4
4
  import Tooltip from '../tooltip/Tooltip.svelte'
5
5
  import { onMount } from 'svelte'
6
6
  import type { HTMLButtonAttributes } from 'svelte/elements'
7
- import type { ButtonProps } from './types.ts'
7
+ import type { ButtonProps } from './types.js'
8
8
 
9
9
  let {
10
10
  variant = 'outlined',
@@ -278,7 +278,6 @@
278
278
  background-color: color-mix(in srgb, var(--np-color-on-surface) 12%, transparent);
279
279
  }
280
280
  .outlined-disabled {
281
- /* Variant outline now rendered via pseudo-element; keep token for color */
282
281
  --_outlined-border-color: color-mix(in srgb, var(--np-color-on-surface) 12%, transparent);
283
282
  }
284
283
  .enabled:focus-visible {
@@ -4,7 +4,7 @@
4
4
  import Tooltip from '../tooltip/Tooltip.svelte'
5
5
  import { onMount } from 'svelte'
6
6
  import type { HTMLButtonAttributes } from 'svelte/elements'
7
- import type { IconButtonProps } from './types.ts'
7
+ import type { IconButtonProps } from './types.js'
8
8
 
9
9
  let {
10
10
  variant = 'text',
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import CheckIcon from '../icons/CheckIcon.svelte'
3
3
  import Ripple from '../ripple/Ripple.svelte'
4
- import type { SegmentedButtonProps } from './types.ts'
4
+ import type { SegmentedButtonProps } from './types.js'
5
5
 
6
6
  let {
7
7
  name,
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import Ripple from '../ripple/Ripple.svelte'
3
- import type { CardProps } from './types.ts'
3
+ import type { CardProps } from './types.js'
4
4
 
5
5
  let {
6
6
  image,
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import Ripple from '../ripple/Ripple.svelte'
3
- import type { CheckboxProps } from './types.ts'
3
+ import type { CheckboxProps } from './types.js'
4
4
 
5
5
  let {
6
6
  indeterminate = $bindable(),
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import type { AssistChipProps } from './types.ts'
2
+ import type { AssistChipProps } from './types.js'
3
3
  import Button from '../button/Button.svelte'
4
4
 
5
5
  let {
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { arrowKeyNav, rovingTabindex } from '../keyboard-nav.js'
3
- import type { ChipSetProps } from './types.ts'
3
+ import type { ChipSetProps } from './types.js'
4
4
 
5
5
  let { children, chipsCount, ...attributes }: ChipSetProps = $props()
6
6
 
@@ -3,7 +3,7 @@
3
3
  import CheckIcon from '../icons/CheckIcon.svelte'
4
4
  import CloseIcon from '../icons/CloseIcon.svelte'
5
5
  import Ripple from '../ripple/Ripple.svelte'
6
- import type { FilterChipProps } from './types.ts'
6
+ import type { FilterChipProps } from './types.js'
7
7
 
8
8
  let {
9
9
  selected = $bindable(),
@@ -1,4 +1,4 @@
1
1
  import type { FilterChipProps } from './types.ts';
2
- declare const FilterChip: import("svelte").Component<FilterChipProps, {}, "element" | "group" | "selected">;
2
+ declare const FilterChip: import("svelte").Component<FilterChipProps, {}, "element" | "selected" | "group">;
3
3
  type FilterChip = ReturnType<typeof FilterChip>;
4
4
  export default FilterChip;
@@ -2,7 +2,7 @@
2
2
  import IconButton from '../button/IconButton.svelte'
3
3
  import CloseIcon from '../icons/CloseIcon.svelte'
4
4
  import Ripple from '../ripple/Ripple.svelte'
5
- import type { InputChipProps } from './types.ts'
5
+ import type { InputChipProps } from './types.js'
6
6
 
7
7
  let {
8
8
  selected = $bindable(),
@@ -97,8 +97,6 @@
97
97
  overflow: hidden;
98
98
  min-width: 0;
99
99
  }
100
- /* The chip container draws the focus ring, so the body keeps none of its own.
101
- `outline-width: 0` would not do, the UA ring is `outline-style: auto`. */
102
100
  .np-input-chip-label:focus-visible {
103
101
  outline: none;
104
102
  }
@@ -1,4 +1,4 @@
1
- import type { ButtonElement, ButtonProps } from '../button/types.ts';
1
+ import type { ButtonElement, ButtonProps } from '../button/types.js';
2
2
  import type { Snippet } from 'svelte';
3
3
  import type { HTMLAttributes, MouseEventHandler } from 'svelte/elements';
4
4
  export interface ChipSetProps extends HTMLAttributes<HTMLDivElement> {
@@ -0,0 +1,487 @@
1
+ <script lang="ts">
2
+ import Ripple from '../ripple/Ripple.svelte'
3
+ import { tick } from 'svelte'
4
+ import type { Attachment } from 'svelte/attachments'
5
+ import {
6
+ addDays,
7
+ addMonths,
8
+ clampDate,
9
+ compareDays,
10
+ DAYS_IN_WEEK,
11
+ formatDateLong,
12
+ formatMonthYear,
13
+ getCalendarDays,
14
+ getWeekdayLabels,
15
+ getWeekRowCount,
16
+ isSameDay,
17
+ isWithin,
18
+ MAX_CALENDAR_ROWS,
19
+ startOfDay,
20
+ toISODate,
21
+ today as getToday,
22
+ } from './dateUtils.js'
23
+ import { afterTwoFrames } from './enterAnimation.js'
24
+ import type { CalendarProps } from './types.js'
25
+
26
+ let {
27
+ month,
28
+ selected,
29
+ rangeStart,
30
+ rangeEnd,
31
+ min,
32
+ max,
33
+ locale,
34
+ firstDayOfWeek,
35
+ isDateEnabled,
36
+ weekdays = true,
37
+ adjacentMonthDays = false,
38
+ dynamicRows = false,
39
+ todayDate,
40
+ focusedDate,
41
+ selectedLabel = 'selected',
42
+ tabStopDate,
43
+ focusRoot,
44
+ onselect,
45
+ onfocusday,
46
+ onmonthstep,
47
+ monthSubhead,
48
+ ...attributes
49
+ }: CalendarProps = $props()
50
+
51
+ const SWIPE_THRESHOLD = 48
52
+
53
+ let todayValue = $derived(todayDate ?? getToday())
54
+ let weekdayLabels = $derived(getWeekdayLabels(locale, firstDayOfWeek))
55
+ let rowCount = $derived(dynamicRows ? getWeekRowCount(month, firstDayOfWeek) : MAX_CALENDAR_ROWS)
56
+ let days = $derived(getCalendarDays(month, firstDayOfWeek, rowCount))
57
+ let weeks = $derived(
58
+ Array.from({ length: rowCount }, (_, index) =>
59
+ days.slice(index * DAYS_IN_WEEK, index * DAYS_IN_WEEK + DAYS_IN_WEEK),
60
+ ),
61
+ )
62
+ let monthLabel = $derived(formatMonthYear(month, locale))
63
+ let monthStep = $derived(month.getFullYear() * 12 + month.getMonth())
64
+
65
+ let previousMonthStep: number | undefined
66
+
67
+ const slideOnMonthChange =
68
+ (step: number): Attachment<HTMLElement> =>
69
+ (element) => {
70
+ const previous = previousMonthStep
71
+ previousMonthStep = step
72
+ if (previous === undefined || step === previous) return
73
+ const slide = `slide-from-${step > previous ? 'end' : 'start'}`
74
+ element.classList.add(slide)
75
+ const cancel = afterTwoFrames(() => element.classList.remove(slide))
76
+ return () => {
77
+ cancel()
78
+ element.classList.remove(slide)
79
+ }
80
+ }
81
+
82
+ const isEnabled = (date: Date) => isWithin(date, min, max) && (isDateEnabled?.(date) ?? true)
83
+
84
+ let tabStop = $derived.by(() => {
85
+ if (tabStopDate) return tabStopDate
86
+ const candidates = [focusedDate, selected, rangeStart, todayValue].filter(
87
+ (date): date is Date =>
88
+ !!date &&
89
+ date.getMonth() === month.getMonth() &&
90
+ date.getFullYear() === month.getFullYear(),
91
+ )
92
+ return candidates[0] ?? new Date(month.getFullYear(), month.getMonth(), 1)
93
+ })
94
+
95
+ const findDay = (root: HTMLElement, date: Date) => {
96
+ const selector = `.np-calendar-day[data-date="${toISODate(date)}"]`
97
+ return (
98
+ root.querySelector<HTMLElement>(`${selector}:not(.outside)`) ??
99
+ root.querySelector<HTMLElement>(selector)
100
+ )
101
+ }
102
+
103
+ const moveFocus = async (grid: HTMLElement, date: Date) => {
104
+ const target = startOfDay(clampDate(date, min, max))
105
+ onfocusday?.(target)
106
+ await tick()
107
+ findDay(focusRoot ?? grid, target)?.focus()
108
+ }
109
+
110
+ const handleKeydown = (event: KeyboardEvent & { currentTarget: EventTarget & HTMLElement }) => {
111
+ const grid = event.currentTarget
112
+ const from = focusedDate ?? tabStop
113
+ switch (event.key) {
114
+ case 'ArrowLeft':
115
+ moveFocus(grid, addDays(from, -1))
116
+ break
117
+ case 'ArrowRight':
118
+ moveFocus(grid, addDays(from, 1))
119
+ break
120
+ case 'ArrowUp':
121
+ moveFocus(grid, addDays(from, -DAYS_IN_WEEK))
122
+ break
123
+ case 'ArrowDown':
124
+ moveFocus(grid, addDays(from, DAYS_IN_WEEK))
125
+ break
126
+ case 'Home':
127
+ moveFocus(
128
+ grid,
129
+ addDays(from, -((from.getDay() - firstDayOfWeek + DAYS_IN_WEEK) % DAYS_IN_WEEK)),
130
+ )
131
+ break
132
+ case 'End':
133
+ moveFocus(
134
+ grid,
135
+ addDays(
136
+ from,
137
+ DAYS_IN_WEEK - 1 - ((from.getDay() - firstDayOfWeek + DAYS_IN_WEEK) % DAYS_IN_WEEK),
138
+ ),
139
+ )
140
+ break
141
+ case 'PageUp':
142
+ moveFocus(grid, addMonths(from, event.shiftKey ? -12 : -1))
143
+ break
144
+ case 'PageDown':
145
+ moveFocus(grid, addMonths(from, event.shiftKey ? 12 : 1))
146
+ break
147
+ default:
148
+ return
149
+ }
150
+ event.preventDefault()
151
+ }
152
+
153
+ let swipeStart: { x: number; y: number; id: number } | undefined
154
+
155
+ const handlePointerdown = (event: PointerEvent) => {
156
+ if (!onmonthstep || event.pointerType === 'mouse') return
157
+ swipeStart = { x: event.clientX, y: event.clientY, id: event.pointerId }
158
+ }
159
+
160
+ const handlePointerup = (event: PointerEvent) => {
161
+ if (!swipeStart || event.pointerId !== swipeStart.id) return
162
+ const dx = event.clientX - swipeStart.x
163
+ const dy = event.clientY - swipeStart.y
164
+ swipeStart = undefined
165
+ if (Math.abs(dx) < SWIPE_THRESHOLD || Math.abs(dx) <= Math.abs(dy)) return
166
+ onmonthstep?.(dx < 0 ? 1 : -1)
167
+ }
168
+
169
+ const inRange = (date: Date) =>
170
+ !!rangeStart &&
171
+ !!rangeEnd &&
172
+ compareDays(date, rangeStart) > 0 &&
173
+ compareDays(date, rangeEnd) < 0
174
+ </script>
175
+
176
+ <div
177
+ {...attributes}
178
+ class={['np-calendar', onmonthstep && 'swipeable', attributes.class]}
179
+ onpointerdown={handlePointerdown}
180
+ onpointerup={handlePointerup}
181
+ onpointercancel={() => (swipeStart = undefined)}
182
+ >
183
+ {#if monthSubhead}
184
+ {@render monthSubhead(monthLabel)}
185
+ {/if}
186
+ <div
187
+ class={['np-calendar-body', dynamicRows && 'dynamic']}
188
+ style:--np-calendar-rows={rowCount}
189
+ style:--np-calendar-head={weekdays ? '2.5rem' : '0rem'}
190
+ >
191
+ <table
192
+ {@attach slideOnMonthChange(monthStep)}
193
+ class="np-calendar-grid"
194
+ role="grid"
195
+ aria-label={monthLabel}
196
+ onkeydown={handleKeydown}
197
+ >
198
+ <thead class={weekdays ? undefined : 'np-calendar-head-hidden'}>
199
+ <tr>
200
+ {#each weekdayLabels as weekday (weekday.long)}
201
+ <th scope="col" abbr={weekday.long} class="np-calendar-weekday">
202
+ <span aria-hidden="true">{weekday.narrow}</span>
203
+ <span class="np-calendar-sr-only">{weekday.long}</span>
204
+ </th>
205
+ {/each}
206
+ </tr>
207
+ </thead>
208
+ <tbody>
209
+ {#each weeks as week (week[0].date.getTime())}
210
+ <tr>
211
+ {#each week as { date, inMonth } (date.getTime())}
212
+ {#if !inMonth && !adjacentMonthDays}
213
+ <td role="gridcell" class="np-calendar-cell"></td>
214
+ {:else}
215
+ {@const isSelected =
216
+ isSameDay(date, selected) ||
217
+ isSameDay(date, rangeStart) ||
218
+ isSameDay(date, rangeEnd)}
219
+ {@const isToday = isSameDay(date, todayValue)}
220
+ {@const enabled = isEnabled(date)}
221
+ {@const between = inRange(date)}
222
+ <td
223
+ role="gridcell"
224
+ aria-selected={isSelected}
225
+ class={[
226
+ 'np-calendar-cell',
227
+ between && 'in-range',
228
+ isSameDay(date, rangeStart) && rangeEnd && 'range-start',
229
+ isSameDay(date, rangeEnd) && rangeStart && 'range-end',
230
+ ]}
231
+ >
232
+ <button
233
+ type="button"
234
+ data-date={toISODate(date)}
235
+ class={[
236
+ 'np-calendar-day',
237
+ isSelected && 'selected',
238
+ isToday && !isSelected && 'today',
239
+ !inMonth && 'outside',
240
+ between && 'between',
241
+ ]}
242
+ tabindex={inMonth && isSameDay(date, tabStop) ? 0 : -1}
243
+ aria-disabled={!enabled}
244
+ aria-current={isToday ? 'date' : undefined}
245
+ aria-label={isSelected && selectedLabel
246
+ ? `${formatDateLong(date, locale)}, ${selectedLabel}`
247
+ : formatDateLong(date, locale)}
248
+ onclick={() => {
249
+ if (!enabled) return
250
+ onselect?.(date)
251
+ }}
252
+ onfocus={(event) => {
253
+ if (event.currentTarget.matches(':focus-visible')) onfocusday?.(date)
254
+ }}
255
+ >
256
+ <span class="np-calendar-day-container">
257
+ {date.getDate()}
258
+ {#if enabled}
259
+ <Ripple />
260
+ {/if}
261
+ </span>
262
+ </button>
263
+ </td>
264
+ {/if}
265
+ {/each}
266
+ </tr>
267
+ {/each}
268
+ </tbody>
269
+ </table>
270
+ </div>
271
+ </div>
272
+
273
+ <style>
274
+ .np-calendar-body.dynamic {
275
+ overflow: hidden;
276
+ height: calc(var(--np-calendar-head, 2.5rem) + var(--np-calendar-rows) * 3rem);
277
+ }
278
+
279
+ .np-calendar.swipeable {
280
+ touch-action: pan-y;
281
+ }
282
+
283
+ .np-calendar-sr-only,
284
+ .np-calendar-head-hidden {
285
+ position: absolute;
286
+ width: 1px;
287
+ height: 1px;
288
+ padding: 0;
289
+ margin: -1px;
290
+ overflow: hidden;
291
+ clip-path: inset(50%);
292
+ white-space: nowrap;
293
+ border-width: 0;
294
+ }
295
+
296
+ .np-calendar-grid {
297
+ display: table;
298
+ border-collapse: collapse;
299
+ border-spacing: 0;
300
+ table-layout: fixed;
301
+ overflow: visible;
302
+ box-sizing: border-box;
303
+ width: 100%;
304
+ }
305
+
306
+ .np-calendar-grid thead {
307
+ display: table-header-group;
308
+ }
309
+
310
+ .np-calendar-grid tbody {
311
+ display: table-row-group;
312
+ }
313
+
314
+ @media (prefers-reduced-motion: no-preference) {
315
+ .np-calendar-grid {
316
+ transition:
317
+ transform var(--np-motion-expressive-default-spatial),
318
+ opacity var(--np-motion-expressive-default-effects);
319
+ }
320
+
321
+ .np-calendar-body.dynamic {
322
+ transition: height var(--np-motion-expressive-default-spatial);
323
+ }
324
+
325
+ .np-calendar-grid.slide-from-start,
326
+ .np-calendar-grid.slide-from-end {
327
+ opacity: 0;
328
+ transition: none;
329
+ }
330
+
331
+ .np-calendar-grid.slide-from-end {
332
+ transform: translateX(6%);
333
+ }
334
+
335
+ .np-calendar-grid.slide-from-start {
336
+ transform: translateX(-6%);
337
+ }
338
+ }
339
+
340
+ .np-calendar-grid tr {
341
+ display: table-row;
342
+ }
343
+
344
+ .np-calendar-weekday,
345
+ .np-calendar-cell {
346
+ display: table-cell;
347
+ background: none;
348
+ border: 0;
349
+ border-radius: 0;
350
+ text-align: center;
351
+ vertical-align: middle;
352
+ }
353
+
354
+ .np-calendar-weekday {
355
+ box-sizing: content-box;
356
+ height: 1.5rem;
357
+ padding: 0 0 1rem 0;
358
+ width: 3rem;
359
+ font-size: 1rem;
360
+ line-height: 1.5rem;
361
+ font-weight: 400;
362
+ color: var(--np-date-picker-weekday-label-color, var(--np-color-on-surface));
363
+ }
364
+
365
+ .np-calendar-cell {
366
+ padding: 0;
367
+ width: 3rem;
368
+ height: 3rem;
369
+ position: relative;
370
+ }
371
+
372
+ .np-calendar-day {
373
+ font: inherit;
374
+ -webkit-tap-highlight-color: transparent;
375
+ background: none;
376
+ border: 0;
377
+ padding: 0;
378
+ margin: 0;
379
+ width: 100%;
380
+ height: 100%;
381
+ display: flex;
382
+ align-items: center;
383
+ justify-content: center;
384
+ cursor: pointer;
385
+ position: relative;
386
+ color: var(--np-color-on-surface);
387
+ }
388
+
389
+ .np-calendar-day-container {
390
+ position: relative;
391
+ box-sizing: border-box;
392
+ display: flex;
393
+ align-items: center;
394
+ justify-content: center;
395
+ width: 2.5rem;
396
+ height: 2.5rem;
397
+ border-radius: var(--np-date-picker-date-container-shape, var(--np-shape-corner-full));
398
+ font-size: 1rem;
399
+ line-height: 1.5rem;
400
+ }
401
+
402
+ @media (prefers-reduced-motion: no-preference) {
403
+ .np-calendar-day:not(.between) {
404
+ transition: color var(--np-motion-expressive-default-effects);
405
+ }
406
+
407
+ .np-calendar-day:not(.between) .np-calendar-day-container {
408
+ transition:
409
+ background-color var(--np-motion-expressive-default-effects),
410
+ outline-color var(--np-motion-expressive-default-effects);
411
+ }
412
+ }
413
+
414
+ .np-calendar-day.outside {
415
+ color: var(--np-color-on-surface-variant);
416
+ }
417
+
418
+ .np-calendar-day.today {
419
+ color: var(--np-date-picker-date-today-label-color, var(--np-color-primary));
420
+ }
421
+
422
+ .np-calendar-day.today .np-calendar-day-container {
423
+ outline: 1px solid var(--np-date-picker-date-today-outline-color, var(--np-color-primary));
424
+ outline-offset: -1px;
425
+ }
426
+
427
+ .np-calendar-day.between:not([aria-disabled='true']) {
428
+ color: var(--np-color-on-secondary-container);
429
+ --np-ripple-hover-color: var(--np-color-on-secondary-container);
430
+ --np-ripple-pressed-color: var(--np-color-on-secondary-container);
431
+ }
432
+
433
+ .np-calendar-day.selected {
434
+ color: var(--np-date-picker-date-selected-label-color, var(--np-color-on-primary));
435
+ --np-ripple-hover-color: var(
436
+ --np-date-picker-date-selected-label-color,
437
+ var(--np-color-on-primary)
438
+ );
439
+ --np-ripple-pressed-color: var(
440
+ --np-date-picker-date-selected-label-color,
441
+ var(--np-color-on-primary)
442
+ );
443
+ }
444
+
445
+ .np-calendar-day.selected .np-calendar-day-container {
446
+ background-color: var(--np-date-picker-date-selected-container-color, var(--np-color-primary));
447
+ }
448
+
449
+ .np-calendar-day[aria-disabled='true'] {
450
+ cursor: default;
451
+ color: color-mix(in srgb, var(--np-color-on-surface) 38%, transparent);
452
+ }
453
+
454
+ .np-calendar-day:focus-visible {
455
+ outline: none;
456
+ }
457
+
458
+ .np-calendar-day:focus-visible .np-calendar-day-container {
459
+ outline: 3px solid var(--np-color-secondary);
460
+ outline-offset: 2px;
461
+ }
462
+
463
+ .np-calendar-cell.in-range::before,
464
+ .np-calendar-cell.range-start::before,
465
+ .np-calendar-cell.range-end::before {
466
+ content: '';
467
+ position: absolute;
468
+ inset-block: 0.25rem;
469
+ inset-inline: 0;
470
+ background-color: var(
471
+ --np-date-picker-range-active-indicator-color,
472
+ var(--np-color-secondary-container)
473
+ );
474
+ }
475
+
476
+ .np-calendar-cell.range-start::before {
477
+ inset-inline-start: 50%;
478
+ border-start-start-radius: var(--np-shape-corner-full);
479
+ border-end-start-radius: var(--np-shape-corner-full);
480
+ }
481
+
482
+ .np-calendar-cell.range-end::before {
483
+ inset-inline-end: 50%;
484
+ border-start-end-radius: var(--np-shape-corner-full);
485
+ border-end-end-radius: var(--np-shape-corner-full);
486
+ }
487
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { CalendarProps } from './types.ts';
2
+ declare const Calendar: import("svelte").Component<CalendarProps, {}, "">;
3
+ type Calendar = ReturnType<typeof Calendar>;
4
+ export default Calendar;