noph-ui 0.51.2 → 0.53.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 (187) hide show
  1. package/dist/animation.d.ts +14 -1
  2. package/dist/animation.js +55 -2
  3. package/dist/app-bar/AppBar.svelte +71 -7
  4. package/dist/app-bar/types.d.ts +6 -0
  5. package/dist/autocomplete/AutoComplete.svelte +6 -31
  6. package/dist/autocomplete/AutoComplete.svelte.d.ts +1 -1
  7. package/dist/badge/Badge.svelte +12 -4
  8. package/dist/badge/description.d.ts +4 -0
  9. package/dist/badge/description.js +4 -0
  10. package/dist/button/Button.svelte +53 -30
  11. package/dist/button/ButtonGroup.svelte +139 -19
  12. package/dist/button/ButtonGroup.svelte.d.ts +1 -1
  13. package/dist/button/IconButton.svelte +51 -33
  14. package/dist/button/SegmentedButton.svelte +52 -15
  15. package/dist/button/SplitButton.svelte +77 -3
  16. package/dist/button/SplitButton.svelte.d.ts +1 -1
  17. package/dist/button/buttonGroup.d.ts +0 -4
  18. package/dist/button/buttonGroup.js +0 -9
  19. package/dist/button/groupContext.d.ts +10 -0
  20. package/dist/button/groupContext.js +4 -0
  21. package/dist/button/types.d.ts +19 -0
  22. package/dist/card/Card.svelte +3 -19
  23. package/dist/card/types.d.ts +12 -2
  24. package/dist/carousel/Carousel.svelte +77 -14
  25. package/dist/carousel/CarouselItem.svelte +26 -14
  26. package/dist/carousel/carouselMorph.js +1 -1
  27. package/dist/carousel/carouselStrategy.js +25 -27
  28. package/dist/checkbox/Checkbox.svelte +6 -8
  29. package/dist/chip/ChipSet.svelte +28 -2
  30. package/dist/chip/FilterChip.svelte +33 -17
  31. package/dist/chip/InputChip.svelte +127 -26
  32. package/dist/chip/SuggestionChip.svelte +6 -22
  33. package/dist/chip/SuggestionChip.svelte.d.ts +1 -2
  34. package/dist/chip/types.d.ts +8 -1
  35. package/dist/date-picker/Calendar.svelte +34 -31
  36. package/dist/date-picker/Calendar.svelte.d.ts +2 -0
  37. package/dist/date-picker/CalendarHeader.svelte +84 -62
  38. package/dist/date-picker/CalendarHeader.svelte.d.ts +3 -0
  39. package/dist/date-picker/DatePickerDialog.svelte +135 -75
  40. package/dist/date-picker/DatePickerDialog.svelte.d.ts +4 -3
  41. package/dist/date-picker/DateRangePicker.svelte +227 -78
  42. package/dist/date-picker/DateRangePicker.svelte.d.ts +3 -3
  43. package/dist/date-picker/DockedDatePicker.svelte +76 -457
  44. package/dist/date-picker/DockedDatePicker.svelte.d.ts +3 -3
  45. package/dist/date-picker/DockedDateTimePicker.svelte +128 -518
  46. package/dist/date-picker/DockedDateTimePicker.svelte.d.ts +3 -3
  47. package/dist/date-picker/DockedPickerField.svelte +221 -0
  48. package/dist/date-picker/DockedPickerField.svelte.d.ts +9 -0
  49. package/dist/date-picker/MonthPanel.svelte +291 -0
  50. package/dist/date-picker/MonthPanel.svelte.d.ts +12 -0
  51. package/dist/date-picker/SelectionList.svelte +7 -6
  52. package/dist/date-picker/SelectionList.svelte.d.ts +1 -0
  53. package/dist/date-picker/TimeColumn.svelte +2 -6
  54. package/dist/date-picker/TimeColumn.svelte.d.ts +1 -0
  55. package/dist/date-picker/YearGrid.svelte +6 -13
  56. package/dist/date-picker/YearGrid.svelte.d.ts +1 -0
  57. package/dist/date-picker/dateUtils.d.ts +4 -0
  58. package/dist/date-picker/dateUtils.js +15 -88
  59. package/dist/date-picker/exitVisibility.svelte.js +13 -6
  60. package/dist/date-picker/formatters.d.ts +16 -0
  61. package/dist/date-picker/formatters.js +48 -15
  62. package/dist/date-picker/internalTypes.d.ts +59 -1
  63. package/dist/date-picker/shortcuts.d.ts +11 -0
  64. package/dist/date-picker/shortcuts.js +40 -0
  65. package/dist/date-picker/timeUtils.d.ts +8 -3
  66. package/dist/date-picker/timeUtils.js +33 -51
  67. package/dist/date-picker/types.d.ts +22 -0
  68. package/dist/dialog/Dialog.svelte +171 -33
  69. package/dist/dialog/Dialog.svelte.d.ts +2 -1
  70. package/dist/dialog/types.d.ts +6 -0
  71. package/dist/divider/Divider.svelte +36 -10
  72. package/dist/divider/types.d.ts +1 -0
  73. package/dist/fab/ExtendedFab.svelte +26 -60
  74. package/dist/fab/Fab.svelte +13 -48
  75. package/dist/fab/FabMenu.svelte +102 -44
  76. package/dist/fab/FabMenu.svelte.d.ts +2 -1
  77. package/dist/fab/FabMenuItem.svelte +8 -0
  78. package/dist/fab/FabMenuItem.svelte.d.ts +4 -0
  79. package/dist/fab/index.d.ts +1 -0
  80. package/dist/fab/index.js +1 -0
  81. package/dist/fab/types.d.ts +6 -4
  82. package/dist/icons/Icon.svelte +1 -4
  83. package/dist/icons/MenuIcon.svelte +13 -0
  84. package/dist/icons/MenuIcon.svelte.d.ts +7 -0
  85. package/dist/icons/MenuOpenIcon.svelte +15 -0
  86. package/dist/icons/MenuOpenIcon.svelte.d.ts +7 -0
  87. package/dist/icons/index.d.ts +2 -0
  88. package/dist/icons/index.js +2 -0
  89. package/dist/internal/exit.css +33 -0
  90. package/dist/internal/field.css +337 -0
  91. package/dist/internal/fieldTypes.d.ts +6 -0
  92. package/dist/internal/focus-ring.css +25 -6
  93. package/dist/internal/interest.css +3 -1
  94. package/dist/internal/pop-in.css +19 -0
  95. package/dist/internal/visually-hidden.css +11 -0
  96. package/dist/keyboard-nav.d.ts +12 -1
  97. package/dist/keyboard-nav.js +104 -14
  98. package/dist/list/Item.svelte +84 -24
  99. package/dist/list/List.svelte +35 -2
  100. package/dist/list/ListItem.svelte +16 -2
  101. package/dist/list/context.d.ts +6 -0
  102. package/dist/list/context.js +4 -0
  103. package/dist/list/types.d.ts +7 -0
  104. package/dist/media.d.ts +1 -0
  105. package/dist/media.js +1 -0
  106. package/dist/menu/Menu.svelte +53 -20
  107. package/dist/menu/Menu.svelte.d.ts +3 -1
  108. package/dist/menu/MenuItem.svelte +9 -3
  109. package/dist/menu/types.d.ts +7 -1
  110. package/dist/navigation-bar/NavigationBar.svelte +9 -3
  111. package/dist/navigation-bar/NavigationBarItem.svelte +31 -39
  112. package/dist/navigation-drawer/NavigationDrawer.svelte +96 -20
  113. package/dist/navigation-drawer/NavigationDrawer.svelte.d.ts +2 -1
  114. package/dist/navigation-drawer/NavigationDrawerItem.svelte +10 -12
  115. package/dist/navigation-drawer/NavigationDrawerSection.svelte +49 -0
  116. package/dist/navigation-drawer/NavigationDrawerSection.svelte.d.ts +4 -0
  117. package/dist/navigation-drawer/index.d.ts +1 -0
  118. package/dist/navigation-drawer/index.js +1 -0
  119. package/dist/navigation-drawer/types.d.ts +12 -0
  120. package/dist/navigation-rail/NavigationRail.svelte +367 -7
  121. package/dist/navigation-rail/NavigationRail.svelte.d.ts +1 -1
  122. package/dist/navigation-rail/NavigationRailItem.svelte +185 -59
  123. package/dist/navigation-rail/NavigationRailSection.svelte +57 -0
  124. package/dist/navigation-rail/NavigationRailSection.svelte.d.ts +4 -0
  125. package/dist/navigation-rail/context.d.ts +6 -0
  126. package/dist/navigation-rail/context.js +5 -0
  127. package/dist/navigation-rail/index.d.ts +1 -0
  128. package/dist/navigation-rail/index.js +1 -0
  129. package/dist/navigation-rail/morph.d.ts +14 -0
  130. package/dist/navigation-rail/morph.js +78 -0
  131. package/dist/navigation-rail/types.d.ts +21 -0
  132. package/dist/press.svelte.d.ts +0 -1
  133. package/dist/press.svelte.js +0 -11
  134. package/dist/progress/CircularProgress.svelte +28 -82
  135. package/dist/progress/CircularProgress.svelte.d.ts +1 -0
  136. package/dist/progress/LinearProgress.svelte +67 -171
  137. package/dist/progress/LinearProgress.svelte.d.ts +1 -0
  138. package/dist/progress/four-color.css +34 -0
  139. package/dist/progress/types.d.ts +1 -0
  140. package/dist/radio/Radio.svelte +13 -10
  141. package/dist/ripple/Ripple.svelte +8 -16
  142. package/dist/search/Search.svelte +238 -58
  143. package/dist/search/Search.svelte.d.ts +1 -0
  144. package/dist/search/types.d.ts +4 -0
  145. package/dist/select/Check.svelte +8 -31
  146. package/dist/select/Check.svelte.d.ts +1 -1
  147. package/dist/select/NativeSelect.svelte +113 -374
  148. package/dist/select/NativeSelect.svelte.d.ts +1 -0
  149. package/dist/select/Option.svelte +2 -11
  150. package/dist/select/Select.svelte +170 -858
  151. package/dist/select/Select.svelte.d.ts +1 -0
  152. package/dist/select/VirtualList.svelte +16 -2
  153. package/dist/select/VirtualList.svelte.d.ts +6 -2
  154. package/dist/sheet/Sheet.svelte +229 -22
  155. package/dist/sheet/Sheet.svelte.d.ts +3 -1
  156. package/dist/sheet/types.d.ts +10 -0
  157. package/dist/slider/Slider.svelte +14 -64
  158. package/dist/slider/Slider.svelte.d.ts +1 -0
  159. package/dist/snackbar/Snackbar.svelte +3 -0
  160. package/dist/snackbar/Snackbar.svelte.d.ts +2 -1
  161. package/dist/switch/Switch.svelte +53 -19
  162. package/dist/tabs/Tab.svelte +30 -18
  163. package/dist/tabs/Tabs.svelte +28 -4
  164. package/dist/tabs/types.d.ts +3 -0
  165. package/dist/text-field/TextField.svelte +124 -616
  166. package/dist/text-field/TextField.svelte.d.ts +1 -0
  167. package/dist/time-picker/ClockDial.svelte +8 -25
  168. package/dist/time-picker/ClockDial.svelte.d.ts +2 -0
  169. package/dist/time-picker/DockedTimePicker.svelte +102 -239
  170. package/dist/time-picker/DockedTimePicker.svelte.d.ts +3 -3
  171. package/dist/time-picker/PeriodSelector.svelte +8 -7
  172. package/dist/time-picker/PeriodSelector.svelte.d.ts +1 -0
  173. package/dist/time-picker/TimeInputs.svelte +13 -2
  174. package/dist/time-picker/TimePickerDialog.svelte +33 -26
  175. package/dist/time-picker/TimePickerDialog.svelte.d.ts +3 -3
  176. package/dist/time-picker/TimePickerPanel.svelte +26 -4
  177. package/dist/time-picker/TimeSelectors.svelte +4 -9
  178. package/dist/time-picker/TimeSelectors.svelte.d.ts +1 -0
  179. package/dist/time-picker/internalTypes.d.ts +2 -0
  180. package/dist/time-picker/timePickerState.svelte.js +3 -9
  181. package/dist/toolbar/Toolbar.svelte +21 -11
  182. package/dist/toolbar/types.d.ts +1 -0
  183. package/dist/tooltip/RichTooltip.svelte +2 -23
  184. package/dist/tooltip/RichTooltip.svelte.d.ts +2 -1
  185. package/dist/tooltip/Tooltip.svelte +5 -25
  186. package/dist/tooltip/Tooltip.svelte.d.ts +2 -1
  187. package/package.json +12 -12
@@ -1,29 +1,15 @@
1
1
  <script lang="ts">
2
2
  import Button from '../button/Button.svelte'
3
- import IconButton from '../button/IconButton.svelte'
4
- import Divider from '../divider/Divider.svelte'
5
3
  import CalendarToday from '../icons/CalendarToday.svelte'
6
- import Menu from '../menu/Menu.svelte'
7
- import { formReset } from '../form-reset.js'
8
- import { syncOpenEffect } from '../popover.svelte.js'
9
- import TextField from '../text-field/TextField.svelte'
10
4
  import { onMount, tick } from 'svelte'
11
- import Calendar from './Calendar.svelte'
12
- import CalendarHeader from './CalendarHeader.svelte'
13
- import SelectionList from './SelectionList.svelte'
5
+ import DockedPickerField from './DockedPickerField.svelte'
6
+ import MonthPanel from './MonthPanel.svelte'
14
7
  import {
15
- addMonths,
16
- clampMonthInYear,
17
- compareDays,
18
8
  DEFAULT_YEAR_RANGE,
19
9
  formatDate,
20
10
  getDatePattern,
21
11
  getFirstDayOfWeek,
22
- getMonthNames,
23
- getWeekRowCount,
24
- isMonthWithin,
25
12
  isWithin,
26
- isYearWithin,
27
13
  parseDateInput,
28
14
  parseISODate,
29
15
  startOfMonth,
@@ -37,8 +23,6 @@
37
23
  defaultValue,
38
24
  // eslint-disable-next-line @typescript-eslint/no-unused-vars -- pulled out of the rest props on purpose
39
25
  type,
40
- 'aria-invalid': ariaInvalid,
41
- style,
42
26
  displayMonth = $bindable(),
43
27
  open = $bindable(false),
44
28
  element = $bindable(),
@@ -50,15 +34,7 @@
50
34
  isDateEnabled,
51
35
  adjacentMonthDays = false,
52
36
  label = 'Date',
53
- supportingText,
54
- issues,
55
37
  variant = 'outlined',
56
- name,
57
- form,
58
- required,
59
- disabled,
60
- readonly,
61
- noAsterisk,
62
38
  autocomplete = 'off',
63
39
  cancelLabel = 'Cancel',
64
40
  confirmLabel = 'OK',
@@ -71,26 +47,15 @@
71
47
  openCalendarLabel = 'Show date picker',
72
48
  invalidDateMessage = 'Enter a valid date.',
73
49
  selectedDateLabel = 'selected',
74
- onchange,
75
- oninput,
76
- onblur,
50
+ shortcutLabels,
77
51
  ...attributes
78
52
  }: DockedDatePickerProps = $props()
79
53
 
80
54
  const ISO_PATTERN = 'YYYY-MM-DD'
81
55
 
82
- const uid = $props.id()
83
-
84
- let menuElement = $state<HTMLDivElement>()
85
- let mode = $state<'days' | 'months' | 'years'>('days')
86
- let listMode = $state<'months' | 'years' | undefined>(undefined)
56
+ let field = $state<DockedPickerField>()
57
+ let panel = $state<MonthPanel>()
87
58
  let pending = $state<ISODate | undefined>(undefined)
88
- let focusedDay = $state<Date | undefined>(undefined)
89
- let inputElement = $state<HTMLInputElement | HTMLTextAreaElement>()
90
- let valueInput = $state<HTMLInputElement>()
91
-
92
- let typed = $state.raw<{ source: ISODate | null | undefined; text: string } | undefined>()
93
- let invalidText = $state<string | undefined>()
94
59
  let monthBeforeOpen: ISODate | undefined
95
60
 
96
61
  let current = $derived<ISODate | undefined>(
@@ -98,7 +63,6 @@
98
63
  )
99
64
 
100
65
  let todayValue = $derived(getToday())
101
- let week = $derived(firstDayOfWeek ?? getFirstDayOfWeek(locale))
102
66
  let minDate = $derived(parseISODate(min))
103
67
  let maxDate = $derived(parseISODate(max))
104
68
  let committed = $derived(parseISODate(current))
@@ -110,370 +74,100 @@
110
74
  })
111
75
 
112
76
  let localeKnown = $derived(locale !== undefined || mounted)
113
- let pattern = $derived(localeKnown ? getDatePattern(locale) : ISO_PATTERN)
114
77
  let monthDate = $derived(
115
78
  parseISODate(displayMonth) ?? startOfMonth(pendingDate ?? committed ?? todayValue),
116
79
  )
117
- let monthNames = $derived(getMonthNames(locale, 'long'))
118
- let shortMonthNames = $derived(getMonthNames(locale, 'short'))
119
- let rowCount = $derived(getWeekRowCount(monthDate, week))
120
-
121
- const setMode = (next: 'days' | 'months' | 'years') => {
122
- if (mode === next) return
123
- mode = next
124
- if (next !== 'days') listMode = next
125
- }
126
-
127
- const leaveList = async () => {
128
- setMode('days')
129
- await tick()
130
- focusCalendar()
131
- }
132
-
133
- const formatValue = () => {
134
- if (!committed) return ''
135
- return localeKnown ? formatDate(committed, locale) : toISODate(committed)
136
- }
137
-
138
- let text = $derived(typed && typed.source === current ? typed.text : formatValue())
139
-
140
- let inputInvalid = $derived(invalidText !== undefined && invalidText === text)
141
-
142
- let monthOptions = $derived(
143
- monthNames.map((monthName, index) => ({
144
- value: index,
145
- label: monthName,
146
- disabled: !isMonthWithin(monthDate.getFullYear(), index, minDate, maxDate),
147
- })),
148
- )
149
-
150
- let yearOptions = $derived(
151
- Array.from({ length: yearRange[1] - yearRange[0] + 1 }, (_, index) => {
152
- const year = yearRange[0] + index
153
- return {
154
- value: year,
155
- label: `${year}`,
156
- disabled: !isYearWithin(year, minDate, maxDate),
157
- }
158
- }),
159
- )
160
-
161
- let canPreviousMonth = $derived(
162
- !minDate ||
163
- compareDays(new Date(monthDate.getFullYear(), monthDate.getMonth(), 0), minDate) >= 0,
164
- )
165
- let canNextMonth = $derived(
166
- !maxDate ||
167
- compareDays(new Date(monthDate.getFullYear(), monthDate.getMonth() + 1, 1), maxDate) <= 0,
168
- )
169
- let canPreviousYear = $derived(
170
- monthDate.getFullYear() > yearRange[0] &&
171
- (!minDate || compareDays(addMonths(monthDate, -12), startOfMonth(minDate)) >= 0),
172
- )
173
- let canNextYear = $derived(
174
- monthDate.getFullYear() < yearRange[1] &&
175
- (!maxDate || compareDays(addMonths(monthDate, 12), startOfMonth(maxDate)) <= 0),
176
- )
177
80
 
178
81
  const setMonth = (date: Date) => {
179
82
  displayMonth = toISODate(startOfMonth(date))
180
83
  }
181
84
 
182
- const commit = (next: ISODate | undefined) => {
183
- if (current === next) return
184
- value = next
185
- onchange?.(next)
186
- }
187
-
188
- const restoreDefault = () => {
189
- const next = typeof defaultValue === 'string' ? defaultValue : undefined
190
- if (valueInput) valueInput.value = next ?? ''
191
- queueMicrotask(() => {
192
- typed = undefined
193
- invalidText = undefined
194
- pending = undefined
195
- value = next
196
- text = formatValue()
197
- })
198
- }
199
-
200
- const isShowing = () => !!menuElement?.matches(':popover-open')
201
-
202
- const openPicker = () => {
203
- if (isShowing()) return
204
- if (disabled || readonly) {
205
- open = false
206
- return
207
- }
208
- menuElement?.showPopover()
209
- }
210
-
211
- const focusCalendarWhenReady = async () => {
212
- await tick()
213
- focusCalendar()
214
- }
215
-
216
- export const show = () => openPicker()
217
-
218
- export const close = () => {
219
- if (isShowing()) menuElement?.hidePopover()
220
- }
221
-
222
- syncOpenEffect(
223
- () => menuElement,
224
- () => open,
225
- show,
226
- close,
227
- )
228
-
229
- const focusCalendar = () => {
230
- menuElement?.querySelector<HTMLElement>('.np-calendar-day[tabindex="0"]')?.focus()
231
- }
232
-
233
- const closePicker = (restoreFocus = true) => {
234
- menuElement?.hidePopover()
235
- if (restoreFocus) {
236
- element?.querySelector<HTMLElement>('input')?.focus()
237
- }
238
- }
239
-
240
- const selectDay = (date: Date) => {
241
- pending = toISODate(date)
242
- setMonth(date)
243
- focusedDay = date
244
- }
245
-
246
- const confirm = () => {
247
- typed = undefined
248
- invalidText = undefined
249
- commit(pending)
250
- closePicker()
251
- }
252
-
253
- const usableDate = (typed: string) => {
254
- const parsed = parseDateInput(typed, locale)
255
- if (!parsed) return undefined
256
- if (!isWithin(parsed, minDate, maxDate)) return undefined
257
- return (isDateEnabled?.(parsed) ?? true) ? parsed : undefined
258
- }
259
-
260
- const handleInput = (event: Event) => {
261
- const next = (event.currentTarget as HTMLInputElement).value
262
- const parsed = usableDate(next)
263
- commit(parsed ? toISODate(parsed) : undefined)
264
- if (parsed) setMonth(parsed)
265
- typed = { source: current, text: next }
266
- invalidText = undefined
267
- }
268
-
269
- const handleBlur = () => {
270
- if (!text.trim()) {
271
- invalidText = undefined
272
- return
273
- }
274
- const parsed = usableDate(text)
275
- invalidText = parsed ? undefined : text
276
- if (parsed) typed = undefined
85
+ const usableDate = (text: string) => {
86
+ const parsed = parseDateInput(text, locale)
87
+ if (!parsed || !isWithin(parsed, minDate, maxDate)) return undefined
88
+ return (isDateEnabled?.(parsed) ?? true) ? toISODate(parsed) : undefined
277
89
  }
278
90
 
279
- $effect(() => {
280
- const input = inputElement
281
- if (!input) return
282
- const unusable = text.trim() !== '' && !usableDate(text)
283
- input.setCustomValidity(unusable ? invalidDateMessage : '')
284
- })
285
-
286
- const chooseMonth = (month: number) => {
287
- setMonth(new Date(monthDate.getFullYear(), month, 1))
288
- leaveList()
289
- }
290
-
291
- const chooseYear = (year: number) => {
292
- setMonth(new Date(year, clampMonthInYear(year, monthDate.getMonth(), minDate, maxDate), 1))
293
- leaveList()
294
- }
91
+ export const show = () => field?.show()
92
+ export const close = () => field?.close()
295
93
  </script>
296
94
 
297
- <TextField
95
+ <DockedPickerField
298
96
  {...attributes}
299
- class={['np-docked-date-picker', attributes.class]}
300
- style={`anchor-name:--${uid};${style ?? ''}`}
97
+ bind:this={field}
98
+ kind="date-picker"
99
+ bind:value
100
+ bind:open
101
+ bind:element
102
+ {current}
103
+ resetValue={typeof defaultValue === 'string' ? defaultValue : undefined}
301
104
  {label}
302
105
  {variant}
303
- {issues}
304
- {disabled}
305
- {readonly}
306
- {required}
307
- {noAsterisk}
308
106
  {autocomplete}
309
- supportingText={supportingText ?? pattern}
310
- bind:value={text}
311
- bind:element
312
- bind:inputElement
313
- aria-invalid={inputInvalid || issues?.length || ariaInvalid === true || ariaInvalid === 'true'
314
- ? 'true'
315
- : undefined}
316
- oninput={(event) => {
317
- handleInput(event)
318
- oninput?.(event)
107
+ pattern={localeKnown ? getDatePattern(locale) : ISO_PATTERN}
108
+ openLabel={openCalendarLabel}
109
+ invalidMessage={invalidDateMessage}
110
+ format={() =>
111
+ committed ? (localeKnown ? formatDate(committed, locale) : toISODate(committed)) : ''}
112
+ parse={usableDate}
113
+ ontyped={(date) => setMonth(parseISODate(date)!)}
114
+ onrestore={() => (pending = undefined)}
115
+ onmenukeydown={(event) => panel?.handleKeydown(event)}
116
+ onopen={async () => {
117
+ monthBeforeOpen = displayMonth
118
+ pending = current
119
+ await tick()
120
+ panel?.focus()
319
121
  }}
320
- onblur={(event) => {
321
- handleBlur()
322
- onblur?.(event)
122
+ onclosed={() => {
123
+ panel?.reset()
124
+ displayMonth = monthBeforeOpen
323
125
  }}
324
126
  >
325
- {#snippet end()}
326
- <IconButton
327
- type="button"
328
- aria-label={openCalendarLabel}
329
- aria-expanded={open}
330
- aria-haspopup="dialog"
331
- aria-controls={open ? `${uid}-calendar` : undefined}
332
- {disabled}
333
- onclick={() => {
334
- if (open) closePicker()
335
- else openPicker()
336
- }}
337
- >
338
- <CalendarToday />
339
- </IconButton>
127
+ {#snippet icon()}
128
+ <CalendarToday />
340
129
  {/snippet}
341
- </TextField>
342
- <input
343
- bind:this={valueInput}
344
- {@attach formReset(restoreDefault)}
345
- class="np-docked-date-picker-value"
346
- type="hidden"
347
- value={current ?? ''}
348
- {name}
349
- {form}
350
- {disabled}
351
- />
352
-
353
- <Menu
354
- id="{uid}-calendar"
355
- role="dialog"
356
- aria-label={label}
357
- aria-modal="false"
358
- class="np-docked-date-picker-menu"
359
- style={`position-anchor:--${uid};`}
360
- --np-menu-justify-self="none"
361
- --np-menu-position-area="bottom span-right"
362
- --np-menu-over-anchor-position-area="span-all span-right"
363
- --np-menu-margin="0"
364
- --np-menu-container-color="var(--np-docked-date-picker-container-color, var(--np-color-surface-container-high))"
365
- --np-menu-container-shape="var(--np-docked-date-picker-container-shape, var(--np-shape-corner-large))"
366
- anchor={element}
367
- bind:element={menuElement}
368
- bind:open
369
- ontoggle={({ newState }) => {
370
- if (newState === 'open') {
371
- monthBeforeOpen = displayMonth
372
- pending = current
373
- focusCalendarWhenReady()
374
- }
375
- if (newState === 'closed') {
376
- setMode('days')
377
- listMode = undefined
378
- focusedDay = undefined
379
- displayMonth = monthBeforeOpen
380
- }
381
- }}
382
- >
383
- {#if open}
384
- <div class="np-docked-date-picker-container" style:--np-calendar-rows={rowCount}>
385
- <CalendarHeader
386
- {mode}
387
- monthLabel={shortMonthNames[monthDate.getMonth()]}
388
- yearLabel={`${monthDate.getFullYear()}`}
389
- {canPreviousMonth}
390
- {canNextMonth}
391
- {canPreviousYear}
392
- {canNextYear}
393
- {previousMonthLabel}
394
- {nextMonthLabel}
395
- {previousYearLabel}
396
- {nextYearLabel}
397
- {selectMonthLabel}
398
- {selectYearLabel}
399
- monthListId="{uid}-months"
400
- yearListId="{uid}-years"
401
- onpreviousmonth={() => setMonth(addMonths(monthDate, -1))}
402
- onnextmonth={() => setMonth(addMonths(monthDate, 1))}
403
- onpreviousyear={() => setMonth(addMonths(monthDate, -12))}
404
- onnextyear={() => setMonth(addMonths(monthDate, 12))}
405
- ontogglemonths={() => setMode(mode === 'months' ? 'days' : 'months')}
406
- ontoggleyears={() => setMode(mode === 'years' ? 'days' : 'years')}
407
- />
408
-
409
- <div class="np-docked-date-picker-views">
410
- <div class="np-docked-date-picker-body" inert={mode !== 'days'}>
411
- <Calendar
412
- month={monthDate}
413
- selected={pendingDate}
414
- min={minDate}
415
- max={maxDate}
416
- {locale}
417
- firstDayOfWeek={week}
418
- {isDateEnabled}
419
- {adjacentMonthDays}
420
- dynamicRows
421
- todayDate={todayValue}
422
- focusedDate={focusedDay}
423
- selectedLabel={selectedDateLabel}
424
- onselect={selectDay}
425
- onmonthstep={(delta) => setMonth(addMonths(monthDate, delta))}
426
- onfocusday={(date) => {
427
- focusedDay = date
428
- if (
429
- date.getMonth() !== monthDate.getMonth() ||
430
- date.getFullYear() !== monthDate.getFullYear()
431
- ) {
432
- setMonth(date)
433
- }
434
- }}
435
- />
436
- </div>
437
-
438
- {#if listMode}
439
- <div class={['np-docked-date-picker-menu-view', mode !== 'days' && 'open']}>
440
- <div class="np-docked-date-picker-menu-shade">
441
- <Divider --np-divider-color="var(--np-color-outline-variant)" />
442
- {#if listMode === 'months'}
443
- <SelectionList
444
- id="{uid}-months"
445
- aria-label={selectMonthLabel}
446
- options={monthOptions}
447
- value={monthDate.getMonth()}
448
- onselect={chooseMonth}
449
- />
450
- {:else}
451
- <SelectionList
452
- id="{uid}-years"
453
- aria-label={selectYearLabel}
454
- options={yearOptions}
455
- value={monthDate.getFullYear()}
456
- onselect={chooseYear}
457
- />
458
- {/if}
459
- </div>
460
- </div>
461
- {/if}
462
- </div>
463
-
464
- <div class="np-docked-date-picker-actions">
465
- <Button type="button" variant="text" onclick={() => closePicker()}>{cancelLabel}</Button>
466
- <Button type="button" variant="text" onclick={confirm}>{confirmLabel}</Button>
467
- </div>
130
+ <div class="np-docked-date-picker-container">
131
+ <MonthPanel
132
+ bind:this={panel}
133
+ month={monthDate}
134
+ selected={pendingDate}
135
+ min={minDate}
136
+ max={maxDate}
137
+ {locale}
138
+ firstDayOfWeek={firstDayOfWeek ?? getFirstDayOfWeek(locale)}
139
+ {yearRange}
140
+ {isDateEnabled}
141
+ {adjacentMonthDays}
142
+ today={todayValue}
143
+ {previousMonthLabel}
144
+ {nextMonthLabel}
145
+ {previousYearLabel}
146
+ {nextYearLabel}
147
+ {selectMonthLabel}
148
+ {selectYearLabel}
149
+ {selectedDateLabel}
150
+ {shortcutLabels}
151
+ onmonth={setMonth}
152
+ onselect={(date) => {
153
+ pending = toISODate(date)
154
+ setMonth(date)
155
+ }}
156
+ onconfirm={(date) => field?.confirm(toISODate(date))}
157
+ />
158
+
159
+ <div class="np-docked-date-picker-actions">
160
+ <Button type="button" variant="text" onclick={() => field?.closePicker()}
161
+ >{cancelLabel}</Button
162
+ >
163
+ <Button type="button" variant="text" onclick={() => field?.confirm(pending)}
164
+ >{confirmLabel}</Button
165
+ >
468
166
  </div>
469
- {/if}
470
- </Menu>
167
+ </div>
168
+ </DockedPickerField>
471
169
 
472
170
  <style>
473
- :global(.np-docked-date-picker-menu .np-menu) {
474
- padding: 0;
475
- }
476
-
477
171
  .np-docked-date-picker-container {
478
172
  box-sizing: border-box;
479
173
  display: flex;
@@ -484,19 +178,6 @@
484
178
  color: var(--np-color-on-surface);
485
179
  }
486
180
 
487
- .np-docked-date-picker-container :global(.np-date-picker-header) {
488
- margin-inline: 0.75rem;
489
- }
490
-
491
- .np-docked-date-picker-views {
492
- position: relative;
493
- margin-top: 1.875rem;
494
- }
495
-
496
- .np-docked-date-picker-body {
497
- padding-inline: 0.75rem;
498
- }
499
-
500
181
  .np-docked-date-picker-actions {
501
182
  display: flex;
502
183
  justify-content: flex-end;
@@ -511,66 +192,4 @@
511
192
  :global(.np-docked-date-picker-actions .np-button) {
512
193
  height: 2.25rem;
513
194
  }
514
-
515
- .np-docked-date-picker-menu-view {
516
- position: absolute;
517
- inset: 0;
518
- overflow: hidden;
519
- visibility: hidden;
520
- }
521
-
522
- .np-docked-date-picker-menu-view.open {
523
- visibility: visible;
524
- }
525
-
526
- .np-docked-date-picker-menu-shade {
527
- display: flex;
528
- flex-direction: column;
529
- height: 100%;
530
- translate: 0 -100%;
531
- opacity: 0.6;
532
- background-color: var(
533
- --np-docked-date-picker-container-color,
534
- var(--np-color-surface-container-high)
535
- );
536
- }
537
-
538
- .np-docked-date-picker-menu-view.open .np-docked-date-picker-menu-shade {
539
- translate: 0 0;
540
- opacity: 1;
541
- }
542
-
543
- .np-docked-date-picker-menu-view :global(.np-date-picker-selection-list) {
544
- flex: 1;
545
- min-height: 0;
546
- }
547
-
548
- @media (prefers-reduced-motion: no-preference) {
549
- .np-docked-date-picker-menu-view {
550
- transition: visibility var(--np-motion-expressive-default-effects);
551
- }
552
-
553
- .np-docked-date-picker-menu-shade {
554
- transition:
555
- translate var(--np-motion-expressive-default-effects),
556
- opacity var(--np-motion-expressive-fast-effects);
557
- }
558
-
559
- .np-docked-date-picker-menu-view.open .np-docked-date-picker-menu-shade {
560
- transition:
561
- translate var(--np-motion-expressive-default-effects),
562
- opacity var(--np-motion-expressive-default-effects);
563
- }
564
-
565
- @starting-style {
566
- .np-docked-date-picker-menu-view.open .np-docked-date-picker-menu-shade {
567
- translate: 0 -100%;
568
- opacity: 0.6;
569
- }
570
- }
571
- }
572
-
573
- .np-docked-date-picker-container :global(.np-divider) {
574
- flex: none;
575
- }
576
195
  </style>
@@ -1,7 +1,7 @@
1
1
  import type { DockedDatePickerProps } from './types.js';
2
2
  declare const DockedDatePicker: import("svelte").Component<DockedDatePickerProps, {
3
- show: () => void;
4
- close: () => void;
5
- }, "element" | "value" | "open" | "displayMonth">;
3
+ show: () => void | undefined;
4
+ close: () => any;
5
+ }, "open" | "element" | "value" | "displayMonth">;
6
6
  type DockedDatePicker = ReturnType<typeof DockedDatePicker>;
7
7
  export default DockedDatePicker;