noph-ui 0.51.2 → 0.52.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 +26 -1
- package/dist/animation.js +50 -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 +55 -20
- package/dist/button/ButtonGroup.svelte +139 -19
- package/dist/button/ButtonGroup.svelte.d.ts +1 -1
- package/dist/button/IconButton.svelte +49 -18
- package/dist/button/SegmentedButton.svelte +44 -4
- 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/checkbox/Checkbox.svelte +5 -0
- package/dist/chip/ChipSet.svelte +28 -2
- package/dist/chip/FilterChip.svelte +32 -4
- 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 +4 -2
- package/dist/date-picker/DatePickerDialog.svelte +1 -0
- package/dist/date-picker/DatePickerDialog.svelte.d.ts +1 -1
- package/dist/date-picker/DateRangePicker.svelte +1 -0
- package/dist/date-picker/DateRangePicker.svelte.d.ts +1 -1
- package/dist/date-picker/DockedDatePicker.svelte +12 -5
- package/dist/date-picker/DockedDatePicker.svelte.d.ts +1 -1
- package/dist/date-picker/DockedDateTimePicker.svelte +12 -5
- package/dist/date-picker/DockedDateTimePicker.svelte.d.ts +1 -1
- package/dist/date-picker/YearGrid.svelte +4 -2
- 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/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 +47 -0
- package/dist/internal/fieldTypes.d.ts +6 -0
- package/dist/internal/focus-ring.css +4 -0
- package/dist/internal/interest.css +3 -1
- package/dist/keyboard-nav.d.ts +12 -1
- package/dist/keyboard-nav.js +104 -14
- package/dist/list/Item.svelte +52 -6
- 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 +70 -18
- package/dist/menu/Menu.svelte.d.ts +2 -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 +29 -13
- package/dist/navigation-drawer/NavigationDrawer.svelte +96 -20
- package/dist/navigation-drawer/NavigationDrawer.svelte.d.ts +2 -1
- package/dist/navigation-drawer/NavigationDrawerItem.svelte +8 -3
- 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 +190 -53
- 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/progress/CircularProgress.svelte +2 -1
- package/dist/progress/LinearProgress.svelte +48 -20
- package/dist/progress/types.d.ts +1 -0
- package/dist/radio/Radio.svelte +7 -1
- package/dist/search/Search.svelte +245 -58
- package/dist/search/types.d.ts +4 -0
- package/dist/select/NativeSelect.svelte +20 -12
- package/dist/select/Option.svelte +1 -2
- package/dist/select/Select.svelte +59 -140
- package/dist/select/VirtualList.svelte +16 -1
- package/dist/select/VirtualList.svelte.d.ts +6 -2
- package/dist/sheet/Sheet.svelte +223 -5
- package/dist/sheet/Sheet.svelte.d.ts +3 -1
- package/dist/sheet/types.d.ts +10 -0
- package/dist/slider/Slider.svelte +1 -27
- package/dist/snackbar/Snackbar.svelte +3 -0
- package/dist/snackbar/Snackbar.svelte.d.ts +2 -1
- package/dist/switch/Switch.svelte +51 -11
- package/dist/tabs/Tab.svelte +28 -14
- package/dist/tabs/Tabs.svelte +28 -4
- package/dist/tabs/types.d.ts +3 -0
- package/dist/text-field/TextField.svelte +49 -13
- package/dist/time-picker/DockedTimePicker.svelte +6 -1
- package/dist/time-picker/DockedTimePicker.svelte.d.ts +1 -1
- package/dist/time-picker/TimePickerDialog.svelte +1 -0
- package/dist/time-picker/TimePickerDialog.svelte.d.ts +1 -1
- package/dist/toolbar/Toolbar.svelte +21 -11
- package/dist/toolbar/types.d.ts +1 -0
- package/dist/tooltip/RichTooltip.svelte.d.ts +1 -1
- package/dist/tooltip/Tooltip.svelte +3 -1
- package/dist/tooltip/Tooltip.svelte.d.ts +1 -1
- package/package.json +1 -1
package/dist/fab/Fab.svelte
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import '../internal/focus-ring.css'
|
|
3
|
-
import { pressMorph } from '../press.svelte.js'
|
|
4
3
|
import Ripple from '../ripple/Ripple.svelte'
|
|
5
4
|
import Tooltip from '../tooltip/Tooltip.svelte'
|
|
6
5
|
import type { HTMLButtonAttributes } from 'svelte/elements'
|
|
@@ -9,9 +8,8 @@
|
|
|
9
8
|
let {
|
|
10
9
|
variant = 'primary-container',
|
|
11
10
|
size = 's',
|
|
12
|
-
shape = '
|
|
11
|
+
shape = 'square',
|
|
13
12
|
lowered = false,
|
|
14
|
-
disabled = false,
|
|
15
13
|
icon,
|
|
16
14
|
label,
|
|
17
15
|
element = $bindable(),
|
|
@@ -20,16 +18,9 @@
|
|
|
20
18
|
|
|
21
19
|
const uid = $props.id()
|
|
22
20
|
|
|
23
|
-
let isLink = $derived(attributes.href != null
|
|
24
|
-
let tooltipId = $derived(label
|
|
25
|
-
|
|
26
|
-
const morph = pressMorph()
|
|
27
|
-
morph.supersededBy(() => shape)
|
|
28
|
-
|
|
29
|
-
const handlePress = () => {
|
|
30
|
-
if (disabled) return
|
|
31
|
-
morph.press()
|
|
32
|
-
}
|
|
21
|
+
let isLink = $derived(attributes.href != null)
|
|
22
|
+
let tooltipId = $derived(label ? uid : undefined)
|
|
23
|
+
let tooltipNames = $derived(!!tooltipId && !attributes['aria-label'])
|
|
33
24
|
|
|
34
25
|
let classes = $derived([
|
|
35
26
|
'np-fab',
|
|
@@ -38,15 +29,12 @@
|
|
|
38
29
|
size,
|
|
39
30
|
shape,
|
|
40
31
|
lowered && 'np-fab-lowered',
|
|
41
|
-
morph.pressed && 'pressed',
|
|
42
32
|
attributes.class,
|
|
43
33
|
])
|
|
44
34
|
</script>
|
|
45
35
|
|
|
46
36
|
{#snippet content()}
|
|
47
|
-
{
|
|
48
|
-
<Ripple forElement={element} />
|
|
49
|
-
{/if}
|
|
37
|
+
<Ripple forElement={element} />
|
|
50
38
|
{#if icon}
|
|
51
39
|
<span class="np-fab-icon">{@render icon()}</span>
|
|
52
40
|
{/if}
|
|
@@ -55,14 +43,10 @@
|
|
|
55
43
|
{#if isLink}
|
|
56
44
|
<a
|
|
57
45
|
{...attributes}
|
|
58
|
-
onclick={(event) => {
|
|
59
|
-
handlePress()
|
|
60
|
-
attributes.onclick?.(event)
|
|
61
|
-
}}
|
|
62
46
|
bind:this={element}
|
|
63
|
-
aria-describedby={tooltipId
|
|
47
|
+
aria-describedby={(!tooltipNames && tooltipId) || attributes['aria-describedby']}
|
|
64
48
|
interestfor={tooltipId ?? attributes['interestfor']}
|
|
65
|
-
aria-label={
|
|
49
|
+
aria-label={attributes['aria-label'] ?? label}
|
|
66
50
|
class={classes}
|
|
67
51
|
>
|
|
68
52
|
{@render content()}
|
|
@@ -70,16 +54,11 @@
|
|
|
70
54
|
{:else}
|
|
71
55
|
<button
|
|
72
56
|
{...attributes as HTMLButtonAttributes}
|
|
73
|
-
onclick={(event) => {
|
|
74
|
-
handlePress()
|
|
75
|
-
attributes.onclick?.(event)
|
|
76
|
-
}}
|
|
77
57
|
bind:this={element}
|
|
78
|
-
aria-describedby={tooltipId
|
|
58
|
+
aria-describedby={(!tooltipNames && tooltipId) || attributes['aria-describedby']}
|
|
79
59
|
interestfor={tooltipId ?? attributes['interestfor']}
|
|
80
|
-
aria-label={
|
|
60
|
+
aria-label={attributes['aria-label'] ?? label}
|
|
81
61
|
type={(attributes['type'] as HTMLButtonAttributes['type']) ?? 'button'}
|
|
82
|
-
{disabled}
|
|
83
62
|
class={classes}
|
|
84
63
|
>
|
|
85
64
|
{@render content()}
|
|
@@ -116,18 +95,11 @@
|
|
|
116
95
|
border-radius: var(--np-fab-shape, var(--_square-radius));
|
|
117
96
|
}
|
|
118
97
|
|
|
119
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
120
|
-
.round:not(:disabled):is(:active, .pressed) {
|
|
121
|
-
border-radius: var(--np-fab-pressed-shape, var(--_square-radius));
|
|
122
|
-
}
|
|
123
|
-
.square:not(:disabled):is(:active, .pressed) {
|
|
124
|
-
border-radius: var(--np-fab-pressed-shape, 50%);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
98
|
@media (prefers-reduced-motion: no-preference) {
|
|
129
99
|
.np-fab {
|
|
130
100
|
transition:
|
|
101
|
+
width var(--np-motion-expressive-default-spatial),
|
|
102
|
+
height var(--np-motion-expressive-default-spatial),
|
|
131
103
|
border-radius var(--np-motion-expressive-default-spatial),
|
|
132
104
|
box-shadow var(--np-motion-expressive-fast-effects),
|
|
133
105
|
background-color var(--np-motion-expressive-fast-effects);
|
|
@@ -183,21 +155,14 @@
|
|
|
183
155
|
}
|
|
184
156
|
|
|
185
157
|
@media (hover: hover) {
|
|
186
|
-
.np-fab:
|
|
158
|
+
.np-fab:hover {
|
|
187
159
|
box-shadow: var(--np-fab-elevation, var(--np-elevation-4));
|
|
188
160
|
}
|
|
189
|
-
.np-fab-lowered:
|
|
161
|
+
.np-fab-lowered:hover {
|
|
190
162
|
box-shadow: var(--np-fab-elevation, var(--np-elevation-2));
|
|
191
163
|
}
|
|
192
164
|
}
|
|
193
165
|
|
|
194
|
-
.np-fab:disabled {
|
|
195
|
-
cursor: default;
|
|
196
|
-
box-shadow: none;
|
|
197
|
-
background-color: color-mix(in srgb, var(--np-color-on-surface) 12%, transparent);
|
|
198
|
-
color: color-mix(in srgb, var(--np-color-on-surface) 38%, transparent);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
166
|
.np-fab-icon {
|
|
202
167
|
display: flex;
|
|
203
168
|
fill: currentColor;
|
package/dist/fab/FabMenu.svelte
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import
|
|
2
|
+
import '../internal/exit.css'
|
|
3
|
+
import { exitAnimation } from '../animation.js'
|
|
3
4
|
import CloseIcon from '../icons/CloseIcon.svelte'
|
|
4
|
-
import { arrowKeyNav, rovingTabindex } from '../keyboard-nav.js'
|
|
5
|
+
import { arrowKeyNav, focusableItems, rovingTabindex, typeahead } from '../keyboard-nav.js'
|
|
5
6
|
import { popoverController, syncOpenEffect } from '../popover.svelte.js'
|
|
6
|
-
import { PRESS_DURATION } from '../press.svelte.js'
|
|
7
|
-
import { onMount } from 'svelte'
|
|
8
7
|
import Fab from './Fab.svelte'
|
|
9
8
|
import type { FabMenuProps } from './types.js'
|
|
10
9
|
|
|
@@ -16,7 +15,6 @@
|
|
|
16
15
|
variant = 'primary-container',
|
|
17
16
|
size = 's',
|
|
18
17
|
placement = 'block-start',
|
|
19
|
-
closeOnSelect = true,
|
|
20
18
|
open = $bindable(false),
|
|
21
19
|
element = $bindable(),
|
|
22
20
|
...attributes
|
|
@@ -28,38 +26,33 @@
|
|
|
28
26
|
|
|
29
27
|
let menuElement: HTMLDivElement | undefined = $state()
|
|
30
28
|
|
|
29
|
+
let colorSet = $derived(variant.replace('-container', '') as 'primary' | 'secondary' | 'tertiary')
|
|
30
|
+
|
|
31
31
|
const ITEMS = 'button, a[href], [role="menuitem"]'
|
|
32
32
|
const attach = rovingTabindex(ITEMS)
|
|
33
33
|
let arrowHandler = $derived(
|
|
34
34
|
arrowKeyNav(ITEMS, placement.startsWith('inline') ? 'horizontal' : 'vertical'),
|
|
35
35
|
)
|
|
36
|
+
const typeaheadHandler = typeahead(
|
|
37
|
+
ITEMS,
|
|
38
|
+
(item) => (item.querySelector('.children-wrapper') ?? item).textContent ?? '',
|
|
39
|
+
)
|
|
36
40
|
|
|
37
41
|
const controller = popoverController(() => menuElement)
|
|
38
42
|
|
|
39
43
|
export const show = () => controller.show()
|
|
40
44
|
|
|
41
|
-
export const close = () =>
|
|
42
|
-
clearTimeout(closeTimeout)
|
|
43
|
-
controller.close()
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
let closeTimeout: ReturnType<typeof setTimeout>
|
|
45
|
+
export const close = () => controller.close()
|
|
47
46
|
|
|
48
|
-
const
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
const openWithArrow = (event: KeyboardEvent) => {
|
|
48
|
+
if (!menuElement || (event.key !== 'ArrowDown' && event.key !== 'ArrowUp')) return
|
|
49
|
+
event.preventDefault()
|
|
50
|
+
show()
|
|
51
|
+
focusableItems(menuElement, ITEMS)
|
|
52
|
+
.at(event.key === 'ArrowDown' ? 0 : -1)
|
|
53
|
+
?.focus()
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
onMount(() => {
|
|
58
|
-
return () => {
|
|
59
|
-
clearTimeout(closeTimeout)
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
|
|
63
56
|
syncOpenEffect(
|
|
64
57
|
() => menuElement,
|
|
65
58
|
() => open,
|
|
@@ -83,19 +76,26 @@
|
|
|
83
76
|
{...attributes}
|
|
84
77
|
bind:this={element}
|
|
85
78
|
style="anchor-name: {anchorName}; {attributes.style ?? ''}"
|
|
86
|
-
class={[
|
|
79
|
+
class={[
|
|
80
|
+
'np-fab-menu',
|
|
81
|
+
`np-fab-menu-${placement}`,
|
|
82
|
+
`np-fab-menu-${size}`,
|
|
83
|
+
`np-fab-menu-set-${colorSet}`,
|
|
84
|
+
attributes.class,
|
|
85
|
+
]}
|
|
87
86
|
>
|
|
88
87
|
<Fab
|
|
89
|
-
{variant}
|
|
90
|
-
{size}
|
|
88
|
+
variant={open ? colorSet : variant}
|
|
89
|
+
size={open ? 's' : size}
|
|
90
|
+
shape={open ? 'round' : undefined}
|
|
91
91
|
{label}
|
|
92
|
-
shape={open ? 'square' : 'round'}
|
|
93
92
|
command="toggle-popover"
|
|
94
93
|
commandfor={menuId}
|
|
95
94
|
aria-haspopup="menu"
|
|
96
95
|
aria-expanded={open}
|
|
97
96
|
class="np-fab-menu-trigger"
|
|
98
97
|
icon={triggerIcon}
|
|
98
|
+
onkeydown={openWithArrow}
|
|
99
99
|
/>
|
|
100
100
|
|
|
101
101
|
<div
|
|
@@ -108,11 +108,10 @@
|
|
|
108
108
|
aria-label={label}
|
|
109
109
|
class="np-fab-menu-list"
|
|
110
110
|
{@attach attach}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (target.closest(ITEMS)) closeAfterPress()
|
|
111
|
+
{@attach exitAnimation}
|
|
112
|
+
onkeydown={(event) => {
|
|
113
|
+
arrowHandler(event)
|
|
114
|
+
if (!event.defaultPrevented) typeaheadHandler(event)
|
|
116
115
|
}}
|
|
117
116
|
ontoggle={(event) => {
|
|
118
117
|
open = event.newState === 'open'
|
|
@@ -126,6 +125,35 @@
|
|
|
126
125
|
.np-fab-menu {
|
|
127
126
|
position: relative;
|
|
128
127
|
display: inline-flex;
|
|
128
|
+
width: var(--_size);
|
|
129
|
+
height: var(--_size);
|
|
130
|
+
}
|
|
131
|
+
.np-fab-menu-s {
|
|
132
|
+
--_size: 3.5rem;
|
|
133
|
+
}
|
|
134
|
+
.np-fab-menu-m {
|
|
135
|
+
--_size: 5rem;
|
|
136
|
+
}
|
|
137
|
+
.np-fab-menu-l {
|
|
138
|
+
--_size: 6rem;
|
|
139
|
+
}
|
|
140
|
+
.np-fab-menu > :global(.np-fab.np-fab-menu-trigger) {
|
|
141
|
+
position: absolute;
|
|
142
|
+
inset-block-start: 0;
|
|
143
|
+
inset-inline-end: 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.np-fab-menu-set-primary {
|
|
147
|
+
--np-tonal-button-container-color: var(--np-color-primary-container);
|
|
148
|
+
--np-tonal-button-label-text-color: var(--np-color-on-primary-container);
|
|
149
|
+
}
|
|
150
|
+
.np-fab-menu-set-secondary {
|
|
151
|
+
--np-tonal-button-container-color: var(--np-color-secondary-container);
|
|
152
|
+
--np-tonal-button-label-text-color: var(--np-color-on-secondary-container);
|
|
153
|
+
}
|
|
154
|
+
.np-fab-menu-set-tertiary {
|
|
155
|
+
--np-tonal-button-container-color: var(--np-color-tertiary-container);
|
|
156
|
+
--np-tonal-button-label-text-color: var(--np-color-on-tertiary-container);
|
|
129
157
|
}
|
|
130
158
|
|
|
131
159
|
.np-fab-menu-icons {
|
|
@@ -152,49 +180,79 @@
|
|
|
152
180
|
|
|
153
181
|
.np-fab-menu-list {
|
|
154
182
|
position: absolute;
|
|
183
|
+
box-sizing: border-box;
|
|
184
|
+
max-height: 100%;
|
|
155
185
|
margin: 0;
|
|
156
|
-
padding: 0;
|
|
186
|
+
padding: 0.5rem;
|
|
157
187
|
border: none;
|
|
158
188
|
background: none;
|
|
159
189
|
flex-direction: column;
|
|
160
190
|
align-items: flex-end;
|
|
161
191
|
gap: 0.25rem;
|
|
162
|
-
overflow:
|
|
192
|
+
overflow: auto;
|
|
193
|
+
scrollbar-width: none;
|
|
163
194
|
}
|
|
164
195
|
|
|
165
196
|
.np-fab-menu-list:popover-open {
|
|
166
197
|
display: flex;
|
|
167
198
|
}
|
|
199
|
+
.np-fab-menu-list {
|
|
200
|
+
--np-exit-display: flex;
|
|
201
|
+
}
|
|
202
|
+
.np-fab-menu-list > :global(:focus-visible) {
|
|
203
|
+
z-index: 1;
|
|
204
|
+
}
|
|
168
205
|
|
|
169
206
|
.np-fab-menu-block-start .np-fab-menu-list {
|
|
170
|
-
position-area: block-start;
|
|
171
|
-
margin-block-end: 0.5rem;
|
|
172
|
-
flex-direction: column-reverse;
|
|
207
|
+
position-area: block-start span-inline-start;
|
|
173
208
|
}
|
|
174
209
|
.np-fab-menu-block-end .np-fab-menu-list {
|
|
175
|
-
position-area: block-end;
|
|
176
|
-
margin-block-start: 0.5rem;
|
|
210
|
+
position-area: block-end span-inline-start;
|
|
177
211
|
}
|
|
178
212
|
.np-fab-menu-inline-start .np-fab-menu-list {
|
|
179
213
|
position-area: inline-start;
|
|
180
|
-
margin-inline-end: 0.5rem;
|
|
181
|
-
flex-direction: row-reverse;
|
|
182
|
-
align-items: center;
|
|
183
214
|
}
|
|
184
215
|
.np-fab-menu-inline-end .np-fab-menu-list {
|
|
185
216
|
position-area: inline-end;
|
|
186
|
-
|
|
217
|
+
}
|
|
218
|
+
:is(.np-fab-menu-block-start, .np-fab-menu-block-end) .np-fab-menu-list {
|
|
219
|
+
margin-inline-end: -0.5rem;
|
|
220
|
+
}
|
|
221
|
+
:is(.np-fab-menu-inline-start, .np-fab-menu-inline-end) .np-fab-menu-list {
|
|
187
222
|
flex-direction: row;
|
|
188
223
|
align-items: center;
|
|
189
224
|
}
|
|
190
225
|
|
|
191
226
|
@media (prefers-reduced-motion: no-preference) {
|
|
227
|
+
.np-fab-menu-list {
|
|
228
|
+
opacity: 0;
|
|
229
|
+
transition:
|
|
230
|
+
opacity var(--np-motion-expressive-fast-effects),
|
|
231
|
+
display var(--np-motion-expressive-fast-effects) allow-discrete,
|
|
232
|
+
overlay var(--np-motion-expressive-fast-effects) allow-discrete;
|
|
233
|
+
}
|
|
234
|
+
.np-fab-menu-list:popover-open {
|
|
235
|
+
opacity: 1;
|
|
236
|
+
}
|
|
192
237
|
.np-fab-menu-list:popover-open > :global(*) {
|
|
193
238
|
--_stagger-window: 210ms;
|
|
194
239
|
--_delay: calc((sibling-index() - 1) / sibling-count() * var(--_stagger-window));
|
|
195
240
|
animation: np-fab-menu-item-in var(--np-motion-expressive-default-spatial) both;
|
|
196
241
|
animation-delay: var(--_delay);
|
|
197
242
|
}
|
|
243
|
+
.np-fab-menu-list:popover-open > :global(:focus-visible) {
|
|
244
|
+
animation:
|
|
245
|
+
np-fab-menu-item-in var(--np-motion-expressive-default-spatial) both,
|
|
246
|
+
focusAnimation var(--np-motion-expressive-slow-effects) forwards;
|
|
247
|
+
animation-delay: var(--_delay), 0s;
|
|
248
|
+
}
|
|
249
|
+
:is(.np-fab-menu-block-start, .np-fab-menu-inline-start)
|
|
250
|
+
.np-fab-menu-list:popover-open
|
|
251
|
+
> :global(*) {
|
|
252
|
+
--_delay: calc(
|
|
253
|
+
(sibling-count() - sibling-index()) / sibling-count() * var(--_stagger-window)
|
|
254
|
+
);
|
|
255
|
+
}
|
|
198
256
|
}
|
|
199
257
|
|
|
200
258
|
@keyframes np-fab-menu-item-in {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import '../internal/exit.css';
|
|
1
2
|
import type { FabMenuProps } from './types.js';
|
|
2
3
|
declare const FabMenu: import("svelte").Component<FabMenuProps, {
|
|
3
4
|
show: () => void;
|
|
4
5
|
close: () => void;
|
|
5
|
-
}, "
|
|
6
|
+
}, "open" | "element">;
|
|
6
7
|
type FabMenu = ReturnType<typeof FabMenu>;
|
|
7
8
|
export default FabMenu;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Button from '../button/Button.svelte'
|
|
3
|
+
import type { FabMenuItemProps } from './types.js'
|
|
4
|
+
|
|
5
|
+
let { icon, element = $bindable(), ...attributes }: FabMenuItemProps = $props()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<Button {...attributes} bind:element role="menuitem" variant="tonal" size="m" start={icon} />
|
package/dist/fab/index.d.ts
CHANGED
package/dist/fab/index.js
CHANGED
package/dist/fab/types.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import type { ButtonElement } from '../button/types.js';
|
|
1
|
+
import type { ButtonElement, ButtonProps } from '../button/types.js';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAnchorAttributes, HTMLAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
|
4
4
|
export type FabElement = ButtonElement;
|
|
5
|
-
interface BaseFabProps extends HTMLAttributes<FabElement>, Omit<HTMLButtonAttributes, keyof HTMLAttributes<HTMLButtonElement> | 'type'>, Omit<HTMLAnchorAttributes, keyof HTMLAttributes<HTMLAnchorElement> | 'type'> {
|
|
5
|
+
interface BaseFabProps extends HTMLAttributes<FabElement>, Omit<HTMLButtonAttributes, keyof HTMLAttributes<HTMLButtonElement> | 'type' | 'disabled'>, Omit<HTMLAnchorAttributes, keyof HTMLAttributes<HTMLAnchorElement> | 'type'> {
|
|
6
6
|
element?: FabElement;
|
|
7
7
|
variant?: 'primary' | 'secondary' | 'tertiary' | 'primary-container' | 'secondary-container' | 'tertiary-container';
|
|
8
8
|
size?: 's' | 'm' | 'l';
|
|
9
9
|
shape?: 'round' | 'square';
|
|
10
10
|
lowered?: boolean;
|
|
11
|
-
disabled?: boolean | null;
|
|
12
11
|
type?: 'submit' | 'reset' | 'button' | (string & {}) | null;
|
|
13
12
|
}
|
|
14
13
|
export interface FabProps extends BaseFabProps {
|
|
@@ -20,6 +19,10 @@ export interface ExtendedFabProps extends BaseFabProps {
|
|
|
20
19
|
label?: string;
|
|
21
20
|
collapsed?: boolean;
|
|
22
21
|
}
|
|
22
|
+
export interface FabMenuItemProps extends Omit<ButtonProps, 'variant' | 'size' | 'start' | 'end' | 'toggle' | 'selected' | 'role'> {
|
|
23
|
+
/** Leading icon. Keep it, it tells the actions apart at a glance. */
|
|
24
|
+
icon?: Snippet;
|
|
25
|
+
}
|
|
23
26
|
export interface FabMenuProps extends HTMLAttributes<HTMLDivElement> {
|
|
24
27
|
label?: string;
|
|
25
28
|
icon?: Snippet;
|
|
@@ -28,7 +31,6 @@ export interface FabMenuProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
28
31
|
size?: FabProps['size'];
|
|
29
32
|
placement?: 'block-start' | 'block-end' | 'inline-start' | 'inline-end';
|
|
30
33
|
open?: boolean;
|
|
31
|
-
closeOnSelect?: boolean;
|
|
32
34
|
element?: HTMLDivElement;
|
|
33
35
|
}
|
|
34
36
|
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
let {
|
|
3
|
+
height = 24,
|
|
4
|
+
width = 24,
|
|
5
|
+
}: {
|
|
6
|
+
height?: number
|
|
7
|
+
width?: number
|
|
8
|
+
} = $props()
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<svg xmlns="http://www.w3.org/2000/svg" {height} viewBox="0 -960 960 960" {width}
|
|
12
|
+
><path d="M120-240v-80h720v80H120Zm0-200v-80h720v80H120Zm0-200v-80h720v80H120Z" /></svg
|
|
13
|
+
>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
let {
|
|
3
|
+
height = 24,
|
|
4
|
+
width = 24,
|
|
5
|
+
}: {
|
|
6
|
+
height?: number
|
|
7
|
+
width?: number
|
|
8
|
+
} = $props()
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<svg xmlns="http://www.w3.org/2000/svg" {height} viewBox="0 -960 960 960" {width}
|
|
12
|
+
><path
|
|
13
|
+
d="M120-240v-80h520v80H120Zm664-40L584-480l200-200 56 56-144 144 144 144-56 56ZM120-440v-80h400v80H120Zm0-200v-80h520v80H120Z"
|
|
14
|
+
/></svg
|
|
15
|
+
>
|
package/dist/icons/index.d.ts
CHANGED
|
@@ -9,5 +9,7 @@ export { default as CloseIcon } from './CloseIcon.svelte';
|
|
|
9
9
|
export { default as EditCalendarIcon } from './EditCalendarIcon.svelte';
|
|
10
10
|
export { default as Icon } from './Icon.svelte';
|
|
11
11
|
export { default as KeyboardIcon } from './KeyboardIcon.svelte';
|
|
12
|
+
export { default as MenuIcon } from './MenuIcon.svelte';
|
|
13
|
+
export { default as MenuOpenIcon } from './MenuOpenIcon.svelte';
|
|
12
14
|
export { default as ScheduleIcon } from './ScheduleIcon.svelte';
|
|
13
15
|
export { default as SearchIcon } from './SearchIcon.svelte';
|
package/dist/icons/index.js
CHANGED
|
@@ -9,5 +9,7 @@ export { default as CloseIcon } from './CloseIcon.svelte';
|
|
|
9
9
|
export { default as EditCalendarIcon } from './EditCalendarIcon.svelte';
|
|
10
10
|
export { default as Icon } from './Icon.svelte';
|
|
11
11
|
export { default as KeyboardIcon } from './KeyboardIcon.svelte';
|
|
12
|
+
export { default as MenuIcon } from './MenuIcon.svelte';
|
|
13
|
+
export { default as MenuOpenIcon } from './MenuOpenIcon.svelte';
|
|
12
14
|
export { default as ScheduleIcon } from './ScheduleIcon.svelte';
|
|
13
15
|
export { default as SearchIcon } from './SearchIcon.svelte';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* Browsers without an `overlay` transition, such as Safari, drop a closing dialog or popover from
|
|
2
|
+
the top layer at once, so its exit animation would never show. While it animates out it carries
|
|
3
|
+
data-np-exiting (see exitAnimation in animation.ts) and these rules keep it shown, over the page
|
|
4
|
+
but not blocking it. Browsers with the transition keep it in the top layer themselves. */
|
|
5
|
+
@supports not (overlay: auto) {
|
|
6
|
+
/* Important, as each component hides its closed state with a rule of its own, scoped and so
|
|
7
|
+
more specific than this one. It only ever holds for the moment of leaving. */
|
|
8
|
+
[popover][data-np-exiting]:not(:popover-open),
|
|
9
|
+
dialog[data-np-exiting]:not([open]) {
|
|
10
|
+
display: var(--np-exit-display, block) !important;
|
|
11
|
+
z-index: 1000 !important;
|
|
12
|
+
pointer-events: none !important;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* A closed dialog is no longer :modal and would lose its place. Components that place their
|
|
16
|
+
dialog themselves win over this. */
|
|
17
|
+
:where(dialog[data-np-exiting]:not([open])) {
|
|
18
|
+
position: fixed;
|
|
19
|
+
inset-block: 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* Its ::backdrop is gone as well, so a dialog with a scrim draws one of its own that fades: a
|
|
23
|
+
wide shadow around it, and one inside for a dialog whose box is transparent, as it sits under
|
|
24
|
+
the content. A shadow rather than a pseudo element covers the screen even while the dialog
|
|
25
|
+
moves. A dialog that is its own surface turns the inner one off with
|
|
26
|
+
--np-exit-scrim-inner: 0 0 transparent. */
|
|
27
|
+
dialog.np-exit-scrim[data-np-exiting]:not([open]) {
|
|
28
|
+
--np-exit-scrim-color: color-mix(in srgb, var(--np-color-scrim) 32%, transparent);
|
|
29
|
+
box-shadow:
|
|
30
|
+
0 0 0 100vmax var(--np-exit-scrim-color),
|
|
31
|
+
var(--np-exit-scrim-inner, inset 0 0 0 100vmax var(--np-exit-scrim-color));
|
|
32
|
+
animation: np-exit-scrim var(--np-exit-scrim-motion, var(--np-motion-expressive-slow-effects))
|
|
33
|
+
forwards;
|
|
34
|
+
}
|
|
35
|
+
@keyframes np-exit-scrim {
|
|
36
|
+
to {
|
|
37
|
+
--np-exit-scrim-color: transparent;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Registered, so the scrim's colour can fade. */
|
|
43
|
+
@property --np-exit-scrim-color {
|
|
44
|
+
syntax: '<color>';
|
|
45
|
+
inherits: false;
|
|
46
|
+
initial-value: transparent;
|
|
47
|
+
}
|
|
@@ -7,6 +7,12 @@ export interface FieldProps {
|
|
|
7
7
|
issues?: Issue[];
|
|
8
8
|
prefixText?: string;
|
|
9
9
|
suffixText?: string;
|
|
10
|
+
/** Spoken in place of `prefixText`, for example "Euro" for "€". */
|
|
11
|
+
prefixLabel?: string;
|
|
12
|
+
/** Spoken in place of `suffixText`, for example "at gmail dot com". */
|
|
13
|
+
suffixLabel?: string;
|
|
14
|
+
/** Spoken before the character counter. */
|
|
15
|
+
counterLabel?: string;
|
|
10
16
|
variant?: 'outlined' | 'filled';
|
|
11
17
|
start?: Snippet;
|
|
12
18
|
end?: Snippet;
|
|
@@ -31,6 +31,10 @@
|
|
|
31
31
|
outline-width: 3px;
|
|
32
32
|
outline-offset: 2px;
|
|
33
33
|
}
|
|
34
|
+
/* The focused state layer, on top of the ring. */
|
|
35
|
+
.np-focus-ring:focus-visible .np-ripple-surface::before {
|
|
36
|
+
opacity: var(--np-ripple-focus-opacity, 0.1);
|
|
37
|
+
}
|
|
34
38
|
@media (prefers-reduced-motion: no-preference) {
|
|
35
39
|
.np-focus-ring:focus-visible {
|
|
36
40
|
animation: focusAnimation var(--np-motion-expressive-slow-effects) forwards;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/* A tooltip shows at once and lingers a little. Its anchor either points at it with
|
|
2
|
+
aria-describedby or, when the tooltip text is the anchor's name, is followed by it. */
|
|
3
|
+
[interestfor]:is([aria-describedby], :has(+ [role='tooltip'])) {
|
|
2
4
|
interest-delay-start: 0s;
|
|
3
5
|
interest-delay-end: 500ms;
|
|
4
6
|
}
|
package/dist/keyboard-nav.d.ts
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import type { Attachment } from 'svelte/attachments';
|
|
2
|
+
export declare const focusableItems: (node: ParentNode, itemSelector: string) => HTMLElement[];
|
|
3
|
+
export declare const focusedItem: (node: HTMLElement, itemSelector: string, items: HTMLElement[]) => HTMLElement | null;
|
|
2
4
|
export declare const rovingTabindex: (itemSelector: string, options?: {
|
|
3
5
|
currentAttr?: string;
|
|
4
6
|
currentValue?: string;
|
|
7
|
+
/** Picks the current item by selector instead of `currentAttr` and `currentValue`. */
|
|
8
|
+
current?: string;
|
|
5
9
|
}) => Attachment<HTMLElement>;
|
|
6
|
-
export declare const arrowKeyNav: (itemSelector: string, orientation?: "vertical" | "horizontal", { wrap }?: {
|
|
10
|
+
export declare const arrowKeyNav: (itemSelector: string, orientation?: "vertical" | "horizontal" | "both", { wrap }?: {
|
|
7
11
|
wrap?: boolean;
|
|
8
12
|
}) => (event: KeyboardEvent & {
|
|
9
13
|
currentTarget: EventTarget & HTMLElement;
|
|
10
14
|
}) => void;
|
|
15
|
+
export declare const typeaheadBuffer: (timeout?: number) => (event: KeyboardEvent) => string | undefined;
|
|
16
|
+
export declare const typeaheadMatch: (labels: string[], current: number, query: string) => number;
|
|
17
|
+
export declare const typeahead: (itemSelector: string, labelOf: (item: HTMLElement) => string, { timeout }?: {
|
|
18
|
+
timeout?: number;
|
|
19
|
+
}) => (event: KeyboardEvent & {
|
|
20
|
+
currentTarget: EventTarget & HTMLElement;
|
|
21
|
+
}) => void;
|