@noxlovette/material 0.4.8 → 0.5.1
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/Shapes.stories.svelte +56 -0
- package/dist/animation/Shapes.stories.svelte.d.ts +3 -0
- package/dist/animation/TransitionPatterns.stories.svelte +359 -0
- package/dist/animation/TransitionPatterns.stories.svelte.d.ts +3 -0
- package/dist/animation/containerTransform.d.ts +35 -12
- package/dist/animation/containerTransform.js +31 -138
- package/dist/animation/enterExit.d.ts +30 -3
- package/dist/animation/enterExit.js +69 -22
- package/dist/animation/index.d.ts +2 -1
- package/dist/animation/index.js +2 -1
- package/dist/animation/presence.svelte.d.ts +47 -0
- package/dist/animation/presence.svelte.js +84 -0
- package/dist/animation/shapeMorph.svelte.d.ts +52 -0
- package/dist/animation/shapeMorph.svelte.js +112 -0
- package/dist/animation/shapesAnimatableSmall.d.ts +28 -22
- package/dist/animation/shapesAnimatableSmall.js +32 -23
- package/dist/animation/sharedAxisTransition.d.ts +57 -37
- package/dist/animation/sharedAxisTransition.js +74 -22
- package/dist/animation/skeleton.d.ts +16 -0
- package/dist/animation/skeleton.js +28 -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 +99 -92
- package/dist/components/date/DateField.svelte.d.ts +4 -5
- package/dist/components/date/DateRangeField.svelte +127 -155
- package/dist/components/date/DateRangeField.svelte.d.ts +4 -5
- package/dist/components/date/calendarMotion.d.ts +9 -0
- package/dist/components/date/calendarMotion.js +23 -0
- package/dist/components/date/theme.d.ts +95 -0
- package/dist/components/date/theme.js +103 -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 +12 -0
- package/dist/components/forms/textfield/theme.js +30 -10
- 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/TabHolder.svelte +29 -3
- package/dist/components/nav/tabs/TabHolder.svelte.d.ts +3 -1
- 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 +69 -62
- package/dist/components/time/TimeField.svelte.d.ts +6 -0
- package/dist/components/time/TimepickerInput.svelte +8 -4
- package/dist/components/time/types.d.ts +11 -1
- 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 +16 -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 @@ Link Previews display a preview of a link's content when hovered.
|
|
|
5
5
|
@see https://bits-ui.com/docs/components/link-preview
|
|
6
6
|
-->
|
|
7
7
|
<script lang="ts">
|
|
8
|
+
import { enterExit, presence } from '../../../animation/index.js';
|
|
8
9
|
import { LinkPreview } from 'bits-ui';
|
|
9
10
|
import clsx from 'clsx';
|
|
10
11
|
import { linkPreview } from './theme.js';
|
|
11
12
|
import type { LinkPreviewProps } from './types.js';
|
|
12
|
-
import { enterExit, easeEmphasizedDecel, easeEmphasizedAccel } from '../../../animation/index.js';
|
|
13
13
|
import { Layer } from '../../../utils/index.js';
|
|
14
14
|
|
|
15
15
|
let {
|
|
@@ -33,31 +33,20 @@ Link Previews display a preview of a link's content when hovered.
|
|
|
33
33
|
</LinkPreview.Trigger>
|
|
34
34
|
|
|
35
35
|
<LinkPreview.Portal>
|
|
36
|
-
<LinkPreview.Content
|
|
36
|
+
<LinkPreview.Content {side} {align} {sideOffset}>
|
|
37
37
|
{#snippet child({ wrapperProps, props, open: isOpen })}
|
|
38
|
-
{
|
|
39
|
-
<div
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}}
|
|
48
|
-
out:enterExit={{
|
|
49
|
-
duration: 150,
|
|
50
|
-
easing: easeEmphasizedAccel,
|
|
51
|
-
mode: 'scale'
|
|
52
|
-
}}
|
|
53
|
-
>
|
|
54
|
-
<Layer />
|
|
55
|
-
<div class={content()}>
|
|
56
|
-
{@render children()}
|
|
57
|
-
</div>
|
|
38
|
+
<div {...wrapperProps}>
|
|
39
|
+
<div
|
|
40
|
+
{...props}
|
|
41
|
+
class={base({ class: clsx(className) })}
|
|
42
|
+
{@attach presence(() => isOpen, enterExit.scale)}
|
|
43
|
+
>
|
|
44
|
+
<Layer />
|
|
45
|
+
<div class={content()}>
|
|
46
|
+
{@render children()}
|
|
58
47
|
</div>
|
|
59
48
|
</div>
|
|
60
|
-
|
|
49
|
+
</div>
|
|
61
50
|
{/snippet}
|
|
62
51
|
</LinkPreview.Content>
|
|
63
52
|
</LinkPreview.Portal>
|
|
@@ -3,15 +3,15 @@ export type LinkPreviewVariants = VariantProps<typeof linkPreview>;
|
|
|
3
3
|
export declare const linkPreview: import("tailwind-variants").TVReturnType<{
|
|
4
4
|
[key: string]: {
|
|
5
5
|
[key: string]: import("tailwind-variants").ClassValue | {
|
|
6
|
-
base?: import("tailwind-variants").ClassValue;
|
|
7
6
|
content?: import("tailwind-variants").ClassValue;
|
|
7
|
+
base?: import("tailwind-variants").ClassValue;
|
|
8
8
|
};
|
|
9
9
|
};
|
|
10
10
|
} | {
|
|
11
11
|
[x: string]: {
|
|
12
12
|
[x: string]: import("tailwind-variants").ClassValue | {
|
|
13
|
-
base?: import("tailwind-variants").ClassValue;
|
|
14
13
|
content?: import("tailwind-variants").ClassValue;
|
|
14
|
+
base?: import("tailwind-variants").ClassValue;
|
|
15
15
|
};
|
|
16
16
|
};
|
|
17
17
|
} | {}, {
|
|
@@ -20,8 +20,8 @@ export declare const linkPreview: import("tailwind-variants").TVReturnType<{
|
|
|
20
20
|
}, undefined, {
|
|
21
21
|
[key: string]: {
|
|
22
22
|
[key: string]: import("tailwind-variants").ClassValue | {
|
|
23
|
-
base?: import("tailwind-variants").ClassValue;
|
|
24
23
|
content?: import("tailwind-variants").ClassValue;
|
|
24
|
+
base?: import("tailwind-variants").ClassValue;
|
|
25
25
|
};
|
|
26
26
|
};
|
|
27
27
|
} | {}, {
|
|
@@ -16,11 +16,10 @@ Contrast with `MenuItem` (a single interactive row inside the panel) and
|
|
|
16
16
|
@see https://m3.material.io/components/menus/guidelines
|
|
17
17
|
-->
|
|
18
18
|
<script lang="ts">
|
|
19
|
+
import { enterExit, presence } from '../../../animation/index.js';
|
|
19
20
|
import { DropdownMenu } from 'bits-ui';
|
|
20
21
|
import clsx from 'clsx';
|
|
21
22
|
import Button from '../../buttons/Button.svelte';
|
|
22
|
-
import { enterExit } from '../../../animation/enterExit.js';
|
|
23
|
-
import { easeEmphasizedDecel } from '../../../animation/easing.js';
|
|
24
23
|
import type { MenuProps } from './types.js';
|
|
25
24
|
|
|
26
25
|
let {
|
|
@@ -45,27 +44,21 @@ Contrast with `MenuItem` (a single interactive row inside the panel) and
|
|
|
45
44
|
</DropdownMenu.Trigger>
|
|
46
45
|
|
|
47
46
|
<DropdownMenu.Portal>
|
|
48
|
-
<DropdownMenu.Content
|
|
47
|
+
<DropdownMenu.Content {align} sideOffset={4} class="z-100">
|
|
49
48
|
{#snippet child({ wrapperProps, props, open: isOpen })}
|
|
50
|
-
{
|
|
51
|
-
<div
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
easing: easeEmphasizedDecel,
|
|
62
|
-
mode: 'scale'
|
|
63
|
-
}}
|
|
64
|
-
>
|
|
65
|
-
{@render children()}
|
|
66
|
-
</div>
|
|
49
|
+
<div {...wrapperProps} class={wrapperProps.class as any}>
|
|
50
|
+
<div
|
|
51
|
+
{...props}
|
|
52
|
+
class={clsx(
|
|
53
|
+
'bg-md-sys-color-surface-container-high shadow-elevation-3 ring-md-sys-color-outline/10 max-w-sm min-w-48 gap-1 overflow-y-auto rounded-lg px-2 py-1',
|
|
54
|
+
props.class as any,
|
|
55
|
+
contentClass
|
|
56
|
+
)}
|
|
57
|
+
{@attach presence(() => isOpen, enterExit.scale)}
|
|
58
|
+
>
|
|
59
|
+
{@render children()}
|
|
67
60
|
</div>
|
|
68
|
-
|
|
61
|
+
</div>
|
|
69
62
|
{/snippet}
|
|
70
63
|
</DropdownMenu.Content>
|
|
71
64
|
</DropdownMenu.Portal>
|
|
@@ -25,13 +25,12 @@ trigger row (`iconProps`/`helper`/`children` label) behaves like a
|
|
|
25
25
|
@see https://m3.material.io/components/menus/guidelines
|
|
26
26
|
-->
|
|
27
27
|
<script lang="ts">
|
|
28
|
+
import { enterExit, presence } from '../../../animation/index.js';
|
|
28
29
|
import { DropdownMenu } from 'bits-ui';
|
|
29
30
|
import clsx from 'clsx';
|
|
30
31
|
import Icon from '../../../utils/icon/Icon.svelte';
|
|
31
32
|
import Layer from '../../../utils/Layer.svelte';
|
|
32
33
|
import { menu as menuCls } from './theme.js';
|
|
33
|
-
import { enterExit } from '../../../animation/enterExit.js';
|
|
34
|
-
import { easeEmphasizedDecel } from '../../../animation/easing.js';
|
|
35
34
|
import type { MenuSubProps } from './types.js';
|
|
36
35
|
|
|
37
36
|
let {
|
|
@@ -68,23 +67,17 @@ trigger row (`iconProps`/`helper`/`children` label) behaves like a
|
|
|
68
67
|
</DropdownMenu.SubTrigger>
|
|
69
68
|
|
|
70
69
|
<DropdownMenu.Portal>
|
|
71
|
-
<DropdownMenu.SubContent
|
|
70
|
+
<DropdownMenu.SubContent sideOffset={4} class="z-100">
|
|
72
71
|
{#snippet child({ wrapperProps, props, open: isOpen })}
|
|
73
|
-
{
|
|
74
|
-
<div
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
easing: easeEmphasizedDecel,
|
|
81
|
-
mode: 'scale'
|
|
82
|
-
}}
|
|
83
|
-
>
|
|
84
|
-
{@render submenu()}
|
|
85
|
-
</div>
|
|
72
|
+
<div {...wrapperProps} class={wrapperProps.class as any}>
|
|
73
|
+
<div
|
|
74
|
+
{...props}
|
|
75
|
+
class={clsx(cls.content(), props.class as any, submenuClass)}
|
|
76
|
+
{@attach presence(() => isOpen, enterExit.scale)}
|
|
77
|
+
>
|
|
78
|
+
{@render submenu()}
|
|
86
79
|
</div>
|
|
87
|
-
|
|
80
|
+
</div>
|
|
88
81
|
{/snippet}
|
|
89
82
|
</DropdownMenu.SubContent>
|
|
90
83
|
</DropdownMenu.Portal>
|
|
@@ -27,9 +27,11 @@ the pane itself stays `position: fixed` and doesn't move with either.
|
|
|
27
27
|
<script lang="ts">
|
|
28
28
|
import clsx from 'clsx';
|
|
29
29
|
import { onMount } from 'svelte';
|
|
30
|
+
import { animate, type AnimationPlaybackControls } from 'motion';
|
|
31
|
+
import { springTokens, springTransition } from '../../../animation/spring.js';
|
|
30
32
|
import { Icon, Layer } from '../../../utils/index.js';
|
|
31
33
|
import { ButtonIcon } from '../../buttons/index.js';
|
|
32
|
-
import { clickOutside } from '../../../
|
|
34
|
+
import { clickOutside } from '../../../attachments/index.js';
|
|
33
35
|
import { draggablePane, type ResizeEdge } from './theme.js';
|
|
34
36
|
import { dragPositions } from './dragStore.svelte.js';
|
|
35
37
|
import type { DraggablePaneProps } from './types.js';
|
|
@@ -269,7 +271,10 @@ the pane itself stays `position: fixed` and doesn't move with either.
|
|
|
269
271
|
persist();
|
|
270
272
|
|
|
271
273
|
window.addEventListener('resize', recomputeBounds);
|
|
272
|
-
return () =>
|
|
274
|
+
return () => {
|
|
275
|
+
window.removeEventListener('resize', recomputeBounds);
|
|
276
|
+
stopSettle();
|
|
277
|
+
};
|
|
273
278
|
});
|
|
274
279
|
|
|
275
280
|
// `bounds` can be an element that resizes or scrolls independently of the
|
|
@@ -301,28 +306,106 @@ the pane itself stays `position: fixed` and doesn't move with either.
|
|
|
301
306
|
}
|
|
302
307
|
});
|
|
303
308
|
|
|
309
|
+
/*
|
|
310
|
+
Expressive drag: the pane tracks the pointer 1:1 (direct manipulation never lags behind a
|
|
311
|
+
spring), rubber-bands past `bounds` instead of hitting a wall, and on release springs back
|
|
312
|
+
inside on the fast spatial spring, carrying the pointer's velocity. Keyboard nudges glide on
|
|
313
|
+
the same spring. Grabbing the pane mid-spring stops it where it is.
|
|
314
|
+
*/
|
|
315
|
+
const SETTLE_SPRING = springTransition(springTokens.fastSpatial);
|
|
316
|
+
/* Share of the overshoot still applied at the edge, shrinking the further it's pulled. The
|
|
317
|
+
UIScrollView rubber-band constant — M3 has no token for this; tune by eye. */
|
|
318
|
+
const RUBBER_BAND = 0.55;
|
|
319
|
+
/* Pointer samples older than this don't count towards the release velocity. */
|
|
320
|
+
const VELOCITY_WINDOW_MS = 100;
|
|
321
|
+
|
|
322
|
+
let settleX: AnimationPlaybackControls | undefined;
|
|
323
|
+
let settleY: AnimationPlaybackControls | undefined;
|
|
324
|
+
/** Where the running spring is headed; undefined once it's done or stopped. */
|
|
325
|
+
let settleTarget: { x: number; y: number } | undefined;
|
|
326
|
+
|
|
327
|
+
function stopSettle() {
|
|
328
|
+
settleX?.stop();
|
|
329
|
+
settleY?.stop();
|
|
330
|
+
settleTarget = undefined;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** Springs the pane to `target` (clamped), starting with `velocity` px/s. */
|
|
334
|
+
function settleTo(targetX: number, targetY: number, velocity = { x: 0, y: 0 }) {
|
|
335
|
+
stopSettle();
|
|
336
|
+
const next = clamp(targetX, targetY);
|
|
337
|
+
const fromX = x ?? initialX;
|
|
338
|
+
const fromY = y ?? initialY;
|
|
339
|
+
settleTarget = next;
|
|
340
|
+
settleX = animate(fromX, next.x, {
|
|
341
|
+
...SETTLE_SPRING,
|
|
342
|
+
velocity: velocity.x,
|
|
343
|
+
onUpdate: (value) => (x = value),
|
|
344
|
+
onComplete: () => (settleTarget = undefined)
|
|
345
|
+
});
|
|
346
|
+
settleY = animate(fromY, next.y, {
|
|
347
|
+
...SETTLE_SPRING,
|
|
348
|
+
velocity: velocity.y,
|
|
349
|
+
onUpdate: (value) => (y = value)
|
|
350
|
+
});
|
|
351
|
+
// Persist the resting position up front — the spring only animates towards it.
|
|
352
|
+
if (persistKey) dragPositions.set(persistKey, { x: next.x, y: next.y, width, height });
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** Resisted overshoot: the further past the edge, the less the pane follows. */
|
|
356
|
+
function rubberBand(overshoot: number, limit: number) {
|
|
357
|
+
return (1 - 1 / ((overshoot * RUBBER_BAND) / limit + 1)) * limit;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function resist(value: number, min: number, max: number, size: number) {
|
|
361
|
+
if (value < min) return min - rubberBand(min - value, size);
|
|
362
|
+
if (value > max) return max + rubberBand(value - max, size);
|
|
363
|
+
return value;
|
|
364
|
+
}
|
|
365
|
+
|
|
304
366
|
let dragStartX = 0;
|
|
305
367
|
let dragStartY = 0;
|
|
306
368
|
let originX = 0;
|
|
307
369
|
let originY = 0;
|
|
370
|
+
let samples: { x: number; y: number; t: number }[] = [];
|
|
308
371
|
|
|
309
372
|
function startDrag(event: PointerEvent) {
|
|
310
373
|
if (disableDrag) return;
|
|
374
|
+
stopSettle();
|
|
311
375
|
dragging = true;
|
|
312
376
|
dragStartX = event.clientX;
|
|
313
377
|
dragStartY = event.clientY;
|
|
314
378
|
originX = x ?? initialX;
|
|
315
379
|
originY = y ?? initialY;
|
|
380
|
+
samples = [{ x: event.clientX, y: event.clientY, t: event.timeStamp }];
|
|
316
381
|
(event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);
|
|
317
382
|
}
|
|
318
383
|
|
|
319
384
|
function moveDrag(event: PointerEvent) {
|
|
320
385
|
if (!dragging) return;
|
|
321
|
-
|
|
386
|
+
const rawX = originX + (event.clientX - dragStartX);
|
|
387
|
+
const rawY = originY + (event.clientY - dragStartY);
|
|
388
|
+
const rect = boundsRect();
|
|
389
|
+
const { x: minX, y: minY } = clamp(-Infinity, -Infinity);
|
|
390
|
+
const { x: maxX, y: maxY } = clamp(Infinity, Infinity);
|
|
391
|
+
x = resist(rawX, minX, maxX, rect.right - rect.left);
|
|
392
|
+
y = resist(rawY, minY, maxY, rect.bottom - rect.top);
|
|
393
|
+
samples.push({ x: event.clientX, y: event.clientY, t: event.timeStamp });
|
|
394
|
+
samples = samples.filter((sample) => event.timeStamp - sample.t <= VELOCITY_WINDOW_MS);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function releaseVelocity() {
|
|
398
|
+
const first = samples[0];
|
|
399
|
+
const last = samples[samples.length - 1];
|
|
400
|
+
const seconds = first && last ? (last.t - first.t) / 1000 : 0;
|
|
401
|
+
if (!seconds) return { x: 0, y: 0 };
|
|
402
|
+
return { x: (last.x - first.x) / seconds, y: (last.y - first.y) / seconds };
|
|
322
403
|
}
|
|
323
404
|
|
|
324
405
|
function endDrag() {
|
|
406
|
+
if (!dragging) return;
|
|
325
407
|
dragging = false;
|
|
408
|
+
settleTo(x ?? initialX, y ?? initialY, releaseVelocity());
|
|
326
409
|
}
|
|
327
410
|
|
|
328
411
|
const NUDGE = 8;
|
|
@@ -339,7 +422,9 @@ the pane itself stays `position: fixed` and doesn't move with either.
|
|
|
339
422
|
const delta = deltas[event.key];
|
|
340
423
|
if (!delta) return;
|
|
341
424
|
event.preventDefault();
|
|
342
|
-
|
|
425
|
+
// Retargets a running nudge, so holding an arrow key glides instead of stepping.
|
|
426
|
+
const from = settleTarget ?? clamp(x ?? initialX, y ?? initialY);
|
|
427
|
+
settleTo(from.x + delta[0], from.y + delta[1]);
|
|
343
428
|
}
|
|
344
429
|
|
|
345
430
|
let resizeStartClientX = 0;
|
|
@@ -440,7 +525,7 @@ the pane itself stays `position: fixed` and doesn't move with either.
|
|
|
440
525
|
{style}
|
|
441
526
|
role="group"
|
|
442
527
|
aria-label={title}
|
|
443
|
-
|
|
528
|
+
{@attach onClickOutside && clickOutside(onClickOutside)}
|
|
444
529
|
{...rest}
|
|
445
530
|
>
|
|
446
531
|
<div
|
|
@@ -24,6 +24,6 @@ import type { DraggablePaneProps } from './types.js';
|
|
|
24
24
|
* element resizes or scrolls (itself or via any scrolling ancestor), since
|
|
25
25
|
* the pane itself stays `position: fixed` and doesn't move with either.
|
|
26
26
|
*/
|
|
27
|
-
declare const DraggablePane: import("svelte").Component<DraggablePaneProps, {}, "
|
|
27
|
+
declare const DraggablePane: import("svelte").Component<DraggablePaneProps, {}, "height" | "width" | "x" | "y" | "collapsed">;
|
|
28
28
|
type DraggablePane = ReturnType<typeof DraggablePane>;
|
|
29
29
|
export default DraggablePane;
|
|
@@ -117,7 +117,7 @@ export const pane = tv({
|
|
|
117
117
|
export const paneHandle = tv({
|
|
118
118
|
slots: {
|
|
119
119
|
base: 'group relative flex shrink-0 w-3 self-stretch cursor-col-resize touch-none items-center justify-center rounded-full bg-transparent hover:bg-md-sys-color-outline/20',
|
|
120
|
-
grip: 'rounded-full transition-[background-color,height,width]
|
|
120
|
+
grip: 'rounded-full transition-[background-color,height,width] md-sys-motion-fast-spatial'
|
|
121
121
|
},
|
|
122
122
|
variants: {
|
|
123
123
|
dragging: {
|
|
@@ -135,7 +135,7 @@ export const paneHandle = tv({
|
|
|
135
135
|
});
|
|
136
136
|
export const draggablePane = tv({
|
|
137
137
|
slots: {
|
|
138
|
-
base: 'fixed z-[100] flex min-w-72 flex-col rounded-md bg-md-sys-color-surface-container-highest shadow-elevation-3',
|
|
138
|
+
base: 'fixed z-[100] flex min-w-72 flex-col rounded-md bg-md-sys-color-surface-container-highest shadow-elevation-3 transition-shadow md-sys-motion-effects',
|
|
139
139
|
headerBar: 'relative flex shrink-0 items-center gap-2 rounded-t-2xl px-3 py-2 touch-none select-none md-sys-state-focus-indicator',
|
|
140
140
|
grip: 'shrink-0 text-md-sys-color-on-surface-variant',
|
|
141
141
|
headline: 'flex-1 truncate md-sys-typescale-title-small text-md-sys-color-on-surface',
|
|
@@ -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>
|