@noxlovette/material 0.1.19 → 0.1.20
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/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/actions/portal.d.ts +3 -0
- package/dist/actions/portal.js +8 -0
- package/dist/components/buttons/FAB.svelte +4 -3
- package/dist/components/buttons/FABMenu.svelte +14 -52
- package/dist/components/buttons/Toggle.svelte +0 -2
- package/dist/components/buttons/theme.js +3 -3
- package/dist/components/buttons/types.d.ts +2 -0
- package/package.json +1 -1
package/dist/actions/index.d.ts
CHANGED
package/dist/actions/index.js
CHANGED
|
@@ -35,6 +35,7 @@ Floating action buttons (FABs) help people take primary actions.
|
|
|
35
35
|
const { base, icon, label: labelClass } = $derived(fab({ size, config, expanded }));
|
|
36
36
|
|
|
37
37
|
let showMenu = $state(false);
|
|
38
|
+
let wrapperEl = $state<HTMLElement | null>(null);
|
|
38
39
|
|
|
39
40
|
const btnCls = $derived(
|
|
40
41
|
base({
|
|
@@ -58,7 +59,7 @@ Floating action buttons (FABs) help people take primary actions.
|
|
|
58
59
|
}
|
|
59
60
|
</script>
|
|
60
61
|
|
|
61
|
-
<div class="contents" use:clickOutside={() => (showMenu = false)}>
|
|
62
|
+
<div class="contents" bind:this={wrapperEl} use:clickOutside={() => (showMenu = false)}>
|
|
62
63
|
<Button.Root
|
|
63
64
|
{disabled}
|
|
64
65
|
{formaction}
|
|
@@ -76,8 +77,8 @@ Floating action buttons (FABs) help people take primary actions.
|
|
|
76
77
|
{/if}
|
|
77
78
|
</Button.Root>
|
|
78
79
|
|
|
79
|
-
{#if withMenu && showMenu}
|
|
80
|
-
<FABMenu>
|
|
80
|
+
{#if withMenu && showMenu && wrapperEl?.firstElementChild}
|
|
81
|
+
<FABMenu anchorEl={wrapperEl.firstElementChild as HTMLElement}>
|
|
81
82
|
{@render children?.()}
|
|
82
83
|
</FABMenu>
|
|
83
84
|
{/if}
|
|
@@ -5,69 +5,31 @@ Should be used with `FABMenuItem` as children.
|
|
|
5
5
|
-->
|
|
6
6
|
<script lang="ts">
|
|
7
7
|
import clsx from 'clsx';
|
|
8
|
+
import { flip } from '@floating-ui/dom';
|
|
8
9
|
import { fabMenu } from './theme.js';
|
|
9
10
|
import type { FABMenuProps } from './types.js';
|
|
10
11
|
import { enterExit } from '../../animation/enterExit.js';
|
|
11
|
-
import { easeEmphasizedDecel } from '../../animation/easing.js';
|
|
12
|
+
import { easeEmphasizedAccel, easeEmphasizedDecel } from '../../animation/easing.js';
|
|
13
|
+
import { floating, portal } from '../../actions/index.js';
|
|
12
14
|
|
|
13
|
-
let { children, class: className, ...restProps }: FABMenuProps = $props();
|
|
15
|
+
let { children, class: className, anchorEl, ...restProps }: FABMenuProps = $props();
|
|
14
16
|
|
|
15
17
|
const { base } = fabMenu();
|
|
16
|
-
|
|
17
|
-
const margin = 8;
|
|
18
|
-
const gap = 8;
|
|
19
|
-
let coords = $state({
|
|
20
|
-
x: 0,
|
|
21
|
-
y: 0,
|
|
22
|
-
originX: 'right',
|
|
23
|
-
originY: 'bottom',
|
|
24
|
-
maxHeight: 0
|
|
25
|
-
});
|
|
26
18
|
</script>
|
|
27
19
|
|
|
28
20
|
<ul
|
|
29
21
|
data-cy="m3-fab-menu"
|
|
30
22
|
{...restProps}
|
|
31
|
-
class={base({
|
|
32
|
-
class: clsx(className, 'fab-menu overflow-y-auto')
|
|
33
|
-
})}
|
|
23
|
+
class={base({ class: clsx(className, 'fab-menu overflow-y-auto') })}
|
|
34
24
|
in:enterExit={{ duration: 300, easing: easeEmphasizedDecel, mode: 'scale' }}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const rect = menu.getBoundingClientRect();
|
|
44
|
-
|
|
45
|
-
const spaceAbove = anchorRect.top - gap - margin;
|
|
46
|
-
const spaceBelow = window.innerHeight - margin - (anchorRect.bottom + gap);
|
|
47
|
-
const placeAbove = spaceAbove >= rect.height || spaceAbove >= Math.max(0, spaceBelow);
|
|
48
|
-
|
|
49
|
-
let maxHeight = placeAbove ? spaceAbove : spaceBelow;
|
|
50
|
-
maxHeight = Math.max(0, Math.min(rect.height, maxHeight));
|
|
51
|
-
|
|
52
|
-
const targetTop = placeAbove ? anchorRect.top - gap - maxHeight : anchorRect.bottom + gap;
|
|
53
|
-
|
|
54
|
-
let targetLeft = anchorRect.right - rect.width;
|
|
55
|
-
if (targetLeft + rect.width > window.innerWidth - margin) {
|
|
56
|
-
targetLeft = window.innerWidth - margin - rect.width;
|
|
57
|
-
}
|
|
58
|
-
if (targetLeft < margin) targetLeft = margin;
|
|
59
|
-
|
|
60
|
-
let clampedTop = targetTop;
|
|
61
|
-
if (clampedTop < margin) clampedTop = margin;
|
|
62
|
-
if (clampedTop + maxHeight > window.innerHeight - margin) {
|
|
63
|
-
clampedTop = window.innerHeight - margin - maxHeight;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const originY = placeAbove ? 'bottom' : 'top';
|
|
67
|
-
const originX =
|
|
68
|
-
anchorRect.left + anchorRect.width / 2 < targetLeft + rect.width / 2 ? 'left' : 'right';
|
|
69
|
-
|
|
70
|
-
coords = { x: targetLeft, y: clampedTop, originX, originY, maxHeight };
|
|
25
|
+
out:enterExit={{ duration: 200, easing: easeEmphasizedAccel, mode: 'scale' }}
|
|
26
|
+
use:portal
|
|
27
|
+
use:floating={{
|
|
28
|
+
reference: anchorEl,
|
|
29
|
+
strategy: 'fixed',
|
|
30
|
+
placement: 'top-end',
|
|
31
|
+
offsetPx: 8,
|
|
32
|
+
middleware: [flip()]
|
|
71
33
|
}}
|
|
72
34
|
>
|
|
73
35
|
{@render children()}
|
|
@@ -75,6 +37,6 @@ Should be used with `FABMenuItem` as children.
|
|
|
75
37
|
|
|
76
38
|
<style>
|
|
77
39
|
.fab-menu {
|
|
78
|
-
transform-origin:
|
|
40
|
+
transform-origin: bottom right;
|
|
79
41
|
}
|
|
80
42
|
</style>
|
|
@@ -66,7 +66,7 @@ export const button = tv({
|
|
|
66
66
|
{
|
|
67
67
|
usage: 'selection',
|
|
68
68
|
selected: false,
|
|
69
|
-
class: { base: 'bg-md-sys-color-surface-container' }
|
|
69
|
+
class: { base: 'bg-md-sys-color-surface-container-high text-md-sys-color-on-surface-variant' }
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
variant: 'text',
|
|
@@ -275,7 +275,7 @@ export const buttonIcon = tv({
|
|
|
275
275
|
{
|
|
276
276
|
variation: 'toggle',
|
|
277
277
|
selected: false,
|
|
278
|
-
class: { base: 'bg-md-sys-color-surface-container' }
|
|
278
|
+
class: { base: 'bg-md-sys-color-surface-container-high text-md-sys-color-on-surface-variant' }
|
|
279
279
|
},
|
|
280
280
|
{
|
|
281
281
|
variant: 'text',
|
|
@@ -474,7 +474,7 @@ export const fab = tv({
|
|
|
474
474
|
});
|
|
475
475
|
export const fabMenu = tv({
|
|
476
476
|
slots: {
|
|
477
|
-
base: 'gap-2 pb-2 flex flex-col
|
|
477
|
+
base: 'gap-2 pb-2 flex flex-col z-[9999] overflow-visible p-1'
|
|
478
478
|
}
|
|
479
479
|
});
|
|
480
480
|
export const fabMenuItem = tv({
|
|
@@ -158,6 +158,8 @@ export type FABProps = FABVariants & AnchorButtonAttributes & {
|
|
|
158
158
|
children?: Snippet;
|
|
159
159
|
};
|
|
160
160
|
export type FABMenuProps = HTMLAttributes<HTMLUListElement> & {
|
|
161
|
+
/** The FAB button element to position the menu relative to. */
|
|
162
|
+
anchorEl: HTMLElement;
|
|
161
163
|
/**
|
|
162
164
|
* The menu items. Use `FABMenuItem` components.
|
|
163
165
|
*/
|