@noxlovette/material 0.3.0 → 0.3.2
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/components/containers/context-menu/ContextMenu.stories.svelte +71 -0
- package/dist/components/containers/context-menu/ContextMenu.stories.svelte.d.ts +19 -0
- package/dist/components/containers/context-menu/ContextMenu.svelte +2 -2
- package/dist/components/containers/divider/Divider.stories.svelte +62 -0
- package/dist/components/containers/divider/Divider.stories.svelte.d.ts +19 -0
- package/dist/components/containers/divider/Divider.svelte +12 -11
- package/dist/components/containers/divider/types.d.ts +7 -2
- package/dist/components/containers/panes/SupportingPane.svelte +0 -2
- package/dist/components/nav/rail/RailItem.svelte +1 -0
- package/dist/components/nav/tabs/TabHolder.svelte +1 -1
- package/dist/components/nav/tabs/Tabs.stories.svelte +5 -4
- package/dist/components/time/TimepickerInput.svelte +1 -0
- package/dist/utils/Layer.svelte +4 -3
- package/package.json +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import ContextMenu from './ContextMenu.svelte';
|
|
4
|
+
|
|
5
|
+
const { Story } = defineMeta({
|
|
6
|
+
title: 'Containers/Context Menu',
|
|
7
|
+
component: ContextMenu
|
|
8
|
+
});
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<Story name="Playground" asChild>
|
|
12
|
+
<ContextMenu
|
|
13
|
+
items={[
|
|
14
|
+
{ label: 'Edit', value: 'edit', iconProps: { name: 'edit' } },
|
|
15
|
+
{ label: 'Duplicate', value: 'duplicate', iconProps: { name: 'content_copy' } },
|
|
16
|
+
{ separator: true },
|
|
17
|
+
{ label: 'Delete', value: 'delete', iconProps: { name: 'delete' } }
|
|
18
|
+
]}
|
|
19
|
+
onselect={(value) => console.log('selected', value)}
|
|
20
|
+
>
|
|
21
|
+
<div
|
|
22
|
+
class="border-md-sys-color-outline text-md-sys-color-on-surface-variant flex size-40 items-center justify-center rounded-lg border border-dashed"
|
|
23
|
+
>
|
|
24
|
+
Right click me
|
|
25
|
+
</div>
|
|
26
|
+
</ContextMenu>
|
|
27
|
+
</Story>
|
|
28
|
+
|
|
29
|
+
<Story name="With Submenu" asChild>
|
|
30
|
+
<ContextMenu
|
|
31
|
+
items={[
|
|
32
|
+
{ label: 'Edit', value: 'edit', iconProps: { name: 'edit' } },
|
|
33
|
+
{ separator: true },
|
|
34
|
+
{
|
|
35
|
+
label: 'Share',
|
|
36
|
+
value: 'share',
|
|
37
|
+
iconProps: { name: 'share' },
|
|
38
|
+
items: [
|
|
39
|
+
{ label: 'Email', value: 'email' },
|
|
40
|
+
{ label: 'Link', value: 'link' }
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{ separator: true },
|
|
44
|
+
{ label: 'Delete', value: 'delete', iconProps: { name: 'delete' } }
|
|
45
|
+
]}
|
|
46
|
+
onselect={(value) => console.log('selected', value)}
|
|
47
|
+
>
|
|
48
|
+
<div
|
|
49
|
+
class="border-md-sys-color-outline text-md-sys-color-on-surface-variant flex size-40 items-center justify-center rounded-lg border border-dashed"
|
|
50
|
+
>
|
|
51
|
+
Right click me
|
|
52
|
+
</div>
|
|
53
|
+
</ContextMenu>
|
|
54
|
+
</Story>
|
|
55
|
+
|
|
56
|
+
<Story name="With Selected Item" asChild>
|
|
57
|
+
<ContextMenu
|
|
58
|
+
selected="name"
|
|
59
|
+
items={[
|
|
60
|
+
{ label: 'Name', value: 'name' },
|
|
61
|
+
{ label: 'Date modified', value: 'date' },
|
|
62
|
+
{ label: 'Size', value: 'size' }
|
|
63
|
+
]}
|
|
64
|
+
>
|
|
65
|
+
<div
|
|
66
|
+
class="border-md-sys-color-outline text-md-sys-color-on-surface-variant flex size-40 items-center justify-center rounded-lg border border-dashed"
|
|
67
|
+
>
|
|
68
|
+
Right click me
|
|
69
|
+
</div>
|
|
70
|
+
</ContextMenu>
|
|
71
|
+
</Story>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import ContextMenu from './ContextMenu.svelte';
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const ContextMenu: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
}, {}, {}, string>;
|
|
18
|
+
type ContextMenu = InstanceType<typeof ContextMenu>;
|
|
19
|
+
export default ContextMenu;
|
|
@@ -76,7 +76,7 @@ Context menus appear on right-click and provide actions related to the clicked e
|
|
|
76
76
|
mode: 'scale'
|
|
77
77
|
}}
|
|
78
78
|
>
|
|
79
|
-
{#each item.items as subItem}
|
|
79
|
+
{#each item.items as subItem (subItem)}
|
|
80
80
|
{@render MenuItem(subItem)}
|
|
81
81
|
{/each}
|
|
82
82
|
</div>
|
|
@@ -139,7 +139,7 @@ Context menus appear on right-click and provide actions related to the clicked e
|
|
|
139
139
|
mode: 'scale'
|
|
140
140
|
}}
|
|
141
141
|
>
|
|
142
|
-
{#each items as item}
|
|
142
|
+
{#each items as item (item)}
|
|
143
143
|
{@render MenuItem(item)}
|
|
144
144
|
{/each}
|
|
145
145
|
</div>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import Divider from './Divider.svelte';
|
|
4
|
+
import { Body } from '../../../index.js';
|
|
5
|
+
|
|
6
|
+
const { Story } = defineMeta({
|
|
7
|
+
title: 'Containers/Divider',
|
|
8
|
+
component: Divider,
|
|
9
|
+
argTypes: {
|
|
10
|
+
variant: { control: 'select', options: ['full', 'inset', 'wavy'] },
|
|
11
|
+
orientation: { control: 'select', options: ['horizontal', 'vertical'] }
|
|
12
|
+
},
|
|
13
|
+
args: {
|
|
14
|
+
variant: 'full',
|
|
15
|
+
orientation: 'horizontal'
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<Story name="Playground">
|
|
21
|
+
{#snippet template(args)}
|
|
22
|
+
<div class="w-96">
|
|
23
|
+
<Divider variant={args.variant} orientation={args.orientation} />
|
|
24
|
+
</div>
|
|
25
|
+
{/snippet}
|
|
26
|
+
</Story>
|
|
27
|
+
|
|
28
|
+
<Story name="Full" asChild>
|
|
29
|
+
<div class="w-96">
|
|
30
|
+
<Divider variant="full" />
|
|
31
|
+
</div>
|
|
32
|
+
</Story>
|
|
33
|
+
|
|
34
|
+
<Story name="Inset" asChild>
|
|
35
|
+
<div class="w-96">
|
|
36
|
+
<Divider variant="inset" />
|
|
37
|
+
</div>
|
|
38
|
+
</Story>
|
|
39
|
+
|
|
40
|
+
<Story name="Wavy" asChild>
|
|
41
|
+
<div class="w-96">
|
|
42
|
+
<Divider variant="wavy" />
|
|
43
|
+
</div>
|
|
44
|
+
</Story>
|
|
45
|
+
|
|
46
|
+
<Story name="With Label" asChild>
|
|
47
|
+
<div class="w-96">
|
|
48
|
+
<Divider>
|
|
49
|
+
{#snippet children()}
|
|
50
|
+
OR
|
|
51
|
+
{/snippet}
|
|
52
|
+
</Divider>
|
|
53
|
+
</div>
|
|
54
|
+
</Story>
|
|
55
|
+
|
|
56
|
+
<Story name="Vertical" asChild>
|
|
57
|
+
<div class="flex h-24 items-center gap-4">
|
|
58
|
+
<Body>Left</Body>
|
|
59
|
+
<Divider orientation="vertical" />
|
|
60
|
+
<Body>Right</Body>
|
|
61
|
+
</div>
|
|
62
|
+
</Story>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Divider from './Divider.svelte';
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const Divider: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
}, {}, {}, string>;
|
|
18
|
+
type Divider = InstanceType<typeof Divider>;
|
|
19
|
+
export default Divider;
|
|
@@ -9,7 +9,7 @@ Powered by bits-ui for accessibility.
|
|
|
9
9
|
@see https://m3.material.io/components/divider/overview
|
|
10
10
|
-->
|
|
11
11
|
<script lang="ts">
|
|
12
|
-
import { Separator } from 'bits-ui';
|
|
12
|
+
import { Separator, type SeparatorRootProps } from 'bits-ui';
|
|
13
13
|
import clsx from 'clsx';
|
|
14
14
|
import { hr } from './theme.js';
|
|
15
15
|
import type { HrProps } from './types.js';
|
|
@@ -33,7 +33,6 @@ Powered by bits-ui for accessibility.
|
|
|
33
33
|
);
|
|
34
34
|
let insetClass = $derived(variant === 'inset' ? 'mr-2 ml-4' : '');
|
|
35
35
|
|
|
36
|
-
let host = $state<HTMLDivElement | null>(null);
|
|
37
36
|
let width = $state(0);
|
|
38
37
|
let waveHeight = 12;
|
|
39
38
|
let waveThickness = 1;
|
|
@@ -43,23 +42,20 @@ Powered by bits-ui for accessibility.
|
|
|
43
42
|
let right = $derived(Math.max(left, width - waveThickness * 0.5));
|
|
44
43
|
let wavePath = $derived(width > 0 ? linear(waveAmp, waveCenter, left, right, 0) : '');
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
if (variant !== 'wavy' || !host || typeof window === 'undefined') return;
|
|
45
|
+
function trackWidth(node: HTMLElement) {
|
|
48
46
|
const observer = new ResizeObserver((entries) => {
|
|
49
47
|
const entry = entries[0];
|
|
50
48
|
width = Math.max(0, entry?.contentRect.width ?? 0);
|
|
51
49
|
});
|
|
52
|
-
observer.observe(
|
|
53
|
-
return () =>
|
|
54
|
-
|
|
55
|
-
};
|
|
56
|
-
});
|
|
50
|
+
observer.observe(node);
|
|
51
|
+
return () => observer.disconnect();
|
|
52
|
+
}
|
|
57
53
|
</script>
|
|
58
54
|
|
|
59
55
|
{#if variant === 'wavy'}
|
|
60
56
|
<div
|
|
61
57
|
{...restProps}
|
|
62
|
-
|
|
58
|
+
{@attach trackWidth}
|
|
63
59
|
class={clsx('w-full', insetClass, className)}
|
|
64
60
|
role={decorative ? 'none' : 'separator'}
|
|
65
61
|
aria-orientation={orientation}
|
|
@@ -96,5 +92,10 @@ Powered by bits-ui for accessibility.
|
|
|
96
92
|
<div class={lineClass}></div>
|
|
97
93
|
</div>
|
|
98
94
|
{:else}
|
|
99
|
-
<Separator.Root
|
|
95
|
+
<Separator.Root
|
|
96
|
+
{...restProps as SeparatorRootProps}
|
|
97
|
+
{orientation}
|
|
98
|
+
{decorative}
|
|
99
|
+
class={clsx(styling, className)}
|
|
100
|
+
/>
|
|
100
101
|
{/if}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DivAttrs } from '../../../utils/types.js';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HrVariants } from './theme.js';
|
|
4
4
|
/**
|
|
5
5
|
* Props for the Divider component.
|
|
6
6
|
* Dividers are thin lines that group content in lists and layouts.
|
|
7
7
|
*/
|
|
8
|
-
export interface HrProps extends HrVariants,
|
|
8
|
+
export interface HrProps extends HrVariants, DivAttrs {
|
|
9
9
|
/**
|
|
10
10
|
* Optional content to be rendered within the divider (horizontal only).
|
|
11
11
|
* If provided, the divider will show the content centered between two lines.
|
|
@@ -24,4 +24,9 @@ export interface HrProps extends HrVariants, Omit<SeparatorRootProps, 'children'
|
|
|
24
24
|
* @default 'full'
|
|
25
25
|
*/
|
|
26
26
|
variant?: HrVariants['variant'];
|
|
27
|
+
/**
|
|
28
|
+
* Whether the separator is decorative and should be hidden from assistive technologies.
|
|
29
|
+
* @default true
|
|
30
|
+
*/
|
|
31
|
+
decorative?: boolean;
|
|
27
32
|
}
|
|
@@ -62,7 +62,6 @@ SupportingPane provides a layout with a main content area and a supporting side
|
|
|
62
62
|
mobileTriggerClass
|
|
63
63
|
}: SupportingPaneProps = $props();
|
|
64
64
|
|
|
65
|
-
let entered = $state(false);
|
|
66
65
|
let supportingVisible = $state(true);
|
|
67
66
|
let mobileSheetOpen = $state(false);
|
|
68
67
|
let isLargeScreen = $state(false);
|
|
@@ -140,7 +139,6 @@ SupportingPane provides a layout with a main content area and a supporting side
|
|
|
140
139
|
class={supportingCls({
|
|
141
140
|
class: clsx(supportingClass, inlineSupportingClass)
|
|
142
141
|
})}
|
|
143
|
-
data-entered={entered}
|
|
144
142
|
data-position={position}
|
|
145
143
|
>
|
|
146
144
|
{@render supporting()}
|
|
@@ -30,7 +30,7 @@ Use TabContent for content-panel tabs; omit it for navigation (href) tabs.
|
|
|
30
30
|
|
|
31
31
|
<Tabs.Root bind:value {onValueChange} {activationMode}>
|
|
32
32
|
<Tabs.List class={base()}>
|
|
33
|
-
{#each items as item}
|
|
33
|
+
{#each items as item (item)}
|
|
34
34
|
<Tab {...item} {variant} />
|
|
35
35
|
{/each}
|
|
36
36
|
|
|
@@ -33,10 +33,11 @@
|
|
|
33
33
|
<Story name="Playground">
|
|
34
34
|
{#snippet template(args)}
|
|
35
35
|
<div class="flex flex-col gap-4">
|
|
36
|
-
<TabHolder {...args} {items}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
<TabHolder {...args} {items}>
|
|
37
|
+
<TabContent value="flights"><Body>Flights panel content.</Body></TabContent>
|
|
38
|
+
<TabContent value="trips"><Body>Trips panel content.</Body></TabContent>
|
|
39
|
+
<TabContent value="explore"><Body>Explore panel content.</Body></TabContent>
|
|
40
|
+
</TabHolder>
|
|
40
41
|
</div>
|
|
41
42
|
{/snippet}
|
|
42
43
|
</Story>
|
|
@@ -24,6 +24,7 @@ It follows the Material 3 design for time input pickers.
|
|
|
24
24
|
|
|
25
25
|
const cls = timepicker();
|
|
26
26
|
|
|
27
|
+
// svelte-ignore state_referenced_locally (timeValue is a one-time editable seed from `time`, then mutated locally via bind:value)
|
|
27
28
|
let timeValue = $state<Time>(parseTime(time?.includes(':') ? time : '00:00'));
|
|
28
29
|
|
|
29
30
|
const output = $derived(
|
package/dist/utils/Layer.svelte
CHANGED
|
@@ -120,7 +120,8 @@
|
|
|
120
120
|
|
|
121
121
|
document.addEventListener('pointerdown', (e) => {
|
|
122
122
|
if (e.button !== 0) return;
|
|
123
|
-
|
|
123
|
+
if (!(e.target instanceof Element)) return;
|
|
124
|
+
const layer = e.target.closest('.m3-layer');
|
|
124
125
|
if (!layer || !isEnabled(layer)) return;
|
|
125
126
|
const rect = layer.getBoundingClientRect();
|
|
126
127
|
const cancel = createRippleSvg(
|
|
@@ -142,8 +143,8 @@
|
|
|
142
143
|
|
|
143
144
|
document.addEventListener('keydown', (e) => {
|
|
144
145
|
if (e.repeat) return;
|
|
145
|
-
|
|
146
|
-
const layer = target.closest('.m3-layer');
|
|
146
|
+
if (!(e.target instanceof Element)) return;
|
|
147
|
+
const layer = e.target.closest('.m3-layer');
|
|
147
148
|
if (!layer || !isEnabled(layer)) return;
|
|
148
149
|
const isActivate = e.key === 'Enter' || (e.key === ' ' && layer.tagName === 'BUTTON');
|
|
149
150
|
if (!isActivate) return;
|