@noxlovette/material 0.4.8 → 0.5.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/TransitionPatterns.stories.svelte +357 -0
- package/dist/animation/TransitionPatterns.stories.svelte.d.ts +3 -0
- package/dist/animation/containerTransform.d.ts +26 -12
- package/dist/animation/containerTransform.js +22 -138
- package/dist/animation/enterExit.d.ts +21 -3
- package/dist/animation/enterExit.js +69 -22
- package/dist/animation/index.d.ts +1 -1
- package/dist/animation/index.js +1 -1
- package/dist/animation/presence.svelte.d.ts +47 -0
- package/dist/animation/presence.svelte.js +84 -0
- package/dist/animation/sharedAxisTransition.d.ts +35 -37
- package/dist/animation/sharedAxisTransition.js +50 -22
- package/dist/animation/skeleton.d.ts +11 -0
- package/dist/animation/skeleton.js +23 -0
- package/dist/animation/spring.d.ts +61 -0
- package/dist/animation/spring.js +53 -0
- package/dist/animation/springValue.svelte.d.ts +22 -0
- package/dist/animation/springValue.svelte.js +42 -0
- package/dist/animation/transition.d.ts +3 -1
- package/dist/animation/transition.js +3 -1
- package/dist/attachments/clickOutside.d.ts +13 -0
- package/dist/attachments/clickOutside.js +18 -0
- package/dist/attachments/index.d.ts +1 -0
- package/dist/attachments/index.js +1 -0
- package/dist/components/buttons/FAB.svelte +23 -16
- package/dist/components/buttons/FABMenu.svelte +24 -29
- package/dist/components/buttons/FABMenu.svelte.d.ts +2 -1
- package/dist/components/buttons/FABMenuItem.svelte +23 -20
- package/dist/components/buttons/FABMenuItem.svelte.d.ts +5 -1
- package/dist/components/buttons/split-button/SplitButton.svelte +10 -17
- package/dist/components/buttons/split-button/theme.js +1 -1
- package/dist/components/buttons/types.d.ts +3 -3
- package/dist/components/cards/theme.js +1 -1
- package/dist/components/containers/bottom-sheet/BottomSheet.stories.svelte +8 -12
- package/dist/components/containers/bottom-sheet/BottomSheet.svelte +67 -55
- package/dist/components/containers/bottom-sheet/BottomSheet.svelte.d.ts +1 -1
- package/dist/components/containers/bottom-sheet/types.d.ts +8 -2
- package/dist/components/containers/context-menu/ContextMenu.svelte +23 -36
- package/dist/components/containers/context-menu/theme.js +2 -2
- package/dist/components/containers/dialogue/Dialogue.svelte +49 -65
- package/dist/components/containers/link-preview/LinkPreview.svelte +12 -23
- package/dist/components/containers/link-preview/theme.d.ts +3 -3
- package/dist/components/containers/menu/Menu.svelte +14 -21
- package/dist/components/containers/menu/MenuSub.svelte +10 -17
- package/dist/components/containers/pane/DraggablePane.svelte +90 -5
- package/dist/components/containers/pane/DraggablePane.svelte.d.ts +1 -1
- package/dist/components/containers/pane/theme.js +2 -2
- package/dist/components/containers/popover/Popover.svelte +31 -42
- package/dist/components/containers/popover/theme.d.ts +3 -3
- package/dist/components/containers/scroll-area/theme.js +2 -2
- package/dist/components/containers/side-sheet/SideSheet.stories.svelte +10 -15
- package/dist/components/containers/side-sheet/SideSheet.svelte +44 -44
- package/dist/components/containers/side-sheet/SideSheet.svelte.d.ts +4 -3
- package/dist/components/containers/side-sheet/types.d.ts +8 -2
- package/dist/components/date/DateField.svelte +85 -92
- package/dist/components/date/DateField.svelte.d.ts +2 -5
- package/dist/components/date/DateRangeField.svelte +113 -155
- package/dist/components/date/DateRangeField.svelte.d.ts +2 -5
- package/dist/components/date/theme.d.ts +95 -0
- package/dist/components/date/theme.js +99 -14
- package/dist/components/date/types.d.ts +13 -0
- package/dist/components/forms/checkbox/theme.js +2 -2
- package/dist/components/forms/command/theme.d.ts +3 -3
- package/dist/components/forms/command/theme.js +1 -1
- package/dist/components/forms/pin/theme.js +2 -2
- package/dist/components/forms/radio-group/theme.js +2 -2
- package/dist/components/forms/select/Select.svelte +42 -54
- package/dist/components/forms/select/theme.js +4 -4
- package/dist/components/forms/slider/Slider.svelte +144 -126
- package/dist/components/forms/slider/Slider.svelte.d.ts +3 -0
- package/dist/components/forms/slider/theme.d.ts +154 -48
- package/dist/components/forms/slider/theme.js +60 -20
- package/dist/components/forms/slider/types.d.ts +1 -1
- package/dist/components/forms/switch/theme.js +4 -4
- package/dist/components/forms/textfield/Textfield.svelte +1 -1
- package/dist/components/forms/textfield/theme.d.ts +9 -0
- package/dist/components/forms/textfield/theme.js +26 -9
- package/dist/components/forms/toggle-group/theme.js +1 -1
- package/dist/components/forms/tooltip/Tooltip.svelte +24 -35
- package/dist/components/nav/breadcrumb/theme.js +1 -1
- package/dist/components/nav/navbar/theme.js +2 -2
- package/dist/components/nav/rail/Rail.svelte +4 -5
- package/dist/components/nav/rail/theme.js +7 -7
- package/dist/components/nav/tabs/theme.js +1 -1
- package/dist/components/progress/CircularProgress.svelte +78 -4
- package/dist/components/progress/CircularProgress.svelte.d.ts +5 -0
- package/dist/components/progress/LinearProgress.svelte +70 -7
- package/dist/components/progress/LinearProgress.svelte.d.ts +5 -0
- package/dist/components/progress/WavyLinearProgress.svelte +27 -3
- package/dist/components/progress/WavyLinearProgress.svelte.d.ts +3 -0
- package/dist/components/progress/_wavy.d.ts +2 -0
- package/dist/components/progress/_wavy.js +3 -1
- package/dist/components/snackbar/Snackbar.svelte +13 -17
- package/dist/components/table/TableBody.svelte +3 -16
- package/dist/components/table/TableBody.svelte.d.ts +1 -5
- package/dist/components/table/TableHeader.svelte +1 -1
- package/dist/components/table/theme.js +1 -1
- package/dist/components/table/types.d.ts +0 -7
- package/dist/components/time/TimeField.stories.svelte +41 -0
- package/dist/components/time/TimeField.stories.svelte.d.ts +19 -0
- package/dist/components/time/TimeField.svelte +62 -61
- package/dist/components/toolbar/theme.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/styles/component.css +21 -22
- package/dist/styles/motion.css +317 -38
- package/dist/utils/Layer.svelte +16 -29
- package/dist/utils/icon/LoadingIndicator.svelte +61 -22
- package/dist/utils/icon/loadingShapes.d.ts +1 -0
- package/dist/utils/icon/loadingShapes.js +15 -0
- package/package.json +5 -2
- package/dist/actions/clickOutside.d.ts +0 -3
- package/dist/actions/clickOutside.js +0 -13
- package/dist/actions/floating.d.ts +0 -20
- package/dist/actions/floating.js +0 -87
- package/dist/actions/index.d.ts +0 -6
- package/dist/actions/index.js +0 -6
- package/dist/actions/keyboard.d.ts +0 -3
- package/dist/actions/keyboard.js +0 -14
- package/dist/actions/portal.d.ts +0 -3
- package/dist/actions/portal.js +0 -8
- package/dist/actions/positionFloating.d.ts +0 -10
- package/dist/actions/positionFloating.js +0 -59
- package/dist/actions/rovingFocusGroup.d.ts +0 -20
- package/dist/actions/rovingFocusGroup.js +0 -82
- package/dist/animation/easing.d.ts +0 -6
- package/dist/animation/easing.js +0 -78
- package/dist/animation/outroClass.d.ts +0 -3
- package/dist/animation/outroClass.js +0 -20
- package/dist/animation/transitionTypes.d.ts +0 -8
- package/dist/animation/transitionTypes.js +0 -1
|
@@ -5,11 +5,11 @@ Popovers display rich content in a non-modal overlay anchored to a trigger eleme
|
|
|
5
5
|
@see https://m3.material.io/components/dialogs/overview (non-modal surface variant)
|
|
6
6
|
-->
|
|
7
7
|
<script lang="ts">
|
|
8
|
+
import { enterExit, presence } from '../../../animation/index.js';
|
|
8
9
|
import { Popover } from 'bits-ui';
|
|
9
10
|
import clsx from 'clsx';
|
|
10
11
|
import { popover } from './theme.js';
|
|
11
12
|
import type { PopoverProps } from './types.js';
|
|
12
|
-
import { enterExit, easeEmphasizedDecel, easeEmphasizedAccel } from '../../../animation/index.js';
|
|
13
13
|
import ButtonIcon from '../../buttons/ButtonIcon.svelte';
|
|
14
14
|
import Title from '../../typography/title/Title.svelte';
|
|
15
15
|
let {
|
|
@@ -35,49 +35,38 @@ Popovers display rich content in a non-modal overlay anchored to a trigger eleme
|
|
|
35
35
|
</Popover.Trigger>
|
|
36
36
|
|
|
37
37
|
<Popover.Portal>
|
|
38
|
-
<Popover.Content
|
|
38
|
+
<Popover.Content {side} {align} {sideOffset}>
|
|
39
39
|
{#snippet child({ wrapperProps, props, open: isOpen })}
|
|
40
|
-
{
|
|
41
|
-
<div
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
variant="text"
|
|
69
|
-
size="sm"
|
|
70
|
-
/>
|
|
71
|
-
</div>
|
|
72
|
-
{/snippet}
|
|
73
|
-
</Popover.Close>
|
|
74
|
-
{/if}
|
|
75
|
-
</div>
|
|
76
|
-
{/if}
|
|
77
|
-
{@render children()}
|
|
78
|
-
</div>
|
|
40
|
+
<div {...wrapperProps} class={wrapperProps.class as any}>
|
|
41
|
+
<div
|
|
42
|
+
{...props}
|
|
43
|
+
class={base({ class: clsx(className, props.class as any) })}
|
|
44
|
+
{@attach presence(() => isOpen, enterExit.scale)}
|
|
45
|
+
>
|
|
46
|
+
{#if title || showClose}
|
|
47
|
+
<div class={header()}>
|
|
48
|
+
{#if title}
|
|
49
|
+
<Title class={titleCls()}>{title}</Title>
|
|
50
|
+
{/if}
|
|
51
|
+
{#if showClose}
|
|
52
|
+
<Popover.Close>
|
|
53
|
+
{#snippet child({ props: closeProps })}
|
|
54
|
+
<div class={close()}>
|
|
55
|
+
<ButtonIcon
|
|
56
|
+
{...closeProps}
|
|
57
|
+
iconProps={{ name: 'close' }}
|
|
58
|
+
variant="text"
|
|
59
|
+
size="sm"
|
|
60
|
+
/>
|
|
61
|
+
</div>
|
|
62
|
+
{/snippet}
|
|
63
|
+
</Popover.Close>
|
|
64
|
+
{/if}
|
|
65
|
+
</div>
|
|
66
|
+
{/if}
|
|
67
|
+
{@render children()}
|
|
79
68
|
</div>
|
|
80
|
-
|
|
69
|
+
</div>
|
|
81
70
|
{/snippet}
|
|
82
71
|
</Popover.Content>
|
|
83
72
|
</Popover.Portal>
|
|
@@ -3,21 +3,21 @@ export type PopoverVariants = VariantProps<typeof popover>;
|
|
|
3
3
|
export declare const popover: import("tailwind-variants").TVReturnType<{
|
|
4
4
|
[key: string]: {
|
|
5
5
|
[key: string]: import("tailwind-variants").ClassValue | {
|
|
6
|
+
title?: import("tailwind-variants").ClassValue;
|
|
6
7
|
close?: import("tailwind-variants").ClassValue;
|
|
7
8
|
base?: import("tailwind-variants").ClassValue;
|
|
8
9
|
body?: import("tailwind-variants").ClassValue;
|
|
9
10
|
header?: import("tailwind-variants").ClassValue;
|
|
10
|
-
title?: import("tailwind-variants").ClassValue;
|
|
11
11
|
};
|
|
12
12
|
};
|
|
13
13
|
} | {
|
|
14
14
|
[x: string]: {
|
|
15
15
|
[x: string]: import("tailwind-variants").ClassValue | {
|
|
16
|
+
title?: import("tailwind-variants").ClassValue;
|
|
16
17
|
close?: import("tailwind-variants").ClassValue;
|
|
17
18
|
base?: import("tailwind-variants").ClassValue;
|
|
18
19
|
body?: import("tailwind-variants").ClassValue;
|
|
19
20
|
header?: import("tailwind-variants").ClassValue;
|
|
20
|
-
title?: import("tailwind-variants").ClassValue;
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
} | {}, {
|
|
@@ -29,11 +29,11 @@ export declare const popover: import("tailwind-variants").TVReturnType<{
|
|
|
29
29
|
}, undefined, {
|
|
30
30
|
[key: string]: {
|
|
31
31
|
[key: string]: import("tailwind-variants").ClassValue | {
|
|
32
|
+
title?: import("tailwind-variants").ClassValue;
|
|
32
33
|
close?: import("tailwind-variants").ClassValue;
|
|
33
34
|
base?: import("tailwind-variants").ClassValue;
|
|
34
35
|
body?: import("tailwind-variants").ClassValue;
|
|
35
36
|
header?: import("tailwind-variants").ClassValue;
|
|
36
|
-
title?: import("tailwind-variants").ClassValue;
|
|
37
37
|
};
|
|
38
38
|
};
|
|
39
39
|
} | {}, {
|
|
@@ -3,8 +3,8 @@ export const scrollArea = tv({
|
|
|
3
3
|
slots: {
|
|
4
4
|
root: 'relative overflow-hidden',
|
|
5
5
|
viewport: 'size-full rounded-[inherit]',
|
|
6
|
-
scrollbar: 'flex touch-none select-none transition-colors
|
|
7
|
-
thumb: 'relative flex-1 rounded-full bg-md-sys-color-outline-variant hover:bg-md-sys-color-secondary active:bg-md-sys-color-secondary transition-colors
|
|
6
|
+
scrollbar: 'flex touch-none select-none transition-colors md-sys-motion-fast-effects',
|
|
7
|
+
thumb: 'relative flex-1 rounded-full bg-md-sys-color-outline-variant hover:bg-md-sys-color-secondary active:bg-md-sys-color-secondary transition-colors md-sys-motion-fast-effects',
|
|
8
8
|
corner: 'bg-md-sys-color-surface-container-highest'
|
|
9
9
|
},
|
|
10
10
|
variants: {
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
SideSheet
|
|
3
|
-
|
|
4
|
-
({#if open}<SideSheet ...>{/if}), same as BottomSheet. `close` is a required callback the
|
|
5
|
-
sheet invokes on Esc or backdrop click — the consumer is expected to flip its own `open` flag
|
|
6
|
-
to false in response.
|
|
2
|
+
SideSheet is controlled with `bind:open`: it dismisses itself (close button, Esc, backdrop
|
|
3
|
+
click) by setting `open` to false, and stays mounted until its exit animation finishes.
|
|
7
4
|
-->
|
|
8
5
|
<script module lang="ts">
|
|
9
6
|
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
@@ -31,16 +28,14 @@
|
|
|
31
28
|
{#snippet template(args)}
|
|
32
29
|
<div class="p-6">
|
|
33
30
|
<Button onclick={() => (playgroundOpen = true)}>Show side sheet</Button>
|
|
34
|
-
{
|
|
35
|
-
<
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
</SideSheet>
|
|
43
|
-
{/if}
|
|
31
|
+
<SideSheet headline={args.headline} bind:open={playgroundOpen}>
|
|
32
|
+
<div class="flex flex-col gap-3 px-6 pb-6">
|
|
33
|
+
<Body class="text-md-sys-color-on-surface-variant">
|
|
34
|
+
Supplementary content and actions, anchored to the edge of the screen while the main
|
|
35
|
+
content stays visible.
|
|
36
|
+
</Body>
|
|
37
|
+
</div>
|
|
38
|
+
</SideSheet>
|
|
44
39
|
</div>
|
|
45
40
|
{/snippet}
|
|
46
41
|
</Story>
|
|
@@ -4,69 +4,69 @@ Side sheets are supplementary surfaces which are anchored to the edge of the scr
|
|
|
4
4
|
|
|
5
5
|
Like BottomSheet, SideSheet owns its own overlay: it renders as a native `<dialog>` pinned to
|
|
6
6
|
the right edge of the screen, dims the rest of the app behind a backdrop, and slides in/out.
|
|
7
|
-
|
|
8
|
-
rendering
|
|
7
|
+
Visibility is controlled by `bind:open`; the sheet stays mounted until its exit animation
|
|
8
|
+
finishes. Conditionally rendering it ({#if open}<SideSheet close={…} />{/if}) still works, but
|
|
9
|
+
skips the exit animation.
|
|
9
10
|
|
|
10
11
|
@see https://m3.material.io/components/side-sheets/guidelines
|
|
11
12
|
-->
|
|
12
13
|
<script lang="ts">
|
|
13
14
|
import type { SideSheetProps } from './types.js';
|
|
14
|
-
import type { TransitionConfig } from 'svelte/transition';
|
|
15
15
|
import ButtonIcon from '../../buttons/ButtonIcon.svelte';
|
|
16
|
-
import {
|
|
17
|
-
import { outroClass } from '../../../animation/outroClass.js';
|
|
16
|
+
import { enterExit, Presence } from '../../../animation/index.js';
|
|
18
17
|
|
|
19
|
-
let { headline, children, close }: SideSheetProps = $props();
|
|
18
|
+
let { headline, children, open = $bindable(true), close }: SideSheetProps = $props();
|
|
20
19
|
|
|
21
|
-
const
|
|
20
|
+
const sheet = new Presence(() => open);
|
|
22
21
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
duration: options.duration,
|
|
30
|
-
easing: options.easing,
|
|
31
|
-
css: (t) => `transform: translateX(${(1 - t) * width}px)`
|
|
32
|
-
};
|
|
22
|
+
const showModal = (node: HTMLDialogElement) => node.showModal();
|
|
23
|
+
|
|
24
|
+
const dismiss = () => {
|
|
25
|
+
open = false;
|
|
26
|
+
close?.();
|
|
33
27
|
};
|
|
34
28
|
</script>
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
30
|
+
{#if sheet.mounted}
|
|
31
|
+
<dialog
|
|
32
|
+
class="bg-md-sys-color-surface-container-low text-md-sys-color-on-surface fixed inset-y-0 right-0 left-auto m-0 h-full w-full max-w-sm rounded-l-md"
|
|
33
|
+
data-state={open ? 'open' : 'closed'}
|
|
34
|
+
{@attach showModal}
|
|
35
|
+
{@attach sheet.attach(enterExit.sideSheet)}
|
|
36
|
+
oncancel={(e) => {
|
|
37
|
+
e.preventDefault();
|
|
38
|
+
dismiss();
|
|
39
|
+
}}
|
|
40
|
+
onmousedown={(e) => {
|
|
41
|
+
if (e.target != e.currentTarget) return;
|
|
42
|
+
dismiss();
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
<div class="flex h-full flex-col">
|
|
46
|
+
<div class="flex items-center justify-between p-6">
|
|
47
|
+
<span class="md-sys-typescale-title-large text-md-sys-color-on-surface-variant"
|
|
48
|
+
>{headline}</span
|
|
49
|
+
>
|
|
50
|
+
<ButtonIcon type="button" variant="text" iconProps={{ name: 'close' }} onclick={dismiss} />
|
|
51
|
+
</div>
|
|
52
|
+
{@render children()}
|
|
57
53
|
</div>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
</dialog>
|
|
54
|
+
</dialog>
|
|
55
|
+
{/if}
|
|
61
56
|
|
|
62
57
|
<style>
|
|
63
58
|
dialog::backdrop {
|
|
64
59
|
background-color: rgba(0, 0, 0, 0.5);
|
|
65
|
-
animation: backdrop
|
|
60
|
+
animation: backdrop var(--md-sys-motion-duration-effects-spring)
|
|
61
|
+
var(--md-sys-motion-timing-function-effects-spring);
|
|
62
|
+
}
|
|
63
|
+
dialog[data-state='closed'] {
|
|
64
|
+
pointer-events: none;
|
|
66
65
|
}
|
|
67
|
-
dialog
|
|
66
|
+
dialog[data-state='closed']::backdrop {
|
|
68
67
|
background-color: transparent;
|
|
69
|
-
animation: backdropReverse
|
|
68
|
+
animation: backdropReverse var(--md-sys-motion-duration-fast-effects-spring)
|
|
69
|
+
var(--md-sys-motion-timing-function-fast-effects-spring);
|
|
70
70
|
}
|
|
71
71
|
@keyframes backdrop {
|
|
72
72
|
from {
|
|
@@ -4,11 +4,12 @@ import type { SideSheetProps } from './types.js';
|
|
|
4
4
|
*
|
|
5
5
|
* Like BottomSheet, SideSheet owns its own overlay: it renders as a native `<dialog>` pinned to
|
|
6
6
|
* the right edge of the screen, dims the rest of the app behind a backdrop, and slides in/out.
|
|
7
|
-
*
|
|
8
|
-
* rendering
|
|
7
|
+
* Visibility is controlled by `bind:open`; the sheet stays mounted until its exit animation
|
|
8
|
+
* finishes. Conditionally rendering it ({#if open}<SideSheet close={…} />{/if}) still works, but
|
|
9
|
+
* skips the exit animation.
|
|
9
10
|
*
|
|
10
11
|
* @see https://m3.material.io/components/side-sheets/guidelines
|
|
11
12
|
*/
|
|
12
|
-
declare const SideSheet: import("svelte").Component<SideSheetProps, {}, "">;
|
|
13
|
+
declare const SideSheet: import("svelte").Component<SideSheetProps, {}, "open">;
|
|
13
14
|
type SideSheet = ReturnType<typeof SideSheet>;
|
|
14
15
|
export default SideSheet;
|
|
@@ -12,7 +12,13 @@ export interface SideSheetProps {
|
|
|
12
12
|
*/
|
|
13
13
|
children: Snippet;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* Whether the sheet is shown. Bind it (`bind:open`) so the sheet can play its exit animation
|
|
16
|
+
* before unmounting.
|
|
17
|
+
* @default true
|
|
16
18
|
*/
|
|
17
|
-
|
|
19
|
+
open?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Called when the user dismisses the sheet (close button, Esc, backdrop click).
|
|
22
|
+
*/
|
|
23
|
+
close?: () => void;
|
|
18
24
|
}
|
|
@@ -1,40 +1,44 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
@component
|
|
3
|
-
DateField is a text field that allows users to enter a date or pick it from a calendar.
|
|
3
|
+
DateField is a text field that allows users to enter a date or pick it from a docked calendar.
|
|
4
4
|
|
|
5
5
|
@see https://m3.material.io/components/date-pickers/guidelines
|
|
6
6
|
-->
|
|
7
7
|
<script lang="ts">
|
|
8
|
-
import { DatePicker } from 'bits-ui';
|
|
8
|
+
import { DatePicker, useId } from 'bits-ui';
|
|
9
|
+
import { enterExit, presence } from '../../animation/index.js';
|
|
9
10
|
import ButtonIcon from '../buttons/ButtonIcon.svelte';
|
|
10
11
|
import Icon from '../../utils/icon/Icon.svelte';
|
|
11
12
|
import Layer from '../../utils/Layer.svelte';
|
|
12
13
|
import type { DateFieldProps } from './types';
|
|
13
|
-
import { dateField } from './theme';
|
|
14
|
+
import { dateCalendar, dateField, dateSegment } from './theme';
|
|
14
15
|
|
|
15
16
|
let {
|
|
16
17
|
value = $bindable(),
|
|
17
18
|
label,
|
|
18
|
-
id,
|
|
19
|
+
id = useId(),
|
|
19
20
|
required = false,
|
|
20
21
|
disabled = false,
|
|
21
22
|
error = false,
|
|
22
23
|
variant = 'outlined',
|
|
23
24
|
supportingText,
|
|
24
25
|
name,
|
|
26
|
+
locale,
|
|
27
|
+
weekStartsOn,
|
|
25
28
|
leadingIconProps
|
|
26
|
-
}: DateFieldProps
|
|
29
|
+
}: DateFieldProps = $props();
|
|
27
30
|
|
|
28
31
|
const cls = $derived(dateField({ disabled, error, variant }));
|
|
32
|
+
const calendar = dateCalendar();
|
|
29
33
|
</script>
|
|
30
34
|
|
|
31
35
|
<DatePicker.Root
|
|
32
36
|
bind:value
|
|
33
|
-
weekStartsOn
|
|
37
|
+
{weekStartsOn}
|
|
34
38
|
{required}
|
|
35
39
|
{disabled}
|
|
36
|
-
locale
|
|
37
|
-
weekdayFormat="
|
|
40
|
+
{locale}
|
|
41
|
+
weekdayFormat="narrow"
|
|
38
42
|
fixedWeeks
|
|
39
43
|
>
|
|
40
44
|
<div class="relative w-full">
|
|
@@ -47,45 +51,34 @@ DateField is a text field that allows users to enter a date or pick it from a ca
|
|
|
47
51
|
<DatePicker.Input class={cls.input()} {name} id={id ?? undefined}>
|
|
48
52
|
{#snippet children({ segments })}
|
|
49
53
|
<div class={cls.segments()}>
|
|
50
|
-
<div class="flex
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
{
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
</DatePicker.Segment>
|
|
60
|
-
{:else}
|
|
61
|
-
<DatePicker.Segment
|
|
62
|
-
{part}
|
|
63
|
-
class="text-md-sys-color-on-surface hover:bg-md-sys-color-on-surface/8 focus:bg-md-sys-color-primary-container focus:text-md-sys-color-on-primary-container focus:outline-md-sys-color-primary
|
|
64
|
-
aria-[valuetext=Empty]:text-md-sys-color-on-surface-variant cursor-default
|
|
65
|
-
rounded-xs
|
|
66
|
-
px-1
|
|
67
|
-
py-0.5
|
|
68
|
-
transition-colors
|
|
69
|
-
duration-100 select-none focus:outline-2
|
|
70
|
-
focus-visible:ring-0! focus-visible:ring-offset-0!"
|
|
71
|
-
>
|
|
72
|
-
{value}
|
|
73
|
-
</DatePicker.Segment>
|
|
74
|
-
{/if}
|
|
75
|
-
{/each}
|
|
76
|
-
</div>
|
|
54
|
+
<div class="flex">
|
|
55
|
+
{#each segments as { part, value: segment }}
|
|
56
|
+
<DatePicker.Segment
|
|
57
|
+
{part}
|
|
58
|
+
class={dateSegment({ part: part === 'literal' ? 'literal' : 'value' })}
|
|
59
|
+
>
|
|
60
|
+
{segment}
|
|
61
|
+
</DatePicker.Segment>
|
|
62
|
+
{/each}
|
|
77
63
|
</div>
|
|
78
64
|
</div>
|
|
79
65
|
{/snippet}
|
|
80
66
|
</DatePicker.Input>
|
|
81
67
|
|
|
82
|
-
<
|
|
68
|
+
<DatePicker.Label class={cls.label()}>
|
|
83
69
|
{label}{#if required}<span class={cls.requiredAsterisk()} aria-hidden="true">*</span>{/if}
|
|
84
|
-
</
|
|
70
|
+
</DatePicker.Label>
|
|
85
71
|
</div>
|
|
86
72
|
|
|
87
|
-
<DatePicker.Trigger
|
|
88
|
-
|
|
73
|
+
<DatePicker.Trigger>
|
|
74
|
+
{#snippet child({ props })}
|
|
75
|
+
<ButtonIcon
|
|
76
|
+
{...props}
|
|
77
|
+
{disabled}
|
|
78
|
+
class={cls.trailingIcon()}
|
|
79
|
+
iconProps={{ name: 'calendar_month' }}
|
|
80
|
+
/>
|
|
81
|
+
{/snippet}
|
|
89
82
|
</DatePicker.Trigger>
|
|
90
83
|
|
|
91
84
|
{#if variant === 'outlined'}
|
|
@@ -103,62 +96,62 @@ DateField is a text field that allows users to enter a date or pick it from a ca
|
|
|
103
96
|
</div>
|
|
104
97
|
{/if}
|
|
105
98
|
</div>
|
|
106
|
-
<DatePicker.Portal>
|
|
107
|
-
<DatePicker.Content sideOffset={6} class="z-[100]">
|
|
108
|
-
<DatePicker.Calendar
|
|
109
|
-
class="bg-md-sys-color-surface-container-high shadow-elevation-3 h-104 w-90 rounded-lg p-6"
|
|
110
|
-
>
|
|
111
|
-
{#snippet children({ months, weekdays })}
|
|
112
|
-
<DatePicker.Header
|
|
113
|
-
class="text-md-sys-color-on-surface-variant z-10 flex w-full items-center justify-between pb-7.5"
|
|
114
|
-
>
|
|
115
|
-
<DatePicker.PrevButton>
|
|
116
|
-
<ButtonIcon type="button" iconProps={{ name: 'chevron_left' }} />
|
|
117
|
-
</DatePicker.PrevButton>
|
|
118
|
-
<DatePicker.Heading class="md-sys-typescale-label-large" />
|
|
119
|
-
<DatePicker.NextButton>
|
|
120
|
-
<ButtonIcon type="button" iconProps={{ name: 'chevron_right' }} />
|
|
121
|
-
</DatePicker.NextButton>
|
|
122
|
-
</DatePicker.Header>
|
|
123
99
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
<DatePicker.Day
|
|
147
|
-
class="group data-disabled:text-md-sys-color-on-surface/38 data-selected:bg-md-sys-color-primary data-selected:text-md-sys-color-on-primary data-unavailable:text-md-sys-color-on-surface/38 relative flex size-10 items-center justify-center rounded-full bg-transparent p-0 data-disabled:cursor-not-allowed data-outside-month:pointer-events-none data-unavailable:line-through"
|
|
148
|
-
>
|
|
149
|
-
<Layer />
|
|
100
|
+
<DatePicker.Portal>
|
|
101
|
+
<DatePicker.Content sideOffset={4} align="start">
|
|
102
|
+
{#snippet child({ wrapperProps, props, open })}
|
|
103
|
+
<div {...wrapperProps}>
|
|
104
|
+
<div {...props} {@attach presence(() => open, enterExit.scale)}>
|
|
105
|
+
<DatePicker.Calendar class={calendar.surface()}>
|
|
106
|
+
{#snippet children({ months, weekdays })}
|
|
107
|
+
<DatePicker.Header class={calendar.header()}>
|
|
108
|
+
<DatePicker.Heading class={calendar.heading()} />
|
|
109
|
+
<div class={calendar.nav()}>
|
|
110
|
+
<DatePicker.PrevButton>
|
|
111
|
+
{#snippet child({ props })}
|
|
112
|
+
<ButtonIcon {...props} iconProps={{ name: 'chevron_left' }} />
|
|
113
|
+
{/snippet}
|
|
114
|
+
</DatePicker.PrevButton>
|
|
115
|
+
<DatePicker.NextButton>
|
|
116
|
+
{#snippet child({ props })}
|
|
117
|
+
<ButtonIcon {...props} iconProps={{ name: 'chevron_right' }} />
|
|
118
|
+
{/snippet}
|
|
119
|
+
</DatePicker.NextButton>
|
|
120
|
+
</div>
|
|
121
|
+
</DatePicker.Header>
|
|
150
122
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
123
|
+
{#each months as month (month.value.toString())}
|
|
124
|
+
<DatePicker.Grid class={calendar.grid()}>
|
|
125
|
+
<DatePicker.GridHead>
|
|
126
|
+
<DatePicker.GridRow class={calendar.row()}>
|
|
127
|
+
{#each weekdays as day, i (i)}
|
|
128
|
+
<DatePicker.HeadCell class={calendar.weekday()}>
|
|
129
|
+
{day}
|
|
130
|
+
</DatePicker.HeadCell>
|
|
131
|
+
{/each}
|
|
132
|
+
</DatePicker.GridRow>
|
|
133
|
+
</DatePicker.GridHead>
|
|
134
|
+
<DatePicker.GridBody>
|
|
135
|
+
{#each month.weeks as weekDates, i (i)}
|
|
136
|
+
<DatePicker.GridRow class={calendar.row()}>
|
|
137
|
+
{#each weekDates as date (date.toString())}
|
|
138
|
+
<DatePicker.Cell {date} month={month.value} class={calendar.cell()}>
|
|
139
|
+
<DatePicker.Day class={calendar.day()}>
|
|
140
|
+
<Layer />
|
|
141
|
+
{date.day}
|
|
142
|
+
</DatePicker.Day>
|
|
143
|
+
</DatePicker.Cell>
|
|
144
|
+
{/each}
|
|
145
|
+
</DatePicker.GridRow>
|
|
146
|
+
{/each}
|
|
147
|
+
</DatePicker.GridBody>
|
|
148
|
+
</DatePicker.Grid>
|
|
156
149
|
{/each}
|
|
157
|
-
|
|
158
|
-
</DatePicker.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
150
|
+
{/snippet}
|
|
151
|
+
</DatePicker.Calendar>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
{/snippet}
|
|
162
155
|
</DatePicker.Content>
|
|
163
156
|
</DatePicker.Portal>
|
|
164
157
|
</DatePicker.Root>
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import type { DateFieldProps } from './types';
|
|
2
|
-
type $$ComponentProps = DateFieldProps & {
|
|
3
|
-
leadingIconProps?: any;
|
|
4
|
-
};
|
|
5
2
|
/**
|
|
6
|
-
* DateField is a text field that allows users to enter a date or pick it from a calendar.
|
|
3
|
+
* DateField is a text field that allows users to enter a date or pick it from a docked calendar.
|
|
7
4
|
*
|
|
8
5
|
* @see https://m3.material.io/components/date-pickers/guidelines
|
|
9
6
|
*/
|
|
10
|
-
declare const DateField: import("svelte").Component
|
|
7
|
+
declare const DateField: import("svelte").Component<DateFieldProps, {}, "value">;
|
|
11
8
|
type DateField = ReturnType<typeof DateField>;
|
|
12
9
|
export default DateField;
|