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.
- package/dist/animation.d.ts +14 -1
- package/dist/animation.js +55 -2
- package/dist/app-bar/AppBar.svelte +71 -7
- package/dist/app-bar/types.d.ts +6 -0
- package/dist/autocomplete/AutoComplete.svelte +6 -31
- package/dist/autocomplete/AutoComplete.svelte.d.ts +1 -1
- package/dist/badge/Badge.svelte +12 -4
- package/dist/badge/description.d.ts +4 -0
- package/dist/badge/description.js +4 -0
- package/dist/button/Button.svelte +53 -30
- package/dist/button/ButtonGroup.svelte +139 -19
- package/dist/button/ButtonGroup.svelte.d.ts +1 -1
- package/dist/button/IconButton.svelte +51 -33
- package/dist/button/SegmentedButton.svelte +52 -15
- package/dist/button/SplitButton.svelte +77 -3
- package/dist/button/SplitButton.svelte.d.ts +1 -1
- package/dist/button/buttonGroup.d.ts +0 -4
- package/dist/button/buttonGroup.js +0 -9
- package/dist/button/groupContext.d.ts +10 -0
- package/dist/button/groupContext.js +4 -0
- package/dist/button/types.d.ts +19 -0
- package/dist/card/Card.svelte +3 -19
- package/dist/card/types.d.ts +12 -2
- package/dist/carousel/Carousel.svelte +77 -14
- package/dist/carousel/CarouselItem.svelte +26 -14
- package/dist/carousel/carouselMorph.js +1 -1
- package/dist/carousel/carouselStrategy.js +25 -27
- package/dist/checkbox/Checkbox.svelte +6 -8
- package/dist/chip/ChipSet.svelte +28 -2
- package/dist/chip/FilterChip.svelte +33 -17
- package/dist/chip/InputChip.svelte +127 -26
- package/dist/chip/SuggestionChip.svelte +6 -22
- package/dist/chip/SuggestionChip.svelte.d.ts +1 -2
- package/dist/chip/types.d.ts +8 -1
- package/dist/date-picker/Calendar.svelte +34 -31
- package/dist/date-picker/Calendar.svelte.d.ts +2 -0
- package/dist/date-picker/CalendarHeader.svelte +84 -62
- package/dist/date-picker/CalendarHeader.svelte.d.ts +3 -0
- package/dist/date-picker/DatePickerDialog.svelte +135 -75
- package/dist/date-picker/DatePickerDialog.svelte.d.ts +4 -3
- package/dist/date-picker/DateRangePicker.svelte +227 -78
- package/dist/date-picker/DateRangePicker.svelte.d.ts +3 -3
- package/dist/date-picker/DockedDatePicker.svelte +76 -457
- package/dist/date-picker/DockedDatePicker.svelte.d.ts +3 -3
- package/dist/date-picker/DockedDateTimePicker.svelte +128 -518
- package/dist/date-picker/DockedDateTimePicker.svelte.d.ts +3 -3
- package/dist/date-picker/DockedPickerField.svelte +221 -0
- package/dist/date-picker/DockedPickerField.svelte.d.ts +9 -0
- package/dist/date-picker/MonthPanel.svelte +291 -0
- package/dist/date-picker/MonthPanel.svelte.d.ts +12 -0
- package/dist/date-picker/SelectionList.svelte +7 -6
- package/dist/date-picker/SelectionList.svelte.d.ts +1 -0
- package/dist/date-picker/TimeColumn.svelte +2 -6
- package/dist/date-picker/TimeColumn.svelte.d.ts +1 -0
- package/dist/date-picker/YearGrid.svelte +6 -13
- package/dist/date-picker/YearGrid.svelte.d.ts +1 -0
- package/dist/date-picker/dateUtils.d.ts +4 -0
- package/dist/date-picker/dateUtils.js +15 -88
- package/dist/date-picker/exitVisibility.svelte.js +13 -6
- package/dist/date-picker/formatters.d.ts +16 -0
- package/dist/date-picker/formatters.js +48 -15
- package/dist/date-picker/internalTypes.d.ts +59 -1
- package/dist/date-picker/shortcuts.d.ts +11 -0
- package/dist/date-picker/shortcuts.js +40 -0
- package/dist/date-picker/timeUtils.d.ts +8 -3
- package/dist/date-picker/timeUtils.js +33 -51
- package/dist/date-picker/types.d.ts +22 -0
- package/dist/dialog/Dialog.svelte +171 -33
- package/dist/dialog/Dialog.svelte.d.ts +2 -1
- package/dist/dialog/types.d.ts +6 -0
- package/dist/divider/Divider.svelte +36 -10
- package/dist/divider/types.d.ts +1 -0
- package/dist/fab/ExtendedFab.svelte +26 -60
- package/dist/fab/Fab.svelte +13 -48
- package/dist/fab/FabMenu.svelte +102 -44
- package/dist/fab/FabMenu.svelte.d.ts +2 -1
- package/dist/fab/FabMenuItem.svelte +8 -0
- package/dist/fab/FabMenuItem.svelte.d.ts +4 -0
- package/dist/fab/index.d.ts +1 -0
- package/dist/fab/index.js +1 -0
- package/dist/fab/types.d.ts +6 -4
- package/dist/icons/Icon.svelte +1 -4
- package/dist/icons/MenuIcon.svelte +13 -0
- package/dist/icons/MenuIcon.svelte.d.ts +7 -0
- package/dist/icons/MenuOpenIcon.svelte +15 -0
- package/dist/icons/MenuOpenIcon.svelte.d.ts +7 -0
- package/dist/icons/index.d.ts +2 -0
- package/dist/icons/index.js +2 -0
- package/dist/internal/exit.css +33 -0
- package/dist/internal/field.css +337 -0
- package/dist/internal/fieldTypes.d.ts +6 -0
- package/dist/internal/focus-ring.css +25 -6
- package/dist/internal/interest.css +3 -1
- package/dist/internal/pop-in.css +19 -0
- package/dist/internal/visually-hidden.css +11 -0
- package/dist/keyboard-nav.d.ts +12 -1
- package/dist/keyboard-nav.js +104 -14
- package/dist/list/Item.svelte +84 -24
- package/dist/list/List.svelte +35 -2
- package/dist/list/ListItem.svelte +16 -2
- package/dist/list/context.d.ts +6 -0
- package/dist/list/context.js +4 -0
- package/dist/list/types.d.ts +7 -0
- package/dist/media.d.ts +1 -0
- package/dist/media.js +1 -0
- package/dist/menu/Menu.svelte +53 -20
- package/dist/menu/Menu.svelte.d.ts +3 -1
- package/dist/menu/MenuItem.svelte +9 -3
- package/dist/menu/types.d.ts +7 -1
- package/dist/navigation-bar/NavigationBar.svelte +9 -3
- package/dist/navigation-bar/NavigationBarItem.svelte +31 -39
- package/dist/navigation-drawer/NavigationDrawer.svelte +96 -20
- package/dist/navigation-drawer/NavigationDrawer.svelte.d.ts +2 -1
- package/dist/navigation-drawer/NavigationDrawerItem.svelte +10 -12
- package/dist/navigation-drawer/NavigationDrawerSection.svelte +49 -0
- package/dist/navigation-drawer/NavigationDrawerSection.svelte.d.ts +4 -0
- package/dist/navigation-drawer/index.d.ts +1 -0
- package/dist/navigation-drawer/index.js +1 -0
- package/dist/navigation-drawer/types.d.ts +12 -0
- package/dist/navigation-rail/NavigationRail.svelte +367 -7
- package/dist/navigation-rail/NavigationRail.svelte.d.ts +1 -1
- package/dist/navigation-rail/NavigationRailItem.svelte +185 -59
- package/dist/navigation-rail/NavigationRailSection.svelte +57 -0
- package/dist/navigation-rail/NavigationRailSection.svelte.d.ts +4 -0
- package/dist/navigation-rail/context.d.ts +6 -0
- package/dist/navigation-rail/context.js +5 -0
- package/dist/navigation-rail/index.d.ts +1 -0
- package/dist/navigation-rail/index.js +1 -0
- package/dist/navigation-rail/morph.d.ts +14 -0
- package/dist/navigation-rail/morph.js +78 -0
- package/dist/navigation-rail/types.d.ts +21 -0
- package/dist/press.svelte.d.ts +0 -1
- package/dist/press.svelte.js +0 -11
- package/dist/progress/CircularProgress.svelte +28 -82
- package/dist/progress/CircularProgress.svelte.d.ts +1 -0
- package/dist/progress/LinearProgress.svelte +67 -171
- package/dist/progress/LinearProgress.svelte.d.ts +1 -0
- package/dist/progress/four-color.css +34 -0
- package/dist/progress/types.d.ts +1 -0
- package/dist/radio/Radio.svelte +13 -10
- package/dist/ripple/Ripple.svelte +8 -16
- package/dist/search/Search.svelte +238 -58
- package/dist/search/Search.svelte.d.ts +1 -0
- package/dist/search/types.d.ts +4 -0
- package/dist/select/Check.svelte +8 -31
- package/dist/select/Check.svelte.d.ts +1 -1
- package/dist/select/NativeSelect.svelte +113 -374
- package/dist/select/NativeSelect.svelte.d.ts +1 -0
- package/dist/select/Option.svelte +2 -11
- package/dist/select/Select.svelte +170 -858
- package/dist/select/Select.svelte.d.ts +1 -0
- package/dist/select/VirtualList.svelte +16 -2
- package/dist/select/VirtualList.svelte.d.ts +6 -2
- package/dist/sheet/Sheet.svelte +229 -22
- package/dist/sheet/Sheet.svelte.d.ts +3 -1
- package/dist/sheet/types.d.ts +10 -0
- package/dist/slider/Slider.svelte +14 -64
- package/dist/slider/Slider.svelte.d.ts +1 -0
- package/dist/snackbar/Snackbar.svelte +3 -0
- package/dist/snackbar/Snackbar.svelte.d.ts +2 -1
- package/dist/switch/Switch.svelte +53 -19
- package/dist/tabs/Tab.svelte +30 -18
- package/dist/tabs/Tabs.svelte +28 -4
- package/dist/tabs/types.d.ts +3 -0
- package/dist/text-field/TextField.svelte +124 -616
- package/dist/text-field/TextField.svelte.d.ts +1 -0
- package/dist/time-picker/ClockDial.svelte +8 -25
- package/dist/time-picker/ClockDial.svelte.d.ts +2 -0
- package/dist/time-picker/DockedTimePicker.svelte +102 -239
- package/dist/time-picker/DockedTimePicker.svelte.d.ts +3 -3
- package/dist/time-picker/PeriodSelector.svelte +8 -7
- package/dist/time-picker/PeriodSelector.svelte.d.ts +1 -0
- package/dist/time-picker/TimeInputs.svelte +13 -2
- package/dist/time-picker/TimePickerDialog.svelte +33 -26
- package/dist/time-picker/TimePickerDialog.svelte.d.ts +3 -3
- package/dist/time-picker/TimePickerPanel.svelte +26 -4
- package/dist/time-picker/TimeSelectors.svelte +4 -9
- package/dist/time-picker/TimeSelectors.svelte.d.ts +1 -0
- package/dist/time-picker/internalTypes.d.ts +2 -0
- package/dist/time-picker/timePickerState.svelte.js +3 -9
- package/dist/toolbar/Toolbar.svelte +21 -11
- package/dist/toolbar/types.d.ts +1 -0
- package/dist/tooltip/RichTooltip.svelte +2 -23
- package/dist/tooltip/RichTooltip.svelte.d.ts +2 -1
- package/dist/tooltip/Tooltip.svelte +5 -25
- package/dist/tooltip/Tooltip.svelte.d.ts +2 -1
- package/package.json +12 -12
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
disabled = false,
|
|
14
14
|
label = '',
|
|
15
15
|
icon,
|
|
16
|
+
trailingIcon,
|
|
16
17
|
element = $bindable(),
|
|
17
|
-
removeAriaLabel
|
|
18
|
+
removeAriaLabel,
|
|
18
19
|
onremove,
|
|
19
20
|
name,
|
|
20
21
|
value,
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
bind:this={element}
|
|
52
53
|
class={[
|
|
53
54
|
'np-filter-chip',
|
|
55
|
+
'np-focus-ring-within',
|
|
54
56
|
variant === 'elevated' ? 'np-filter-chip-elevated' : 'np-filter-chip-default',
|
|
55
57
|
icon ? 'np-filter-chip-icon' : '',
|
|
56
58
|
removable ? 'np-filter-chip-removable' : '',
|
|
@@ -69,10 +71,22 @@
|
|
|
69
71
|
<CheckIcon width={18} height={18} />
|
|
70
72
|
</div>
|
|
71
73
|
<div class="np-chip-label">{label}</div>
|
|
74
|
+
{#if trailingIcon && !removable}
|
|
75
|
+
<div class="np-chip-trailing-icon" aria-hidden="true">
|
|
76
|
+
{@render trailingIcon()}
|
|
77
|
+
</div>
|
|
78
|
+
{/if}
|
|
79
|
+
<span class="np-touch"></span>
|
|
72
80
|
<input
|
|
73
81
|
type="checkbox"
|
|
74
82
|
checked={isChecked}
|
|
75
83
|
{onchange}
|
|
84
|
+
onkeydown={(event) => {
|
|
85
|
+
// Enter selects like Space, instead of submitting the form.
|
|
86
|
+
if (event.key !== 'Enter') return
|
|
87
|
+
event.preventDefault()
|
|
88
|
+
event.currentTarget.click()
|
|
89
|
+
}}
|
|
76
90
|
{value}
|
|
77
91
|
{name}
|
|
78
92
|
{disabled}
|
|
@@ -89,7 +103,7 @@
|
|
|
89
103
|
type="button"
|
|
90
104
|
size="xs"
|
|
91
105
|
--np-icon-button-icon-size="1.125rem"
|
|
92
|
-
aria-label={removeAriaLabel}
|
|
106
|
+
aria-label={removeAriaLabel ?? `Remove ${label}`}
|
|
93
107
|
onclick={onremove}
|
|
94
108
|
>
|
|
95
109
|
<CloseIcon />
|
|
@@ -99,6 +113,7 @@
|
|
|
99
113
|
|
|
100
114
|
<style>
|
|
101
115
|
.np-filter-chip {
|
|
116
|
+
box-sizing: border-box;
|
|
102
117
|
position: relative;
|
|
103
118
|
display: inline-flex;
|
|
104
119
|
align-items: center;
|
|
@@ -107,7 +122,6 @@
|
|
|
107
122
|
--np-icon-button-icon-color: var(--np-color-on-surface-variant);
|
|
108
123
|
--np-icon-size: 1.125rem;
|
|
109
124
|
--np-ripple-pressed-opacity: 0.1;
|
|
110
|
-
min-width: 0;
|
|
111
125
|
transition: box-shadow var(--np-motion-expressive-slow-effects);
|
|
112
126
|
}
|
|
113
127
|
.np-filter-chip-label input {
|
|
@@ -117,6 +131,7 @@
|
|
|
117
131
|
}
|
|
118
132
|
.np-filter-chip-label {
|
|
119
133
|
cursor: pointer;
|
|
134
|
+
position: relative;
|
|
120
135
|
display: inline-flex;
|
|
121
136
|
align-items: center;
|
|
122
137
|
height: 2rem;
|
|
@@ -126,7 +141,19 @@
|
|
|
126
141
|
gap: 0.5rem;
|
|
127
142
|
z-index: 1;
|
|
128
143
|
padding-inline: 1rem;
|
|
129
|
-
|
|
144
|
+
}
|
|
145
|
+
.np-chip-trailing-icon {
|
|
146
|
+
display: flex;
|
|
147
|
+
margin-inline-end: -0.5rem;
|
|
148
|
+
}
|
|
149
|
+
/* The chip keeps a 48px tall target. */
|
|
150
|
+
.np-touch {
|
|
151
|
+
position: absolute;
|
|
152
|
+
inset-inline: 0;
|
|
153
|
+
top: 50%;
|
|
154
|
+
translate: 0 -50%;
|
|
155
|
+
height: 3rem;
|
|
156
|
+
z-index: -1;
|
|
130
157
|
}
|
|
131
158
|
.np-chip-icon-checked {
|
|
132
159
|
display: flex;
|
|
@@ -154,8 +181,10 @@
|
|
|
154
181
|
.np-filter-chip-icon .np-filter-chip-label {
|
|
155
182
|
padding-inline-start: 0.5rem;
|
|
156
183
|
}
|
|
184
|
+
/* Removable, selecting and removing each keep a 48px target side by side. */
|
|
157
185
|
.np-filter-chip-removable {
|
|
158
186
|
padding-inline-end: 1px;
|
|
187
|
+
min-width: 5.5rem;
|
|
159
188
|
}
|
|
160
189
|
.np-filter-chip-removable .np-filter-chip-label {
|
|
161
190
|
padding-inline-end: 1px;
|
|
@@ -229,16 +258,6 @@
|
|
|
229
258
|
.np-filter-chip:has(input:checked) .np-filter-chip-label {
|
|
230
259
|
color: var(--np-color-on-secondary-container);
|
|
231
260
|
}
|
|
232
|
-
.np-filter-chip-label:focus-visible {
|
|
233
|
-
outline-width: 0;
|
|
234
|
-
}
|
|
235
|
-
.np-filter-chip:has(input:focus-visible) {
|
|
236
|
-
outline-style: solid;
|
|
237
|
-
outline-color: var(--np-color-secondary);
|
|
238
|
-
outline-width: 3px;
|
|
239
|
-
outline-offset: 2px;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
261
|
.np-filter-chip-disabled .np-filter-chip-label {
|
|
243
262
|
cursor: default;
|
|
244
263
|
color: var(--np-color-on-surface) !important;
|
|
@@ -270,8 +289,5 @@
|
|
|
270
289
|
.np-filter-chip-icon .np-chip-icon-checked {
|
|
271
290
|
transition: none;
|
|
272
291
|
}
|
|
273
|
-
.np-filter-chip:has(input:focus-visible) {
|
|
274
|
-
animation: focusAnimation var(--np-motion-expressive-slow-effects) forwards;
|
|
275
|
-
}
|
|
276
292
|
}
|
|
277
293
|
</style>
|
|
@@ -10,9 +10,11 @@
|
|
|
10
10
|
disabled = false,
|
|
11
11
|
label = '',
|
|
12
12
|
icon,
|
|
13
|
+
avatar,
|
|
14
|
+
variant = 'outlined',
|
|
13
15
|
element = $bindable(),
|
|
14
16
|
actionElement = $bindable(),
|
|
15
|
-
removeAriaLabel
|
|
17
|
+
removeAriaLabel,
|
|
16
18
|
onclick,
|
|
17
19
|
onremove,
|
|
18
20
|
name,
|
|
@@ -22,46 +24,88 @@
|
|
|
22
24
|
}: InputChipProps = $props()
|
|
23
25
|
|
|
24
26
|
let hasError = $derived(!!issues?.length)
|
|
27
|
+
let content = $derived(label || `${value ?? ''}`)
|
|
28
|
+
// With nothing to do but remove, the chip is one focusable element: its remove button.
|
|
29
|
+
let hasAction = $derived(!!onclick)
|
|
30
|
+
let removeElement: HTMLElement | undefined = $state()
|
|
31
|
+
|
|
32
|
+
// Backspace and Delete remove the focused chip. Focus moves on to a neighbour first, so it is
|
|
33
|
+
// not lost when the chip leaves the page.
|
|
34
|
+
const removeWithKey = (event: KeyboardEvent) => {
|
|
35
|
+
if (disabled || (event.key !== 'Backspace' && event.key !== 'Delete')) return
|
|
36
|
+
event.preventDefault()
|
|
37
|
+
const set = element?.closest('.np-chip-set')
|
|
38
|
+
if (set && element) {
|
|
39
|
+
const chips = [
|
|
40
|
+
...set.querySelectorAll<HTMLElement>('.np-input-chip:not(.np-input-chip-disabled)'),
|
|
41
|
+
]
|
|
42
|
+
const index = chips.indexOf(element)
|
|
43
|
+
const neighbour = chips[index + 1] ?? chips[index - 1]
|
|
44
|
+
neighbour?.querySelector<HTMLElement>('button')?.focus()
|
|
45
|
+
}
|
|
46
|
+
removeElement?.click()
|
|
47
|
+
}
|
|
25
48
|
</script>
|
|
26
49
|
|
|
27
50
|
<div
|
|
28
51
|
{...attributes}
|
|
29
52
|
bind:this={element}
|
|
30
53
|
aria-disabled={disabled}
|
|
54
|
+
onkeydown={(event) => {
|
|
55
|
+
attributes.onkeydown?.(event)
|
|
56
|
+
if (!event.defaultPrevented) removeWithKey(event)
|
|
57
|
+
}}
|
|
31
58
|
class={[
|
|
32
59
|
'np-input-chip',
|
|
33
|
-
|
|
60
|
+
variant === 'elevated' && 'np-input-chip-elevated',
|
|
61
|
+
hasAction && 'np-input-chip-action',
|
|
62
|
+
avatar ? 'np-input-chip-avatar' : icon ? 'np-input-chip-icon' : '',
|
|
34
63
|
disabled ? 'np-input-chip-disabled' : '',
|
|
35
64
|
selected ? 'np-input-chip-selected' : '',
|
|
36
65
|
hasError && !disabled && 'np-chip-error',
|
|
37
66
|
attributes.class,
|
|
38
67
|
]}
|
|
39
68
|
>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
{
|
|
46
|
-
|
|
47
|
-
>
|
|
48
|
-
{#if icon}
|
|
49
|
-
<div class="np-chip-icon">
|
|
69
|
+
{#snippet chipContent()}
|
|
70
|
+
{#if avatar}
|
|
71
|
+
<div class="np-chip-avatar" aria-hidden="true">
|
|
72
|
+
{@render avatar()}
|
|
73
|
+
</div>
|
|
74
|
+
{:else if icon}
|
|
75
|
+
<div class="np-chip-icon" aria-hidden="true">
|
|
50
76
|
{@render icon()}
|
|
51
77
|
</div>
|
|
52
78
|
{/if}
|
|
53
|
-
<div class="np-chip-label">{
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
79
|
+
<div class="np-chip-label">{content}</div>
|
|
80
|
+
{/snippet}
|
|
81
|
+
{#if hasAction}
|
|
82
|
+
<button
|
|
83
|
+
bind:this={actionElement}
|
|
84
|
+
type="button"
|
|
85
|
+
class="np-input-chip-label"
|
|
86
|
+
aria-pressed={selected === undefined ? undefined : selected}
|
|
87
|
+
{disabled}
|
|
88
|
+
{onclick}
|
|
89
|
+
>
|
|
90
|
+
{@render chipContent()}
|
|
91
|
+
<span class="np-touch"></span>
|
|
92
|
+
</button>
|
|
93
|
+
{#if !disabled}
|
|
94
|
+
<Ripple forElement={actionElement} />
|
|
95
|
+
{/if}
|
|
96
|
+
{:else}
|
|
97
|
+
<div class="np-input-chip-label">
|
|
98
|
+
{@render chipContent()}
|
|
99
|
+
</div>
|
|
58
100
|
{/if}
|
|
101
|
+
<input type="hidden" {value} {name} {disabled} />
|
|
59
102
|
<IconButton
|
|
60
103
|
{disabled}
|
|
61
104
|
type="button"
|
|
62
105
|
size="xs"
|
|
63
106
|
--np-icon-button-icon-size="1.125rem"
|
|
64
|
-
aria-label={removeAriaLabel}
|
|
107
|
+
aria-label={removeAriaLabel ?? `Remove ${content}`}
|
|
108
|
+
bind:element={removeElement}
|
|
65
109
|
onclick={onremove}
|
|
66
110
|
>
|
|
67
111
|
<CloseIcon />
|
|
@@ -70,6 +114,7 @@
|
|
|
70
114
|
|
|
71
115
|
<style>
|
|
72
116
|
.np-input-chip {
|
|
117
|
+
box-sizing: border-box;
|
|
73
118
|
position: relative;
|
|
74
119
|
display: inline-flex;
|
|
75
120
|
align-items: center;
|
|
@@ -78,8 +123,12 @@
|
|
|
78
123
|
--np-icon-button-icon-color: var(--np-color-on-surface-variant);
|
|
79
124
|
--np-icon-size: 1.125rem;
|
|
80
125
|
--np-ripple-pressed-opacity: 0.1;
|
|
126
|
+
--_state-color: var(--np-color-on-surface-variant);
|
|
81
127
|
padding-inline-end: 1px;
|
|
82
|
-
|
|
128
|
+
}
|
|
129
|
+
/* With an action besides remove, both keep a 48px target side by side. */
|
|
130
|
+
.np-input-chip-action {
|
|
131
|
+
min-width: 5.5rem;
|
|
83
132
|
}
|
|
84
133
|
.np-chip-error {
|
|
85
134
|
--np-input-chip-outline-color: var(--np-color-error);
|
|
@@ -97,6 +146,7 @@
|
|
|
97
146
|
padding-block: 0;
|
|
98
147
|
padding-inline-end: 0;
|
|
99
148
|
cursor: pointer;
|
|
149
|
+
position: relative;
|
|
100
150
|
display: inline-flex;
|
|
101
151
|
align-items: center;
|
|
102
152
|
height: 2rem;
|
|
@@ -119,9 +169,36 @@
|
|
|
119
169
|
.np-input-chip-selected .np-chip-icon {
|
|
120
170
|
color: var(--np-color-primary);
|
|
121
171
|
}
|
|
172
|
+
div.np-input-chip-label {
|
|
173
|
+
cursor: default;
|
|
174
|
+
}
|
|
122
175
|
.np-input-chip-icon .np-input-chip-label {
|
|
123
176
|
padding-inline-start: 0.5rem;
|
|
124
177
|
}
|
|
178
|
+
.np-input-chip-avatar .np-input-chip-label {
|
|
179
|
+
padding-inline-start: 0.25rem;
|
|
180
|
+
}
|
|
181
|
+
/* A leading image is larger than an icon, with rounded corners. */
|
|
182
|
+
.np-chip-avatar {
|
|
183
|
+
display: flex;
|
|
184
|
+
flex: none;
|
|
185
|
+
width: 1.5rem;
|
|
186
|
+
height: 1.5rem;
|
|
187
|
+
border-radius: 0.75rem;
|
|
188
|
+
overflow: hidden;
|
|
189
|
+
}
|
|
190
|
+
.np-chip-avatar > :global(*) {
|
|
191
|
+
width: 100%;
|
|
192
|
+
height: 100%;
|
|
193
|
+
object-fit: cover;
|
|
194
|
+
}
|
|
195
|
+
.np-touch {
|
|
196
|
+
position: absolute;
|
|
197
|
+
inset-inline: 0;
|
|
198
|
+
top: 50%;
|
|
199
|
+
translate: 0 -50%;
|
|
200
|
+
height: 3rem;
|
|
201
|
+
}
|
|
125
202
|
.np-chip-label {
|
|
126
203
|
line-height: 1.25rem;
|
|
127
204
|
font-size: 0.875rem;
|
|
@@ -150,17 +227,47 @@
|
|
|
150
227
|
outline-color: transparent;
|
|
151
228
|
background-color: var(--np-color-secondary-container);
|
|
152
229
|
}
|
|
230
|
+
.np-input-chip-elevated {
|
|
231
|
+
box-shadow: var(--np-elevation-1);
|
|
232
|
+
}
|
|
233
|
+
.np-input-chip-elevated:not(.np-input-chip-selected)::before {
|
|
234
|
+
outline-color: transparent;
|
|
235
|
+
background-color: var(--np-color-surface-container-low);
|
|
236
|
+
}
|
|
237
|
+
.np-input-chip-elevated.np-input-chip-disabled {
|
|
238
|
+
box-shadow: none;
|
|
239
|
+
}
|
|
153
240
|
.np-input-chip-selected {
|
|
154
241
|
--np-icon-button-icon-color: var(--np-color-on-secondary-container);
|
|
242
|
+
--_state-color: var(--np-color-on-secondary-container);
|
|
155
243
|
}
|
|
156
244
|
.np-input-chip-selected .np-input-chip-label {
|
|
157
245
|
color: var(--np-color-on-secondary-container);
|
|
158
246
|
}
|
|
159
|
-
|
|
247
|
+
/* The whole chip shows focus, with its ring and a 10% state layer: when its body is focused, or its
|
|
248
|
+
remove button when that is all the chip has. A remove button next to a body shows its own. */
|
|
249
|
+
.np-input-chip:is(
|
|
250
|
+
:has(> .np-input-chip-label:focus-visible),
|
|
251
|
+
:not(.np-input-chip-action):has(:global(:focus-visible))
|
|
252
|
+
) {
|
|
160
253
|
outline-style: solid;
|
|
161
254
|
outline-color: var(--np-color-secondary);
|
|
162
255
|
outline-width: 3px;
|
|
163
256
|
outline-offset: 2px;
|
|
257
|
+
&::before {
|
|
258
|
+
--_state-layer: color-mix(in srgb, var(--_state-color) 10%, transparent);
|
|
259
|
+
background-image: linear-gradient(var(--_state-layer), var(--_state-layer));
|
|
260
|
+
}
|
|
261
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
262
|
+
animation: focusAnimation var(--np-motion-expressive-slow-effects) forwards;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
.np-input-chip:not(.np-input-chip-action) {
|
|
266
|
+
--np-ripple-focus-opacity: 0;
|
|
267
|
+
}
|
|
268
|
+
.np-input-chip:not(.np-input-chip-action) :global(.np-icon-button:focus-visible) {
|
|
269
|
+
outline: none;
|
|
270
|
+
animation: none;
|
|
164
271
|
}
|
|
165
272
|
|
|
166
273
|
.np-input-chip-disabled .np-input-chip-label {
|
|
@@ -176,10 +283,4 @@
|
|
|
176
283
|
outline-color: transparent;
|
|
177
284
|
background-color: color-mix(in srgb, var(--np-color-on-surface) 12%, transparent);
|
|
178
285
|
}
|
|
179
|
-
|
|
180
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
181
|
-
.np-input-chip:has(:focus-visible) {
|
|
182
|
-
animation: focusAnimation var(--np-motion-expressive-slow-effects) forwards;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
286
|
</style>
|
|
@@ -1,29 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import
|
|
2
|
+
import AssistChip from './AssistChip.svelte'
|
|
3
3
|
import type { SuggestionChipProps } from './types.js'
|
|
4
4
|
|
|
5
|
-
let {
|
|
6
|
-
variant = 'outlined',
|
|
7
|
-
disabled = false,
|
|
8
|
-
label = '',
|
|
9
|
-
element = $bindable(),
|
|
10
|
-
...attributes
|
|
11
|
-
}: SuggestionChipProps = $props()
|
|
5
|
+
let { element = $bindable(), ...attributes }: SuggestionChipProps = $props()
|
|
12
6
|
</script>
|
|
13
7
|
|
|
14
|
-
<
|
|
15
|
-
--np-
|
|
16
|
-
--np-
|
|
17
|
-
--np-outlined-button-outline-color="var(--np-suggestion-chip-outline-color, var(--np-color-outline-variant))"
|
|
18
|
-
--np-button-padding="1rem"
|
|
19
|
-
--np-button-shape="0.5rem"
|
|
20
|
-
style="letter-spacing: 0.006rem"
|
|
8
|
+
<AssistChip
|
|
9
|
+
--np-assist-chip-label-text-color="var(--np-suggestion-chip-label-text-color, var(--np-color-on-surface-variant))"
|
|
10
|
+
--np-assist-chip-outline-color="var(--np-suggestion-chip-outline-color, var(--np-color-outline-variant))"
|
|
21
11
|
bind:element
|
|
22
12
|
{...attributes}
|
|
23
|
-
|
|
24
|
-
shape="square"
|
|
25
|
-
{variant}
|
|
26
|
-
{disabled}
|
|
27
|
-
>
|
|
28
|
-
{label}
|
|
29
|
-
</Button>
|
|
13
|
+
/>
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
declare const SuggestionChip: import("svelte").Component<SuggestionChipProps, {}, "element">;
|
|
1
|
+
declare const SuggestionChip: import("svelte").Component<import("./types.js").AssistChipProps, {}, "element">;
|
|
3
2
|
type SuggestionChip = ReturnType<typeof SuggestionChip>;
|
|
4
3
|
export default SuggestionChip;
|
package/dist/chip/types.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface AssistChipProps extends HTMLAttributes<ButtonElement>, Omit<HTM
|
|
|
13
13
|
element?: HTMLElement;
|
|
14
14
|
type?: 'submit' | 'reset' | 'button' | (string & {}) | null;
|
|
15
15
|
}
|
|
16
|
-
export type SuggestionChipProps =
|
|
16
|
+
export type SuggestionChipProps = AssistChipProps;
|
|
17
17
|
export interface FilterChipProps extends HTMLAttributes<HTMLDivElement> {
|
|
18
18
|
selected?: boolean;
|
|
19
19
|
removable?: boolean;
|
|
@@ -21,6 +21,9 @@ export interface FilterChipProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
21
21
|
variant?: 'outlined' | 'elevated';
|
|
22
22
|
label?: string;
|
|
23
23
|
icon?: Snippet;
|
|
24
|
+
/** Trailing icon, such as an arrow for a chip that opens a menu. Not shown when `removable`. */
|
|
25
|
+
trailingIcon?: Snippet;
|
|
26
|
+
/** Defaults to "Remove" and the chip's label. */
|
|
24
27
|
removeAriaLabel?: string;
|
|
25
28
|
element?: HTMLDivElement;
|
|
26
29
|
name?: string;
|
|
@@ -33,8 +36,12 @@ export interface FilterChipProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
33
36
|
export interface InputChipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onclick'> {
|
|
34
37
|
selected?: boolean;
|
|
35
38
|
disabled?: boolean | null;
|
|
39
|
+
variant?: 'outlined' | 'elevated';
|
|
36
40
|
label?: string;
|
|
37
41
|
icon?: Snippet;
|
|
42
|
+
/** A 24px leading image, such as a person's photo. Takes the place of `icon`. */
|
|
43
|
+
avatar?: Snippet;
|
|
44
|
+
/** Defaults to "Remove" and the chip's label. */
|
|
38
45
|
removeAriaLabel?: string;
|
|
39
46
|
element?: HTMLDivElement;
|
|
40
47
|
actionElement?: HTMLButtonElement;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import '../internal/focus-ring.css'
|
|
3
|
+
import '../internal/visually-hidden.css'
|
|
2
4
|
import Ripple from '../ripple/Ripple.svelte'
|
|
3
|
-
import {
|
|
5
|
+
import { flushSync } from 'svelte'
|
|
4
6
|
import type { Attachment } from 'svelte/attachments'
|
|
5
7
|
import {
|
|
6
8
|
addDays,
|
|
@@ -16,6 +18,7 @@
|
|
|
16
18
|
isSameDay,
|
|
17
19
|
isWithin,
|
|
18
20
|
MAX_CALENDAR_ROWS,
|
|
21
|
+
parseISODate,
|
|
19
22
|
startOfDay,
|
|
20
23
|
toISODate,
|
|
21
24
|
today as getToday,
|
|
@@ -42,6 +45,7 @@
|
|
|
42
45
|
tabStopDate,
|
|
43
46
|
focusRoot,
|
|
44
47
|
onselect,
|
|
48
|
+
onconfirm,
|
|
45
49
|
onfocusday,
|
|
46
50
|
onmonthstep,
|
|
47
51
|
monthSubhead,
|
|
@@ -100,22 +104,32 @@
|
|
|
100
104
|
)
|
|
101
105
|
}
|
|
102
106
|
|
|
103
|
-
|
|
107
|
+
// The month changes and focus moves in one step, so no key lands on the page in between.
|
|
108
|
+
const moveFocus = (grid: HTMLElement, date: Date) => {
|
|
104
109
|
const target = startOfDay(clampDate(date, min, max))
|
|
105
|
-
onfocusday?.(target)
|
|
106
|
-
await tick()
|
|
110
|
+
flushSync(() => onfocusday?.(target))
|
|
107
111
|
findDay(focusRoot ?? grid, target)?.focus()
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
const handleKeydown = (event: KeyboardEvent & { currentTarget: EventTarget & HTMLElement }) => {
|
|
111
115
|
const grid = event.currentTarget
|
|
112
116
|
const from = focusedDate ?? tabStop
|
|
117
|
+
if (event.key === 'Enter' && onconfirm) {
|
|
118
|
+
const day = (event.target as HTMLElement).closest<HTMLElement>('.np-calendar-day')
|
|
119
|
+
const date = parseISODate(day?.dataset.date)
|
|
120
|
+
if (!day || !date || day.getAttribute('aria-disabled') === 'true') return
|
|
121
|
+
event.preventDefault()
|
|
122
|
+
onselect?.(date)
|
|
123
|
+
onconfirm(date)
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
const forward = getComputedStyle(grid).direction === 'rtl' ? -1 : 1
|
|
113
127
|
switch (event.key) {
|
|
114
128
|
case 'ArrowLeft':
|
|
115
|
-
moveFocus(grid, addDays(from, -
|
|
129
|
+
moveFocus(grid, addDays(from, -forward))
|
|
116
130
|
break
|
|
117
131
|
case 'ArrowRight':
|
|
118
|
-
moveFocus(grid, addDays(from,
|
|
132
|
+
moveFocus(grid, addDays(from, forward))
|
|
119
133
|
break
|
|
120
134
|
case 'ArrowUp':
|
|
121
135
|
moveFocus(grid, addDays(from, -DAYS_IN_WEEK))
|
|
@@ -195,12 +209,14 @@
|
|
|
195
209
|
aria-label={monthLabel}
|
|
196
210
|
onkeydown={handleKeydown}
|
|
197
211
|
>
|
|
198
|
-
<thead class={weekdays ? undefined : 'np-
|
|
212
|
+
<thead class={weekdays ? undefined : 'np-visually-hidden'}>
|
|
199
213
|
<tr>
|
|
200
214
|
{#each weekdayLabels as weekday (weekday.long)}
|
|
201
215
|
<th scope="col" abbr={weekday.long} class="np-calendar-weekday">
|
|
202
|
-
<span aria-hidden="true"
|
|
203
|
-
|
|
216
|
+
<span class="np-calendar-weekday-short" aria-hidden="true" title={weekday.long}
|
|
217
|
+
>{weekday.narrow}</span
|
|
218
|
+
>
|
|
219
|
+
<span class="np-visually-hidden">{weekday.long}</span>
|
|
204
220
|
</th>
|
|
205
221
|
{/each}
|
|
206
222
|
</tr>
|
|
@@ -254,7 +270,7 @@
|
|
|
254
270
|
if (event.currentTarget.matches(':focus-visible')) onfocusday?.(date)
|
|
255
271
|
}}
|
|
256
272
|
>
|
|
257
|
-
<span class="np-calendar-day-container">
|
|
273
|
+
<span class="np-calendar-day-container np-focus-ring-part">
|
|
258
274
|
{date.getDate()}
|
|
259
275
|
{#if enabled}
|
|
260
276
|
<Ripple />
|
|
@@ -273,27 +289,17 @@
|
|
|
273
289
|
|
|
274
290
|
<style>
|
|
275
291
|
.np-calendar-body.dynamic {
|
|
292
|
+
box-sizing: content-box;
|
|
276
293
|
overflow: hidden;
|
|
277
294
|
height: calc(var(--np-calendar-head, 2.5rem) + var(--np-calendar-rows) * 3rem);
|
|
295
|
+
padding: 0 0.25rem 0.25rem;
|
|
296
|
+
margin: 0 -0.25rem -0.25rem;
|
|
278
297
|
}
|
|
279
298
|
|
|
280
299
|
.np-calendar.swipeable {
|
|
281
300
|
touch-action: pan-y;
|
|
282
301
|
}
|
|
283
302
|
|
|
284
|
-
.np-calendar-sr-only,
|
|
285
|
-
.np-calendar-head-hidden {
|
|
286
|
-
position: absolute;
|
|
287
|
-
width: 1px;
|
|
288
|
-
height: 1px;
|
|
289
|
-
padding: 0;
|
|
290
|
-
margin: -1px;
|
|
291
|
-
overflow: hidden;
|
|
292
|
-
clip-path: inset(50%);
|
|
293
|
-
white-space: nowrap;
|
|
294
|
-
border-width: 0;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
303
|
.np-calendar-grid {
|
|
298
304
|
display: table;
|
|
299
305
|
border-collapse: collapse;
|
|
@@ -352,6 +358,10 @@
|
|
|
352
358
|
vertical-align: middle;
|
|
353
359
|
}
|
|
354
360
|
|
|
361
|
+
.np-calendar-weekday-short {
|
|
362
|
+
display: block;
|
|
363
|
+
}
|
|
364
|
+
|
|
355
365
|
.np-calendar-weekday {
|
|
356
366
|
box-sizing: content-box;
|
|
357
367
|
height: 1.5rem;
|
|
@@ -406,9 +416,7 @@
|
|
|
406
416
|
}
|
|
407
417
|
|
|
408
418
|
.np-calendar-day:not(.between) .np-calendar-day-container {
|
|
409
|
-
transition:
|
|
410
|
-
background-color var(--np-motion-expressive-default-effects),
|
|
411
|
-
outline-color var(--np-motion-expressive-default-effects);
|
|
419
|
+
transition: background-color var(--np-motion-expressive-default-effects);
|
|
412
420
|
}
|
|
413
421
|
}
|
|
414
422
|
|
|
@@ -456,11 +464,6 @@
|
|
|
456
464
|
outline: none;
|
|
457
465
|
}
|
|
458
466
|
|
|
459
|
-
.np-calendar-day:focus-visible .np-calendar-day-container {
|
|
460
|
-
outline: 3px solid var(--np-color-secondary);
|
|
461
|
-
outline-offset: 2px;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
467
|
.np-calendar-cell.in-range::before,
|
|
465
468
|
.np-calendar-cell.range-start::before,
|
|
466
469
|
.np-calendar-cell.range-end::before {
|