noph-ui 0.44.0 → 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 +6 -1
- package/dist/badge/types.d.ts +0 -1
- 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/types.d.ts +1 -1
- package/dist/checkbox/Checkbox.svelte +49 -58
- package/dist/chip/AssistChip.svelte +5 -5
- package/dist/chip/ChipSet.svelte +3 -11
- package/dist/chip/FilterChip.svelte +35 -27
- 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 +24 -9
- 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/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/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/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/internal/focus-ring.css +12 -0
- package/dist/menu/Menu.svelte +12 -7
- package/dist/menu/Menu.svelte.d.ts +2 -2
- 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 +10 -3
- package/dist/navigation-drawer/types.d.ts +6 -1
- package/dist/navigation-rail/NavigationRailItem.svelte +16 -0
- package/dist/navigation-rail/types.d.ts +3 -0
- 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/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/Select.svelte +48 -87
- 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/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/text-field/TextField.svelte +2 -2
- 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 +6 -0
- package/dist/types.js +6 -0
- package/package.json +13 -13
- package/dist/date-picker/enterAnimation.d.ts +0 -1
- package/dist/date-picker/enterAnimation.js +0 -10
|
@@ -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/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;
|
|
@@ -21,9 +21,10 @@
|
|
|
21
21
|
let groupValue = $derived(
|
|
22
22
|
typeof value === 'string' || typeof value === 'number' ? value : undefined,
|
|
23
23
|
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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,
|
|
27
28
|
)
|
|
28
29
|
|
|
29
30
|
const onchange = (event: Event & { currentTarget: EventTarget & HTMLInputElement }) => {
|
|
@@ -42,7 +43,11 @@
|
|
|
42
43
|
|
|
43
44
|
<div
|
|
44
45
|
{style}
|
|
45
|
-
class={[
|
|
46
|
+
class={[
|
|
47
|
+
'np-checkbox-container',
|
|
48
|
+
hasError && !attributes.disabled && 'np-error',
|
|
49
|
+
attributes.class,
|
|
50
|
+
]}
|
|
46
51
|
bind:this={element}
|
|
47
52
|
>
|
|
48
53
|
<div class="np-outline"></div>
|
|
@@ -55,37 +60,23 @@
|
|
|
55
60
|
{#if !attributes.disabled}
|
|
56
61
|
<Ripple forElement={inputEl} />
|
|
57
62
|
{/if}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
/>
|
|
71
|
-
{:else}
|
|
72
|
-
<input
|
|
73
|
-
{...attributes}
|
|
74
|
-
{value}
|
|
75
|
-
class="np-input"
|
|
76
|
-
type="checkbox"
|
|
77
|
-
bind:indeterminate
|
|
78
|
-
bind:checked
|
|
79
|
-
bind:this={inputEl}
|
|
80
|
-
aria-invalid={hasError ? 'true' : ariaInvalid}
|
|
81
|
-
aria-checked={indeterminate ? 'mixed' : undefined}
|
|
82
|
-
/>
|
|
83
|
-
{/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
|
+
/>
|
|
84
75
|
</div>
|
|
85
76
|
</div>
|
|
86
77
|
|
|
87
78
|
<style>
|
|
88
|
-
.np-container {
|
|
79
|
+
.np-checkbox-container {
|
|
89
80
|
border-radius: var(--np-checkbox-container-shape, 2px);
|
|
90
81
|
display: inline-flex;
|
|
91
82
|
place-content: center;
|
|
@@ -102,7 +93,7 @@
|
|
|
102
93
|
:global(label) {
|
|
103
94
|
-webkit-tap-highlight-color: transparent;
|
|
104
95
|
}
|
|
105
|
-
.np-container:has(input:disabled) {
|
|
96
|
+
.np-checkbox-container:has(input:disabled) {
|
|
106
97
|
cursor: default;
|
|
107
98
|
}
|
|
108
99
|
.np-input {
|
|
@@ -148,18 +139,18 @@
|
|
|
148
139
|
border-width: 2px;
|
|
149
140
|
box-sizing: border-box;
|
|
150
141
|
}
|
|
151
|
-
.np-container:focus-within .np-outline,
|
|
152
|
-
.np-container:hover .np-outline {
|
|
142
|
+
.np-checkbox-container:focus-within .np-outline,
|
|
143
|
+
.np-checkbox-container:hover .np-outline {
|
|
153
144
|
border-color: var(--np-color-on-surface);
|
|
154
145
|
border-width: 2px;
|
|
155
146
|
}
|
|
156
|
-
.np-container:has(input:disabled) .np-outline {
|
|
147
|
+
.np-checkbox-container:has(input:disabled) .np-outline {
|
|
157
148
|
border-color: var(--np-color-on-surface);
|
|
158
149
|
border-width: 2px;
|
|
159
150
|
opacity: 0.38;
|
|
160
151
|
}
|
|
161
|
-
.np-container:has(input:disabled:checked) .np-outline,
|
|
162
|
-
.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 {
|
|
163
154
|
visibility: hidden;
|
|
164
155
|
}
|
|
165
156
|
.np-background {
|
|
@@ -173,17 +164,17 @@
|
|
|
173
164
|
transition-timing-function: cubic-bezier(0.3, 0, 0.8, 0.15), linear;
|
|
174
165
|
transform: scale(0.6);
|
|
175
166
|
}
|
|
176
|
-
.np-container:has(input:indeterminate) .np-background,
|
|
177
|
-
.np-container:has(input:checked) .np-background,
|
|
178
|
-
.np-container:has(input:indeterminate) .np-icon,
|
|
179
|
-
.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 {
|
|
180
171
|
opacity: 1;
|
|
181
172
|
transition-duration: 350ms, 50ms;
|
|
182
173
|
transition-timing-function: cubic-bezier(0.05, 0.7, 0.1, 1), linear;
|
|
183
174
|
transform: scale(1);
|
|
184
175
|
}
|
|
185
|
-
.np-container:has(input:disabled:checked) .np-background,
|
|
186
|
-
.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 {
|
|
187
178
|
background: var(--np-color-on-surface);
|
|
188
179
|
opacity: 0.38;
|
|
189
180
|
}
|
|
@@ -208,23 +199,23 @@
|
|
|
208
199
|
height: 18px;
|
|
209
200
|
width: 18px;
|
|
210
201
|
}
|
|
211
|
-
.np-container:has(input:disabled) .np-icon {
|
|
202
|
+
.np-checkbox-container:has(input:disabled) .np-icon {
|
|
212
203
|
fill: var(--np-color-surface);
|
|
213
204
|
}
|
|
214
|
-
.np-container:has(input:checked) .mark.short,
|
|
215
|
-
.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 {
|
|
216
207
|
height: 5.6568542495px;
|
|
217
208
|
}
|
|
218
|
-
.np-container:has(input:indeterminate) .mark,
|
|
219
|
-
.np-container:has(input:checked) .mark {
|
|
209
|
+
.np-checkbox-container:has(input:indeterminate) .mark,
|
|
210
|
+
.np-checkbox-container:has(input:checked) .mark {
|
|
220
211
|
transition-property: none;
|
|
221
212
|
}
|
|
222
|
-
.np-container:has(input:checked) .mark,
|
|
223
|
-
.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 {
|
|
224
215
|
transform: scaleY(-1) translate(7px, -14px) rotate(45deg);
|
|
225
216
|
}
|
|
226
|
-
.np-container:has(input:indeterminate) .mark,
|
|
227
|
-
.np-container:has(input:checked) .mark {
|
|
217
|
+
.np-checkbox-container:has(input:indeterminate) .mark,
|
|
218
|
+
.np-checkbox-container:has(input:checked) .mark {
|
|
228
219
|
animation-duration: 350ms;
|
|
229
220
|
animation-timing-function: cubic-bezier(0.05, 0.7, 0.1, 1);
|
|
230
221
|
transition-duration: 350ms;
|
|
@@ -241,11 +232,11 @@
|
|
|
241
232
|
transition-duration: 150ms;
|
|
242
233
|
transition-timing-function: cubic-bezier(0.3, 0, 0.8, 0.15);
|
|
243
234
|
}
|
|
244
|
-
.np-container:has(input:checked) .mark.long {
|
|
235
|
+
.np-checkbox-container:has(input:checked) .mark.long {
|
|
245
236
|
animation-name: prev-unselected-to-checked;
|
|
246
237
|
}
|
|
247
|
-
.np-container:has(input:checked) .mark.long,
|
|
248
|
-
.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 {
|
|
249
240
|
width: 11.313708499px;
|
|
250
241
|
}
|
|
251
242
|
.mark.long {
|
|
@@ -253,7 +244,7 @@
|
|
|
253
244
|
transition-property: transform, width;
|
|
254
245
|
width: 10px;
|
|
255
246
|
}
|
|
256
|
-
.np-container:has(input:indeterminate) .mark {
|
|
247
|
+
.np-checkbox-container:has(input:indeterminate) .mark {
|
|
257
248
|
transform: scaleY(-1) translate(4px, -10px) rotate(0deg);
|
|
258
249
|
}
|
|
259
250
|
@keyframes prev-unselected-to-checked {
|
|
@@ -266,7 +257,7 @@
|
|
|
266
257
|
background-color: CanvasText;
|
|
267
258
|
}
|
|
268
259
|
|
|
269
|
-
.np-container:has(input:disabled:checked) .np-background {
|
|
260
|
+
.np-checkbox-container:has(input:disabled:checked) .np-background {
|
|
270
261
|
background-color: GrayText;
|
|
271
262
|
opacity: 1;
|
|
272
263
|
}
|
|
@@ -275,7 +266,7 @@
|
|
|
275
266
|
border-color: CanvasText;
|
|
276
267
|
}
|
|
277
268
|
|
|
278
|
-
.np-container:has(input:disabled) .np-outline {
|
|
269
|
+
.np-checkbox-container:has(input:disabled) .np-outline {
|
|
279
270
|
border-color: GrayText;
|
|
280
271
|
opacity: 1;
|
|
281
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,15 +12,7 @@
|
|
|
12
12
|
const onkeydown = arrowKeyNav(CHIP_SELECTOR, 'horizontal')
|
|
13
13
|
</script>
|
|
14
14
|
|
|
15
|
-
<div
|
|
16
|
-
{...attributes}
|
|
17
|
-
bind:this={element}
|
|
18
|
-
class={[
|
|
19
|
-
'np-chip-set-wrapper',
|
|
20
|
-
(chipsCount ?? 0) > 0 && 'np-chip-set-has-chips',
|
|
21
|
-
attributes.class,
|
|
22
|
-
]}
|
|
23
|
-
>
|
|
15
|
+
<div {...attributes} bind:this={element} class={['np-chip-set-wrapper', attributes.class]}>
|
|
24
16
|
{#if children}
|
|
25
17
|
<div {@attach attach} class={['np-chip-set']} role="toolbar" tabindex="-1" {onkeydown}>
|
|
26
18
|
{@render children()}
|
|
@@ -34,7 +26,7 @@
|
|
|
34
26
|
padding: 0.5rem;
|
|
35
27
|
margin: -0.5rem;
|
|
36
28
|
}
|
|
37
|
-
.np-chip-set-has-
|
|
29
|
+
.np-chip-set-wrapper:has(.np-chip-set > :global(*)) {
|
|
38
30
|
margin-inline-end: 0;
|
|
39
31
|
}
|
|
40
32
|
.np-chip-set {
|
|
@@ -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);
|
|
@@ -12,13 +12,16 @@
|
|
|
12
12
|
icon,
|
|
13
13
|
element = $bindable(),
|
|
14
14
|
actionElement = $bindable(),
|
|
15
|
-
|
|
15
|
+
removeAriaLabel = 'Remove',
|
|
16
16
|
onclick,
|
|
17
17
|
onremove,
|
|
18
18
|
name,
|
|
19
19
|
value,
|
|
20
|
+
issues,
|
|
20
21
|
...attributes
|
|
21
22
|
}: InputChipProps = $props()
|
|
23
|
+
|
|
24
|
+
let hasError = $derived(!!issues?.length)
|
|
22
25
|
</script>
|
|
23
26
|
|
|
24
27
|
<div
|
|
@@ -30,6 +33,7 @@
|
|
|
30
33
|
icon ? 'np-input-chip-icon' : '',
|
|
31
34
|
disabled ? 'np-input-chip-disabled' : '',
|
|
32
35
|
selected ? 'np-input-chip-selected' : '',
|
|
36
|
+
hasError && !disabled && 'np-chip-error',
|
|
33
37
|
attributes.class,
|
|
34
38
|
]}
|
|
35
39
|
>
|
|
@@ -57,7 +61,7 @@
|
|
|
57
61
|
type="button"
|
|
58
62
|
size="xs"
|
|
59
63
|
--np-icon-button-icon-size="1.125rem"
|
|
60
|
-
aria-label={
|
|
64
|
+
aria-label={removeAriaLabel}
|
|
61
65
|
onclick={onremove}
|
|
62
66
|
>
|
|
63
67
|
<CloseIcon />
|
|
@@ -77,6 +81,13 @@
|
|
|
77
81
|
padding-inline-end: 1px;
|
|
78
82
|
min-width: 0;
|
|
79
83
|
}
|
|
84
|
+
.np-chip-error {
|
|
85
|
+
--np-input-chip-outline-color: var(--np-color-error);
|
|
86
|
+
--np-icon-button-icon-color: var(--np-color-error);
|
|
87
|
+
--np-ripple-hover-color: var(--np-color-error);
|
|
88
|
+
--np-ripple-pressed-color: var(--np-color-error);
|
|
89
|
+
color: var(--np-color-error);
|
|
90
|
+
}
|
|
80
91
|
.np-input-chip-label {
|
|
81
92
|
appearance: none;
|
|
82
93
|
background: none;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Button from '../button/Button.svelte'
|
|
3
|
+
import type { SuggestionChipProps } from './types.js'
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
variant = 'outlined',
|
|
7
|
+
disabled = false,
|
|
8
|
+
label = '',
|
|
9
|
+
element = $bindable(),
|
|
10
|
+
...attributes
|
|
11
|
+
}: SuggestionChipProps = $props()
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<Button
|
|
15
|
+
--np-elevated-button-label-text-color="var(--np-suggestion-chip-label-text-color, var(--np-color-on-surface))"
|
|
16
|
+
--np-outlined-button-label-text-color="var(--np-suggestion-chip-label-text-color, var(--np-color-on-surface))"
|
|
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"
|
|
21
|
+
bind:element
|
|
22
|
+
{...attributes}
|
|
23
|
+
size="xs"
|
|
24
|
+
shape="square"
|
|
25
|
+
{variant}
|
|
26
|
+
{disabled}
|
|
27
|
+
>
|
|
28
|
+
{label}
|
|
29
|
+
</Button>
|
package/dist/chip/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as FilterChip } from './FilterChip.svelte';
|
|
2
2
|
export { default as AssistChip } from './AssistChip.svelte';
|
|
3
3
|
export { default as InputChip } from './InputChip.svelte';
|
|
4
|
+
export { default as SuggestionChip } from './SuggestionChip.svelte';
|
|
4
5
|
export { default as ChipSet } from './ChipSet.svelte';
|