noph-ui 0.43.1 → 0.45.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/README.md +10 -1
- package/dist/animation.d.ts +17 -0
- package/dist/animation.js +48 -0
- package/dist/app-bar/AppBar.svelte +280 -0
- package/dist/app-bar/AppBar.svelte.d.ts +4 -0
- package/dist/app-bar/index.d.ts +1 -0
- package/dist/app-bar/index.js +1 -0
- package/dist/app-bar/types.d.ts +35 -0
- package/dist/app-bar/types.js +1 -0
- package/dist/autocomplete/AutoComplete.svelte +10 -11
- package/dist/autocomplete/AutoComplete.svelte.d.ts +1 -1
- package/dist/autocomplete/types.d.ts +1 -1
- package/dist/badge/Badge.svelte +11 -1
- package/dist/badge/Badge.svelte.d.ts +2 -5
- package/dist/badge/types.d.ts +5 -0
- package/dist/badge/types.js +1 -0
- package/dist/button/Button.svelte +5 -15
- package/dist/button/IconButton.svelte +5 -15
- package/dist/button/SegmentedButton.svelte +15 -1
- package/dist/button/SplitButton.svelte +92 -0
- package/dist/button/SplitButton.svelte.d.ts +4 -0
- package/dist/button/index.d.ts +1 -0
- package/dist/button/index.js +1 -0
- package/dist/button/types.d.ts +23 -4
- package/dist/card/Card.svelte +1 -1
- package/dist/card/types.d.ts +1 -1
- package/dist/checkbox/Checkbox.svelte +50 -58
- package/dist/chip/AssistChip.svelte +5 -5
- package/dist/chip/ChipSet.svelte +3 -10
- package/dist/chip/ChipSet.svelte.d.ts +1 -1
- package/dist/chip/FilterChip.svelte +35 -27
- package/dist/chip/FilterChip.svelte.d.ts +1 -1
- package/dist/chip/InputChip.svelte +13 -2
- package/dist/chip/SuggestionChip.svelte +29 -0
- package/dist/chip/SuggestionChip.svelte.d.ts +4 -0
- package/dist/chip/index.d.ts +1 -0
- package/dist/chip/index.js +1 -0
- package/dist/chip/types.d.ts +26 -10
- package/dist/date-picker/Calendar.svelte +1 -1
- package/dist/date-picker/DatePickerDialog.svelte +30 -8
- package/dist/date-picker/DatePickerDialog.svelte.d.ts +4 -1
- package/dist/date-picker/DateRangePicker.svelte +45 -10
- package/dist/date-picker/DateRangePicker.svelte.d.ts +4 -1
- package/dist/date-picker/DockedDatePicker.svelte +18 -4
- package/dist/date-picker/DockedDatePicker.svelte.d.ts +4 -1
- package/dist/date-picker/DockedDateTimePicker.svelte +18 -4
- package/dist/date-picker/DockedDateTimePicker.svelte.d.ts +4 -1
- package/dist/date-picker/SelectionList.svelte +6 -32
- package/dist/date-picker/SelectionList.svelte.d.ts +2 -12
- package/dist/date-picker/TimeColumn.svelte +4 -29
- package/dist/date-picker/exitVisibility.svelte.d.ts +10 -0
- package/dist/date-picker/exitVisibility.svelte.js +30 -0
- package/dist/date-picker/optionList.d.ts +16 -0
- package/dist/date-picker/optionList.js +43 -0
- package/dist/date-picker/types.d.ts +11 -4
- package/dist/dialog/Dialog.svelte +77 -68
- package/dist/dialog/Dialog.svelte.d.ts +3 -3
- package/dist/dialog/types.d.ts +5 -3
- package/dist/divider/Divider.svelte +6 -2
- package/dist/divider/Divider.svelte.d.ts +1 -1
- package/dist/divider/types.d.ts +1 -0
- package/dist/fab/ExtendedFab.svelte +281 -0
- package/dist/fab/ExtendedFab.svelte.d.ts +5 -0
- package/dist/fab/Fab.svelte +239 -0
- package/dist/fab/Fab.svelte.d.ts +5 -0
- package/dist/fab/FabMenu.svelte +255 -0
- package/dist/fab/FabMenu.svelte.d.ts +7 -0
- package/dist/fab/index.d.ts +3 -0
- package/dist/fab/index.js +3 -0
- package/dist/fab/types.d.ts +58 -0
- package/dist/fab/types.js +1 -0
- package/dist/icons/ArrowBackIcon.svelte +13 -0
- package/dist/icons/ArrowBackIcon.svelte.d.ts +7 -0
- package/dist/icons/ChevronDownIcon.svelte +3 -0
- package/dist/icons/ChevronDownIcon.svelte.d.ts +26 -0
- package/dist/icons/Icon.svelte +1 -6
- package/dist/icons/Icon.svelte.d.ts +1 -6
- package/dist/icons/SearchIcon.svelte +15 -0
- package/dist/icons/SearchIcon.svelte.d.ts +7 -0
- package/dist/icons/index.d.ts +3 -0
- package/dist/icons/index.js +3 -0
- package/dist/icons/types.d.ts +6 -0
- package/dist/icons/types.js +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/internal/focus-ring.css +12 -0
- package/dist/list/Item.svelte +5 -0
- package/dist/list/Item.svelte.d.ts +1 -1
- package/dist/list/ListItem.svelte +2 -2
- package/dist/list/ListItem.svelte.d.ts +1 -1
- package/dist/list/types.d.ts +1 -0
- package/dist/loading-indicator/LoadingIndicator.svelte +7 -2
- package/dist/loading-indicator/LoadingIndicator.svelte.d.ts +1 -1
- package/dist/loading-indicator/types.d.ts +3 -2
- package/dist/menu/Menu.svelte +13 -8
- package/dist/menu/Menu.svelte.d.ts +2 -2
- package/dist/menu/MenuItem.svelte +2 -2
- package/dist/menu/MenuItem.svelte.d.ts +1 -1
- package/dist/menu/types.d.ts +0 -2
- package/dist/navigation-bar/NavigationBar.svelte +66 -0
- package/dist/navigation-bar/NavigationBar.svelte.d.ts +4 -0
- package/dist/navigation-bar/NavigationBarItem.svelte +261 -0
- package/dist/navigation-bar/NavigationBarItem.svelte.d.ts +5 -0
- package/dist/navigation-bar/index.d.ts +2 -0
- package/dist/navigation-bar/index.js +2 -0
- package/dist/navigation-bar/types.d.ts +29 -0
- package/dist/navigation-bar/types.js +1 -0
- package/dist/navigation-drawer/NavigationDrawer.svelte +128 -76
- package/dist/navigation-drawer/NavigationDrawer.svelte.d.ts +4 -1
- package/dist/navigation-drawer/NavigationDrawerItem.svelte +13 -3
- package/dist/navigation-drawer/NavigationDrawerItem.svelte.d.ts +1 -1
- package/dist/navigation-drawer/types.d.ts +7 -1
- package/dist/navigation-rail/NavigationRail.svelte +9 -3
- package/dist/navigation-rail/NavigationRail.svelte.d.ts +1 -1
- package/dist/navigation-rail/NavigationRailItem.svelte +25 -1
- package/dist/navigation-rail/NavigationRailItem.svelte.d.ts +1 -1
- package/dist/navigation-rail/types.d.ts +7 -1
- package/dist/popover.svelte.d.ts +14 -0
- package/dist/popover.svelte.js +31 -0
- package/dist/press.svelte.d.ts +19 -0
- package/dist/press.svelte.js +45 -0
- package/dist/progress/CircularProgress.svelte +4 -1
- package/dist/progress/CircularProgress.svelte.d.ts +1 -1
- package/dist/progress/LinearProgress.svelte +9 -1
- package/dist/progress/LinearProgress.svelte.d.ts +1 -1
- package/dist/progress/types.d.ts +3 -2
- package/dist/radio/Radio.svelte +26 -7
- package/dist/radio/types.d.ts +3 -0
- package/dist/search/Search.svelte +472 -0
- package/dist/search/Search.svelte.d.ts +5 -0
- package/dist/search/index.d.ts +1 -0
- package/dist/search/index.js +1 -0
- package/dist/search/types.d.ts +39 -0
- package/dist/search/types.js +1 -0
- package/dist/select/NativeSelect.svelte +13 -16
- package/dist/select/NativeSelect.svelte.d.ts +2 -12
- package/dist/select/Option.svelte +1 -7
- package/dist/select/Option.svelte.d.ts +1 -6
- package/dist/select/Select.svelte +48 -87
- package/dist/select/Select.svelte.d.ts +1 -1
- package/dist/select/types.d.ts +15 -1
- package/dist/sheet/Sheet.svelte +260 -0
- package/dist/sheet/Sheet.svelte.d.ts +7 -0
- package/dist/sheet/index.d.ts +1 -0
- package/dist/sheet/index.js +1 -0
- package/dist/sheet/types.d.ts +19 -0
- package/dist/sheet/types.js +1 -0
- package/dist/slider/Slider.svelte +154 -30
- package/dist/slider/Slider.svelte.d.ts +1 -1
- package/dist/slider/types.d.ts +3 -0
- package/dist/snackbar/Snackbar.svelte +48 -37
- package/dist/snackbar/Snackbar.svelte.d.ts +2 -2
- package/dist/snackbar/types.d.ts +3 -2
- package/dist/switch/Switch.svelte +51 -20
- package/dist/switch/types.d.ts +3 -0
- package/dist/tabs/Tab.svelte +8 -12
- package/dist/tabs/Tabs.svelte +3 -3
- package/dist/tabs/Tabs.svelte.d.ts +1 -1
- package/dist/text-field/TextField.svelte +19 -12
- package/dist/text-field/TextField.svelte.d.ts +1 -1
- package/dist/toolbar/Toolbar.svelte +133 -0
- package/dist/toolbar/Toolbar.svelte.d.ts +4 -0
- package/dist/toolbar/index.d.ts +1 -0
- package/dist/toolbar/index.js +1 -0
- package/dist/toolbar/types.d.ts +15 -0
- package/dist/toolbar/types.js +1 -0
- package/dist/tooltip/RichTooltip.svelte +25 -12
- package/dist/tooltip/RichTooltip.svelte.d.ts +2 -2
- package/dist/tooltip/Tooltip.svelte +22 -11
- package/dist/tooltip/Tooltip.svelte.d.ts +4 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.js +8 -0
- package/package.json +13 -13
- package/dist/date-picker/enterAnimation.d.ts +0 -1
- package/dist/date-picker/enterAnimation.js +0 -10
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import '../internal/focus-ring.css'
|
|
3
|
+
import { pressMorph } from '../press.svelte.js'
|
|
3
4
|
import CircularProgress from '../progress/CircularProgress.svelte'
|
|
4
5
|
import Ripple from '../ripple/Ripple.svelte'
|
|
5
6
|
import Tooltip from '../tooltip/Tooltip.svelte'
|
|
6
|
-
import { onMount } from 'svelte'
|
|
7
7
|
import type { HTMLButtonAttributes } from 'svelte/elements'
|
|
8
8
|
import type { IconButtonProps } from './types.js'
|
|
9
9
|
|
|
@@ -29,22 +29,12 @@
|
|
|
29
29
|
const isLink = $derived(attributes.href != null && !disabled && !loading)
|
|
30
30
|
const tooltipId = $derived(title && !disabled && !loading ? uid : undefined)
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
let pressedTimeout: ReturnType<typeof setTimeout>
|
|
32
|
+
const morph = pressMorph()
|
|
34
33
|
|
|
35
34
|
const handlePress = () => {
|
|
36
35
|
if (disabled || loading) return
|
|
37
|
-
|
|
38
|
-
pressedTimeout = setTimeout(() => {
|
|
39
|
-
pressed = false
|
|
40
|
-
}, 100)
|
|
36
|
+
morph.press()
|
|
41
37
|
}
|
|
42
|
-
|
|
43
|
-
onMount(() => {
|
|
44
|
-
return () => {
|
|
45
|
-
clearTimeout(pressedTimeout)
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
38
|
</script>
|
|
49
39
|
|
|
50
40
|
{#snippet content()}
|
|
@@ -86,7 +76,7 @@
|
|
|
86
76
|
'enabled',
|
|
87
77
|
toggle && 'toggle',
|
|
88
78
|
selected && 'selected',
|
|
89
|
-
pressed && 'pressed',
|
|
79
|
+
morph.pressed && 'pressed',
|
|
90
80
|
attributes.class,
|
|
91
81
|
].filter(Boolean)}
|
|
92
82
|
>
|
|
@@ -119,7 +109,7 @@
|
|
|
119
109
|
disabled || loading ? `${variant}-disabled disabled` : `${variant} enabled`,
|
|
120
110
|
toggle && 'toggle',
|
|
121
111
|
selected && 'selected',
|
|
122
|
-
pressed && 'pressed',
|
|
112
|
+
morph.pressed && 'pressed',
|
|
123
113
|
attributes.class,
|
|
124
114
|
]}
|
|
125
115
|
>
|
|
@@ -10,13 +10,16 @@
|
|
|
10
10
|
multiSelect = false,
|
|
11
11
|
element = $bindable(),
|
|
12
12
|
group = $bindable(),
|
|
13
|
+
issues,
|
|
13
14
|
...attributes
|
|
14
15
|
}: SegmentedButtonProps = $props()
|
|
16
|
+
|
|
17
|
+
let hasError = $derived(!!issues?.length)
|
|
15
18
|
</script>
|
|
16
19
|
|
|
17
20
|
<div
|
|
18
21
|
{...attributes}
|
|
19
|
-
class={['np-segmented-buttons', attributes.class]}
|
|
22
|
+
class={['np-segmented-buttons', hasError && 'np-error', attributes.class]}
|
|
20
23
|
bind:this={element}
|
|
21
24
|
style="{attributes.style};grid-template-columns: repeat({options.length}, minmax(max-content, 1fr));"
|
|
22
25
|
>
|
|
@@ -95,6 +98,17 @@
|
|
|
95
98
|
overflow-x: auto;
|
|
96
99
|
}
|
|
97
100
|
|
|
101
|
+
.np-segmented-buttons.np-error {
|
|
102
|
+
--np-ripple-hover-color: var(--np-color-error);
|
|
103
|
+
--np-ripple-pressed-color: var(--np-color-error);
|
|
104
|
+
border-color: var(--np-color-error);
|
|
105
|
+
color: var(--np-color-error);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.np-error .np-segmented-button {
|
|
109
|
+
border-inline-end-color: var(--np-color-error);
|
|
110
|
+
}
|
|
111
|
+
|
|
98
112
|
.np-segmented-button {
|
|
99
113
|
flex: 1;
|
|
100
114
|
padding: 0.5rem 1.75rem;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import ChevronDownIcon from '../icons/ChevronDownIcon.svelte'
|
|
3
|
+
import Menu from '../menu/Menu.svelte'
|
|
4
|
+
import Button from './Button.svelte'
|
|
5
|
+
import ButtonGroup from './ButtonGroup.svelte'
|
|
6
|
+
import type { SplitButtonProps } from './types.js'
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
label = '',
|
|
10
|
+
icon,
|
|
11
|
+
menu,
|
|
12
|
+
variant = 'filled',
|
|
13
|
+
size = 's',
|
|
14
|
+
disabled = false,
|
|
15
|
+
open = $bindable(false),
|
|
16
|
+
menuLabel = 'More options',
|
|
17
|
+
onclick,
|
|
18
|
+
element = $bindable(),
|
|
19
|
+
...attributes
|
|
20
|
+
}: SplitButtonProps = $props()
|
|
21
|
+
|
|
22
|
+
const uid = $props.id()
|
|
23
|
+
const menuId = `np-split-button-menu-${uid}`
|
|
24
|
+
|
|
25
|
+
// The trailing half is the menu's invoker, so it is also the popover's implicit anchor.
|
|
26
|
+
let trigger: HTMLElement | undefined = $state()
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
{#snippet caret()}
|
|
30
|
+
<ChevronDownIcon />
|
|
31
|
+
{/snippet}
|
|
32
|
+
|
|
33
|
+
<ButtonGroup
|
|
34
|
+
{...attributes}
|
|
35
|
+
bind:element
|
|
36
|
+
variant="connected"
|
|
37
|
+
class={['np-split-button', attributes.class]}
|
|
38
|
+
>
|
|
39
|
+
<Button {variant} {size} {disabled} {onclick} start={icon}>{label}</Button>
|
|
40
|
+
<!--
|
|
41
|
+
A `Button` rather than an `IconButton`, because an icon button has no `elevated` variant and
|
|
42
|
+
a split button's two halves have to match.
|
|
43
|
+
-->
|
|
44
|
+
<Button
|
|
45
|
+
{variant}
|
|
46
|
+
{size}
|
|
47
|
+
{disabled}
|
|
48
|
+
bind:element={trigger}
|
|
49
|
+
class="np-split-button-trigger"
|
|
50
|
+
command="toggle-popover"
|
|
51
|
+
commandfor={menuId}
|
|
52
|
+
aria-haspopup="menu"
|
|
53
|
+
aria-expanded={open}
|
|
54
|
+
aria-label={menuLabel}
|
|
55
|
+
start={caret}
|
|
56
|
+
/>
|
|
57
|
+
<Menu id={menuId} anchor={trigger} bind:open coverAnchor={false}>
|
|
58
|
+
{@render menu?.(menuId)}
|
|
59
|
+
</Menu>
|
|
60
|
+
</ButtonGroup>
|
|
61
|
+
|
|
62
|
+
<style>
|
|
63
|
+
/* The caret turns over while the menu is open, the way the select arrow does. */
|
|
64
|
+
:global(.np-split-button-trigger svg) {
|
|
65
|
+
transition: rotate var(--np-motion-expressive-fast-effects);
|
|
66
|
+
}
|
|
67
|
+
:global(.np-split-button-trigger[aria-expanded='true'] svg) {
|
|
68
|
+
rotate: 180deg;
|
|
69
|
+
}
|
|
70
|
+
/*
|
|
71
|
+
The trailing half only holds a caret, so it does not need a full button's width. It is
|
|
72
|
+
square rather than merely narrow, because every size sets its round corner to half its
|
|
73
|
+
height, and only on a square does that corner come out as a true circle.
|
|
74
|
+
*/
|
|
75
|
+
:global(.np-split-button > .np-split-button-trigger) {
|
|
76
|
+
--np-button-padding: 0;
|
|
77
|
+
aspect-ratio: 1;
|
|
78
|
+
justify-content: center;
|
|
79
|
+
}
|
|
80
|
+
/*
|
|
81
|
+
While the menu is open the trailing half reads as selected: its inner corner rounds out to
|
|
82
|
+
the outer one, so the half becomes a circle, and it keeps a state layer up. Overriding the
|
|
83
|
+
group's inner corner rather than `border-radius` leaves ButtonGroup's own corner rules in
|
|
84
|
+
charge of which corner is which.
|
|
85
|
+
*/
|
|
86
|
+
:global(.np-split-button > .np-split-button-trigger[aria-expanded='true']) {
|
|
87
|
+
--np-button-group-inner-corner: var(--_round-radius, var(--np-shape-corner-full));
|
|
88
|
+
}
|
|
89
|
+
:global(.np-split-button-trigger[aria-expanded='true'] .np-ripple-surface::before) {
|
|
90
|
+
opacity: var(--np-ripple-hover-opacity, 0.08);
|
|
91
|
+
}
|
|
92
|
+
</style>
|
package/dist/button/index.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export { default as Button } from './Button.svelte';
|
|
|
2
2
|
export { default as ButtonGroup } from './ButtonGroup.svelte';
|
|
3
3
|
export { default as IconButton } from './IconButton.svelte';
|
|
4
4
|
export { default as SegmentedButton } from './SegmentedButton.svelte';
|
|
5
|
+
export { default as SplitButton } from './SplitButton.svelte';
|
package/dist/button/index.js
CHANGED
|
@@ -2,3 +2,4 @@ export { default as Button } from './Button.svelte';
|
|
|
2
2
|
export { default as ButtonGroup } from './ButtonGroup.svelte';
|
|
3
3
|
export { default as IconButton } from './IconButton.svelte';
|
|
4
4
|
export { default as SegmentedButton } from './SegmentedButton.svelte';
|
|
5
|
+
export { default as SplitButton } from './SplitButton.svelte';
|
package/dist/button/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
import type { HTMLAnchorAttributes, HTMLAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
|
2
|
+
import type { HTMLAnchorAttributes, HTMLAttributes, HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements';
|
|
3
3
|
export type ButtonElement = HTMLButtonElement | HTMLAnchorElement;
|
|
4
|
-
interface BaseButtonProps extends HTMLAttributes<ButtonElement>, Omit<HTMLButtonAttributes, keyof HTMLAttributes<HTMLButtonElement> | 'type'>, Omit<HTMLAnchorAttributes, keyof HTMLAttributes<HTMLAnchorElement> | 'type'> {
|
|
4
|
+
export interface BaseButtonProps extends HTMLAttributes<ButtonElement>, Omit<HTMLButtonAttributes, keyof HTMLAttributes<HTMLButtonElement> | 'type'>, Omit<HTMLAnchorAttributes, keyof HTMLAttributes<HTMLAnchorElement> | 'type'> {
|
|
5
5
|
element?: HTMLElement;
|
|
6
6
|
disabled?: boolean | null;
|
|
7
7
|
loading?: boolean;
|
|
@@ -27,7 +27,24 @@ export interface ButtonGroupProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
27
27
|
expandedRatio?: number;
|
|
28
28
|
compressionLimit?: number;
|
|
29
29
|
element?: HTMLElement;
|
|
30
|
-
|
|
30
|
+
}
|
|
31
|
+
export interface SplitButtonProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onclick'> {
|
|
32
|
+
/** Text of the leading action. */
|
|
33
|
+
label?: string;
|
|
34
|
+
/** Leading icon on the action half. */
|
|
35
|
+
icon?: Snippet;
|
|
36
|
+
/** Menu items for the trailing half. Rendered inside a `Menu`. */
|
|
37
|
+
menu?: Snippet<[string]>;
|
|
38
|
+
variant?: Exclude<ButtonProps['variant'], 'text'>;
|
|
39
|
+
size?: BaseButtonProps['size'];
|
|
40
|
+
disabled?: boolean | null;
|
|
41
|
+
/** Bindable. Whether the menu is open. */
|
|
42
|
+
open?: boolean;
|
|
43
|
+
/** Accessible name for the trailing half, which shows only a caret. */
|
|
44
|
+
menuLabel?: string;
|
|
45
|
+
/** The action half's click handler. The trailing half opens the menu instead. */
|
|
46
|
+
onclick?: MouseEventHandler<ButtonElement>;
|
|
47
|
+
element?: HTMLElement;
|
|
31
48
|
}
|
|
32
49
|
export interface SegmentedButtonProps extends HTMLAttributes<HTMLDivElement> {
|
|
33
50
|
name: string;
|
|
@@ -42,5 +59,7 @@ export interface SegmentedButtonProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
42
59
|
}[];
|
|
43
60
|
group?: string | number | (string | number)[] | null;
|
|
44
61
|
element?: HTMLElement;
|
|
62
|
+
issues?: {
|
|
63
|
+
message: string;
|
|
64
|
+
}[];
|
|
45
65
|
}
|
|
46
|
-
export {};
|
package/dist/card/Card.svelte
CHANGED
package/dist/card/types.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { HTMLAnchorAttributes, HTMLAttributes, HTMLButtonAttributes } from
|
|
|
3
3
|
export type CardElement = HTMLDivElement | HTMLButtonElement | HTMLAnchorElement;
|
|
4
4
|
export interface CardProps extends HTMLAttributes<CardElement>, Omit<HTMLButtonAttributes, keyof HTMLAttributes<HTMLButtonElement> | 'type'>, Omit<HTMLAnchorAttributes, keyof HTMLAttributes<HTMLAnchorElement> | 'type'> {
|
|
5
5
|
variant?: 'elevated' | 'filled' | 'outlined';
|
|
6
|
-
disabled?: boolean;
|
|
6
|
+
disabled?: boolean | null;
|
|
7
7
|
image?: string | null;
|
|
8
8
|
element?: HTMLElement;
|
|
9
9
|
headline?: string | null;
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
issues,
|
|
12
12
|
style,
|
|
13
13
|
value,
|
|
14
|
+
'aria-invalid': ariaInvalid,
|
|
14
15
|
...attributes
|
|
15
16
|
}: CheckboxProps = $props()
|
|
16
17
|
|
|
@@ -20,9 +21,10 @@
|
|
|
20
21
|
let groupValue = $derived(
|
|
21
22
|
typeof value === 'string' || typeof value === 'number' ? value : undefined,
|
|
22
23
|
)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
// A grouped checkbox takes its checked state from the group, so it cannot also `bind:checked`.
|
|
25
|
+
// One controlled input covers both, with the change handler writing back whichever is in play.
|
|
26
|
+
let isChecked = $derived(
|
|
27
|
+
Array.isArray(group) && groupValue !== undefined ? group.includes(groupValue) : checked,
|
|
26
28
|
)
|
|
27
29
|
|
|
28
30
|
const onchange = (event: Event & { currentTarget: EventTarget & HTMLInputElement }) => {
|
|
@@ -41,7 +43,11 @@
|
|
|
41
43
|
|
|
42
44
|
<div
|
|
43
45
|
{style}
|
|
44
|
-
class={[
|
|
46
|
+
class={[
|
|
47
|
+
'np-checkbox-container',
|
|
48
|
+
hasError && !attributes.disabled && 'np-error',
|
|
49
|
+
attributes.class,
|
|
50
|
+
]}
|
|
45
51
|
bind:this={element}
|
|
46
52
|
>
|
|
47
53
|
<div class="np-outline"></div>
|
|
@@ -54,37 +60,23 @@
|
|
|
54
60
|
{#if !attributes.disabled}
|
|
55
61
|
<Ripple forElement={inputEl} />
|
|
56
62
|
{/if}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
/>
|
|
70
|
-
{:else}
|
|
71
|
-
<input
|
|
72
|
-
{...attributes}
|
|
73
|
-
{value}
|
|
74
|
-
class="np-input"
|
|
75
|
-
type="checkbox"
|
|
76
|
-
bind:indeterminate
|
|
77
|
-
bind:checked
|
|
78
|
-
bind:this={inputEl}
|
|
79
|
-
aria-invalid={hasError ? 'true' : undefined}
|
|
80
|
-
aria-checked={indeterminate ? 'mixed' : undefined}
|
|
81
|
-
/>
|
|
82
|
-
{/if}
|
|
63
|
+
<input
|
|
64
|
+
{...attributes}
|
|
65
|
+
{value}
|
|
66
|
+
class="np-input"
|
|
67
|
+
type="checkbox"
|
|
68
|
+
bind:indeterminate
|
|
69
|
+
bind:this={inputEl}
|
|
70
|
+
checked={isChecked}
|
|
71
|
+
{onchange}
|
|
72
|
+
aria-invalid={hasError ? 'true' : ariaInvalid}
|
|
73
|
+
aria-checked={indeterminate ? 'mixed' : undefined}
|
|
74
|
+
/>
|
|
83
75
|
</div>
|
|
84
76
|
</div>
|
|
85
77
|
|
|
86
78
|
<style>
|
|
87
|
-
.np-container {
|
|
79
|
+
.np-checkbox-container {
|
|
88
80
|
border-radius: var(--np-checkbox-container-shape, 2px);
|
|
89
81
|
display: inline-flex;
|
|
90
82
|
place-content: center;
|
|
@@ -101,7 +93,7 @@
|
|
|
101
93
|
:global(label) {
|
|
102
94
|
-webkit-tap-highlight-color: transparent;
|
|
103
95
|
}
|
|
104
|
-
.np-container:has(input:disabled) {
|
|
96
|
+
.np-checkbox-container:has(input:disabled) {
|
|
105
97
|
cursor: default;
|
|
106
98
|
}
|
|
107
99
|
.np-input {
|
|
@@ -147,18 +139,18 @@
|
|
|
147
139
|
border-width: 2px;
|
|
148
140
|
box-sizing: border-box;
|
|
149
141
|
}
|
|
150
|
-
.np-container:focus-within .np-outline,
|
|
151
|
-
.np-container:hover .np-outline {
|
|
142
|
+
.np-checkbox-container:focus-within .np-outline,
|
|
143
|
+
.np-checkbox-container:hover .np-outline {
|
|
152
144
|
border-color: var(--np-color-on-surface);
|
|
153
145
|
border-width: 2px;
|
|
154
146
|
}
|
|
155
|
-
.np-container:has(input:disabled) .np-outline {
|
|
147
|
+
.np-checkbox-container:has(input:disabled) .np-outline {
|
|
156
148
|
border-color: var(--np-color-on-surface);
|
|
157
149
|
border-width: 2px;
|
|
158
150
|
opacity: 0.38;
|
|
159
151
|
}
|
|
160
|
-
.np-container:has(input:disabled:checked) .np-outline,
|
|
161
|
-
.np-container:has(input:disabled:indeterminate) .np-outline {
|
|
152
|
+
.np-checkbox-container:has(input:disabled:checked) .np-outline,
|
|
153
|
+
.np-checkbox-container:has(input:disabled:indeterminate) .np-outline {
|
|
162
154
|
visibility: hidden;
|
|
163
155
|
}
|
|
164
156
|
.np-background {
|
|
@@ -172,17 +164,17 @@
|
|
|
172
164
|
transition-timing-function: cubic-bezier(0.3, 0, 0.8, 0.15), linear;
|
|
173
165
|
transform: scale(0.6);
|
|
174
166
|
}
|
|
175
|
-
.np-container:has(input:indeterminate) .np-background,
|
|
176
|
-
.np-container:has(input:checked) .np-background,
|
|
177
|
-
.np-container:has(input:indeterminate) .np-icon,
|
|
178
|
-
.np-container:has(input:checked) .np-icon {
|
|
167
|
+
.np-checkbox-container:has(input:indeterminate) .np-background,
|
|
168
|
+
.np-checkbox-container:has(input:checked) .np-background,
|
|
169
|
+
.np-checkbox-container:has(input:indeterminate) .np-icon,
|
|
170
|
+
.np-checkbox-container:has(input:checked) .np-icon {
|
|
179
171
|
opacity: 1;
|
|
180
172
|
transition-duration: 350ms, 50ms;
|
|
181
173
|
transition-timing-function: cubic-bezier(0.05, 0.7, 0.1, 1), linear;
|
|
182
174
|
transform: scale(1);
|
|
183
175
|
}
|
|
184
|
-
.np-container:has(input:disabled:checked) .np-background,
|
|
185
|
-
.np-container:has(input:disabled:indeterminate) .np-background {
|
|
176
|
+
.np-checkbox-container:has(input:disabled:checked) .np-background,
|
|
177
|
+
.np-checkbox-container:has(input:disabled:indeterminate) .np-background {
|
|
186
178
|
background: var(--np-color-on-surface);
|
|
187
179
|
opacity: 0.38;
|
|
188
180
|
}
|
|
@@ -207,23 +199,23 @@
|
|
|
207
199
|
height: 18px;
|
|
208
200
|
width: 18px;
|
|
209
201
|
}
|
|
210
|
-
.np-container:has(input:disabled) .np-icon {
|
|
202
|
+
.np-checkbox-container:has(input:disabled) .np-icon {
|
|
211
203
|
fill: var(--np-color-surface);
|
|
212
204
|
}
|
|
213
|
-
.np-container:has(input:checked) .mark.short,
|
|
214
|
-
.np-container:has(input:not(:checked):not(:indeterminate)) .mark.short {
|
|
205
|
+
.np-checkbox-container:has(input:checked) .mark.short,
|
|
206
|
+
.np-checkbox-container:has(input:not(:checked):not(:indeterminate)) .mark.short {
|
|
215
207
|
height: 5.6568542495px;
|
|
216
208
|
}
|
|
217
|
-
.np-container:has(input:indeterminate) .mark,
|
|
218
|
-
.np-container:has(input:checked) .mark {
|
|
209
|
+
.np-checkbox-container:has(input:indeterminate) .mark,
|
|
210
|
+
.np-checkbox-container:has(input:checked) .mark {
|
|
219
211
|
transition-property: none;
|
|
220
212
|
}
|
|
221
|
-
.np-container:has(input:checked) .mark,
|
|
222
|
-
.np-container:has(input:not(:checked):not(:indeterminate)) .mark {
|
|
213
|
+
.np-checkbox-container:has(input:checked) .mark,
|
|
214
|
+
.np-checkbox-container:has(input:not(:checked):not(:indeterminate)) .mark {
|
|
223
215
|
transform: scaleY(-1) translate(7px, -14px) rotate(45deg);
|
|
224
216
|
}
|
|
225
|
-
.np-container:has(input:indeterminate) .mark,
|
|
226
|
-
.np-container:has(input:checked) .mark {
|
|
217
|
+
.np-checkbox-container:has(input:indeterminate) .mark,
|
|
218
|
+
.np-checkbox-container:has(input:checked) .mark {
|
|
227
219
|
animation-duration: 350ms;
|
|
228
220
|
animation-timing-function: cubic-bezier(0.05, 0.7, 0.1, 1);
|
|
229
221
|
transition-duration: 350ms;
|
|
@@ -240,11 +232,11 @@
|
|
|
240
232
|
transition-duration: 150ms;
|
|
241
233
|
transition-timing-function: cubic-bezier(0.3, 0, 0.8, 0.15);
|
|
242
234
|
}
|
|
243
|
-
.np-container:has(input:checked) .mark.long {
|
|
235
|
+
.np-checkbox-container:has(input:checked) .mark.long {
|
|
244
236
|
animation-name: prev-unselected-to-checked;
|
|
245
237
|
}
|
|
246
|
-
.np-container:has(input:checked) .mark.long,
|
|
247
|
-
.np-container:has(input:not(:checked):not(:indeterminate)) .mark.long {
|
|
238
|
+
.np-checkbox-container:has(input:checked) .mark.long,
|
|
239
|
+
.np-checkbox-container:has(input:not(:checked):not(:indeterminate)) .mark.long {
|
|
248
240
|
width: 11.313708499px;
|
|
249
241
|
}
|
|
250
242
|
.mark.long {
|
|
@@ -252,7 +244,7 @@
|
|
|
252
244
|
transition-property: transform, width;
|
|
253
245
|
width: 10px;
|
|
254
246
|
}
|
|
255
|
-
.np-container:has(input:indeterminate) .mark {
|
|
247
|
+
.np-checkbox-container:has(input:indeterminate) .mark {
|
|
256
248
|
transform: scaleY(-1) translate(4px, -10px) rotate(0deg);
|
|
257
249
|
}
|
|
258
250
|
@keyframes prev-unselected-to-checked {
|
|
@@ -265,7 +257,7 @@
|
|
|
265
257
|
background-color: CanvasText;
|
|
266
258
|
}
|
|
267
259
|
|
|
268
|
-
.np-container:has(input:disabled:checked) .np-background {
|
|
260
|
+
.np-checkbox-container:has(input:disabled:checked) .np-background {
|
|
269
261
|
background-color: GrayText;
|
|
270
262
|
opacity: 1;
|
|
271
263
|
}
|
|
@@ -274,7 +266,7 @@
|
|
|
274
266
|
border-color: CanvasText;
|
|
275
267
|
}
|
|
276
268
|
|
|
277
|
-
.np-container:has(input:disabled) .np-outline {
|
|
269
|
+
.np-checkbox-container:has(input:disabled) .np-outline {
|
|
278
270
|
border-color: GrayText;
|
|
279
271
|
opacity: 1;
|
|
280
272
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import Button from '../button/Button.svelte'
|
|
4
4
|
|
|
5
5
|
let {
|
|
6
|
-
|
|
6
|
+
variant = 'outlined',
|
|
7
7
|
disabled = false,
|
|
8
8
|
label = '',
|
|
9
9
|
icon,
|
|
@@ -13,8 +13,6 @@
|
|
|
13
13
|
</script>
|
|
14
14
|
|
|
15
15
|
<Button
|
|
16
|
-
size="xs"
|
|
17
|
-
shape="square"
|
|
18
16
|
--np-elevated-button-label-text-color="var(--np-assist-chip-label-text-color, var(--np-color-on-surface))"
|
|
19
17
|
--np-outlined-button-label-text-color="var(--np-assist-chip-label-text-color, var(--np-color-on-surface))"
|
|
20
18
|
--np-outlined-button-outline-color="var(--np-assist-chip-outline-color, var(--np-color-outline-variant))"
|
|
@@ -27,9 +25,11 @@
|
|
|
27
25
|
: 'var(--np-color-primary)'}
|
|
28
26
|
style="letter-spacing: 0.006rem"
|
|
29
27
|
bind:element
|
|
30
|
-
variant={elevated ? 'elevated' : 'outlined'}
|
|
31
|
-
{disabled}
|
|
32
28
|
{...attributes}
|
|
29
|
+
size="xs"
|
|
30
|
+
shape="square"
|
|
31
|
+
{variant}
|
|
32
|
+
{disabled}
|
|
33
33
|
start={icon}
|
|
34
34
|
>
|
|
35
35
|
{label}
|
package/dist/chip/ChipSet.svelte
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { arrowKeyNav, rovingTabindex } from '../keyboard-nav.js'
|
|
3
3
|
import type { ChipSetProps } from './types.js'
|
|
4
4
|
|
|
5
|
-
let { children,
|
|
5
|
+
let { children, element = $bindable(), ...attributes }: ChipSetProps = $props()
|
|
6
6
|
|
|
7
7
|
const CHIP_SELECTOR = "input:not([type='hidden']), button, a[href]"
|
|
8
8
|
const attach = rovingTabindex(CHIP_SELECTOR, {
|
|
@@ -12,14 +12,7 @@
|
|
|
12
12
|
const onkeydown = arrowKeyNav(CHIP_SELECTOR, 'horizontal')
|
|
13
13
|
</script>
|
|
14
14
|
|
|
15
|
-
<div
|
|
16
|
-
class={[
|
|
17
|
-
'np-chip-set-wrapper',
|
|
18
|
-
(chipsCount ?? 0) > 0 && 'np-chip-set-has-chips',
|
|
19
|
-
attributes.class,
|
|
20
|
-
]}
|
|
21
|
-
style={attributes.style}
|
|
22
|
-
>
|
|
15
|
+
<div {...attributes} bind:this={element} class={['np-chip-set-wrapper', attributes.class]}>
|
|
23
16
|
{#if children}
|
|
24
17
|
<div {@attach attach} class={['np-chip-set']} role="toolbar" tabindex="-1" {onkeydown}>
|
|
25
18
|
{@render children()}
|
|
@@ -33,7 +26,7 @@
|
|
|
33
26
|
padding: 0.5rem;
|
|
34
27
|
margin: -0.5rem;
|
|
35
28
|
}
|
|
36
|
-
.np-chip-set-has-
|
|
29
|
+
.np-chip-set-wrapper:has(.np-chip-set > :global(*)) {
|
|
37
30
|
margin-inline-end: 0;
|
|
38
31
|
}
|
|
39
32
|
.np-chip-set {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ChipSetProps } from './types.ts';
|
|
2
|
-
declare const ChipSet: import("svelte").Component<ChipSetProps, {}, "">;
|
|
2
|
+
declare const ChipSet: import("svelte").Component<ChipSetProps, {}, "element">;
|
|
3
3
|
type ChipSet = ReturnType<typeof ChipSet>;
|
|
4
4
|
export default ChipSet;
|
|
@@ -9,25 +9,30 @@
|
|
|
9
9
|
let {
|
|
10
10
|
selected = $bindable(),
|
|
11
11
|
removable = false,
|
|
12
|
-
|
|
12
|
+
variant = 'outlined',
|
|
13
13
|
disabled = false,
|
|
14
14
|
label = '',
|
|
15
15
|
icon,
|
|
16
16
|
element = $bindable(),
|
|
17
|
-
|
|
17
|
+
removeAriaLabel = 'Remove',
|
|
18
18
|
onremove,
|
|
19
19
|
name,
|
|
20
20
|
value,
|
|
21
21
|
group = $bindable(),
|
|
22
22
|
defaultSelected,
|
|
23
|
+
issues,
|
|
24
|
+
'aria-invalid': ariaInvalid,
|
|
23
25
|
...attributes
|
|
24
26
|
}: FilterChipProps = $props()
|
|
25
27
|
|
|
28
|
+
let hasError = $derived(!!issues?.length)
|
|
29
|
+
|
|
26
30
|
let chipLabel: HTMLLabelElement | undefined = $state()
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
// A grouped chip takes its checked state from the group, so it cannot also `bind:checked`. One
|
|
33
|
+
// controlled input covers both, with the change handler writing back whichever is in play.
|
|
34
|
+
let isChecked = $derived(
|
|
35
|
+
Array.isArray(group) && value !== undefined ? group.includes(value) : selected,
|
|
31
36
|
)
|
|
32
37
|
|
|
33
38
|
const onchange = (event: Event & { currentTarget: EventTarget & HTMLInputElement }) => {
|
|
@@ -48,10 +53,11 @@
|
|
|
48
53
|
bind:this={element}
|
|
49
54
|
class={[
|
|
50
55
|
'np-filter-chip',
|
|
51
|
-
elevated ? 'np-filter-chip-elevated' : 'np-filter-chip-default',
|
|
56
|
+
variant === 'elevated' ? 'np-filter-chip-elevated' : 'np-filter-chip-default',
|
|
52
57
|
icon ? 'np-filter-chip-icon' : '',
|
|
53
58
|
removable ? 'np-filter-chip-removable' : '',
|
|
54
59
|
disabled ? 'np-filter-chip-disabled' : '',
|
|
60
|
+
hasError && !disabled && 'np-chip-error',
|
|
55
61
|
attributes.class,
|
|
56
62
|
]}
|
|
57
63
|
>
|
|
@@ -65,26 +71,16 @@
|
|
|
65
71
|
<CheckIcon width={18} height={18} />
|
|
66
72
|
</div>
|
|
67
73
|
<div class="np-chip-label">{label}</div>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
{:else}
|
|
79
|
-
<input
|
|
80
|
-
type="checkbox"
|
|
81
|
-
bind:checked={selected}
|
|
82
|
-
{value}
|
|
83
|
-
{name}
|
|
84
|
-
{disabled}
|
|
85
|
-
defaultChecked={defaultSelected}
|
|
86
|
-
/>
|
|
87
|
-
{/if}
|
|
74
|
+
<input
|
|
75
|
+
type="checkbox"
|
|
76
|
+
checked={isChecked}
|
|
77
|
+
{onchange}
|
|
78
|
+
{value}
|
|
79
|
+
{name}
|
|
80
|
+
{disabled}
|
|
81
|
+
defaultChecked={defaultSelected}
|
|
82
|
+
aria-invalid={hasError ? 'true' : ariaInvalid}
|
|
83
|
+
/>
|
|
88
84
|
</label>
|
|
89
85
|
{#if !disabled}
|
|
90
86
|
<Ripple forElement={chipLabel} />
|
|
@@ -95,7 +91,7 @@
|
|
|
95
91
|
type="button"
|
|
96
92
|
size="xs"
|
|
97
93
|
--np-icon-button-icon-size="1.125rem"
|
|
98
|
-
aria-label={
|
|
94
|
+
aria-label={removeAriaLabel}
|
|
99
95
|
onclick={onremove}
|
|
100
96
|
>
|
|
101
97
|
<CloseIcon />
|
|
@@ -191,6 +187,18 @@
|
|
|
191
187
|
outline-width: 1px;
|
|
192
188
|
outline-offset: -1px;
|
|
193
189
|
}
|
|
190
|
+
.np-chip-error {
|
|
191
|
+
--np-filter-chip-outline-color: var(--np-color-error);
|
|
192
|
+
--np-ripple-hover-color: var(--np-color-error);
|
|
193
|
+
--np-ripple-pressed-color: var(--np-color-error);
|
|
194
|
+
color: var(--np-color-error);
|
|
195
|
+
}
|
|
196
|
+
.np-chip-error:has(input:checked)::before {
|
|
197
|
+
background-color: var(--np-color-error-container);
|
|
198
|
+
}
|
|
199
|
+
.np-chip-error:has(input:checked) {
|
|
200
|
+
color: var(--np-color-on-error-container);
|
|
201
|
+
}
|
|
194
202
|
.np-filter-chip:has(input:checked)::before {
|
|
195
203
|
outline-color: transparent;
|
|
196
204
|
background-color: var(--np-color-secondary-container);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '../internal/focus-ring.css';
|
|
2
2
|
import type { FilterChipProps } from './types.ts';
|
|
3
|
-
declare const FilterChip: import("svelte").Component<FilterChipProps, {}, "element" | "
|
|
3
|
+
declare const FilterChip: import("svelte").Component<FilterChipProps, {}, "element" | "group" | "selected">;
|
|
4
4
|
type FilterChip = ReturnType<typeof FilterChip>;
|
|
5
5
|
export default FilterChip;
|