@webamoki/web-svelte 0.7.4 → 1.0.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 +83 -3
- package/dist/components/form/Button.svelte +24 -23
- package/dist/components/form/Button.svelte.d.ts +2 -2
- package/dist/components/form/Errors.svelte +13 -13
- package/dist/components/form/FieldWrapper.svelte +57 -55
- package/dist/components/form/FieldWrapper.svelte.d.ts +4 -4
- package/dist/components/form/Form.svelte +18 -14
- package/dist/components/form/Form.svelte.d.ts +31 -22
- package/dist/components/form/IconInputWrapper.svelte +30 -29
- package/dist/components/form/IconInputWrapper.svelte.d.ts +7 -7
- package/dist/components/form/fields/ChoiceField.svelte +45 -43
- package/dist/components/form/fields/ChoiceField.svelte.d.ts +28 -23
- package/dist/components/form/fields/ChoiceMultiField.svelte +44 -42
- package/dist/components/form/fields/ChoiceMultiField.svelte.d.ts +28 -23
- package/dist/components/form/fields/DateField.svelte +42 -40
- package/dist/components/form/fields/DateField.svelte.d.ts +29 -22
- package/dist/components/form/fields/HexColorField.svelte +21 -19
- package/dist/components/form/fields/HexColorField.svelte.d.ts +24 -19
- package/dist/components/form/fields/MessageField.svelte +39 -60
- package/dist/components/form/fields/MessageField.svelte.d.ts +33 -24
- package/dist/components/form/fields/NumberField.svelte +38 -36
- package/dist/components/form/fields/NumberField.svelte.d.ts +32 -23
- package/dist/components/form/fields/PasswordField.svelte +45 -39
- package/dist/components/form/fields/PasswordField.svelte.d.ts +28 -21
- package/dist/components/form/fields/SelectField.svelte +84 -79
- package/dist/components/form/fields/SelectField.svelte.d.ts +39 -26
- package/dist/components/form/fields/SelectMultiField.svelte +90 -85
- package/dist/components/form/fields/SelectMultiField.svelte.d.ts +38 -25
- package/dist/components/form/fields/TextField.svelte +31 -29
- package/dist/components/form/fields/TextField.svelte.d.ts +32 -23
- package/dist/components/form/fields/TextFieldNullable.svelte +49 -47
- package/dist/components/form/fields/TextFieldNullable.svelte.d.ts +32 -23
- package/dist/components/form/fields/TimeField.svelte +66 -64
- package/dist/components/form/fields/TimeField.svelte.d.ts +33 -24
- package/dist/components/form/fields/WeekdayChoiceField.svelte +37 -35
- package/dist/components/form/fields/WeekdayChoiceField.svelte.d.ts +27 -22
- package/dist/components/form/fields/WeekdayChoiceMultiField.svelte +37 -35
- package/dist/components/form/fields/WeekdayChoiceMultiField.svelte.d.ts +27 -22
- package/dist/components/showcase/CodeBlock.svelte +41 -41
- package/dist/components/showcase/Container.svelte +7 -7
- package/dist/components/showcase/Preview.svelte +4 -4
- package/dist/components/showcase/Sidebar.svelte +4 -4
- package/dist/components/showcase/SidebarLink.svelte +3 -3
- package/dist/components/ui/choice/Choice.svelte +25 -22
- package/dist/components/ui/choice/Choice.svelte.d.ts +7 -7
- package/dist/components/ui/choice/ChoiceInternal.svelte +73 -69
- package/dist/components/ui/choice/ChoiceInternal.svelte.d.ts +9 -9
- package/dist/components/ui/choice/ChoiceMulti.svelte +59 -53
- package/dist/components/ui/choice/ChoiceMulti.svelte.d.ts +7 -7
- package/dist/components/ui/choice/WeekdayChoice.svelte +22 -21
- package/dist/components/ui/choice/WeekdayChoice.svelte.d.ts +6 -6
- package/dist/components/ui/choice/WeekdayChoiceMulti.svelte +24 -22
- package/dist/components/ui/choice/WeekdayChoiceMulti.svelte.d.ts +6 -6
- package/dist/components/ui/context-menu/ContextMenu.svelte +51 -50
- package/dist/components/ui/context-menu/ContextMenu.svelte.d.ts +1 -1
- package/dist/components/ui/context-menu/ContextMenuContent.svelte +92 -91
- package/dist/components/ui/context-menu/ContextMenuItem.svelte +26 -25
- package/dist/components/ui/context-menu/ContextMenuItem.svelte.d.ts +1 -1
- package/dist/components/ui/context-menu/ContextMenuTrigger.svelte +16 -15
- package/dist/components/ui/context-menu/context-menu-state.svelte.d.ts +3 -3
- package/dist/components/ui/context-menu/context-menu-state.svelte.js +15 -15
- package/dist/components/ui/drag-drop/Draggable.svelte +73 -72
- package/dist/components/ui/drag-drop/Draggable.svelte.d.ts +2 -2
- package/dist/components/ui/drag-drop/Dropzone.svelte +56 -54
- package/dist/components/ui/drag-drop/Dropzone.svelte.d.ts +3 -3
- package/dist/components/ui/drag-drop/drag-manager.d.ts +2 -2
- package/dist/components/ui/drag-drop/drag-manager.js +9 -9
- package/dist/components/ui/index.d.ts +2 -2
- package/dist/components/ui/index.js +5 -5
- package/dist/components/ui/search/SearchBar.svelte +18 -18
- package/dist/components/ui/search/SearchBar.svelte.d.ts +2 -2
- package/dist/highlight.js +2 -2
- package/dist/server/form-handler.d.ts +12 -12
- package/dist/server/form-handler.js +17 -17
- package/dist/server/form-processor.d.ts +1 -1
- package/dist/server/form-processor.js +0 -1
- package/dist/shadcn/components/ui/button/button.svelte +72 -71
- package/dist/shadcn/components/ui/button/button.svelte.d.ts +23 -23
- package/dist/shadcn/components/ui/button/index.d.ts +1 -1
- package/dist/shadcn/components/ui/button/index.js +2 -2
- package/dist/shadcn/components/ui/input/index.d.ts +1 -1
- package/dist/shadcn/components/ui/input/index.js +2 -2
- package/dist/shadcn/components/ui/input/input.svelte +35 -32
- package/dist/shadcn/components/ui/input/input.svelte.d.ts +2 -2
- package/dist/shadcn/components/ui/select/index.d.ts +6 -6
- package/dist/shadcn/components/ui/select/index.js +7 -7
- package/dist/shadcn/components/ui/select/select-content.svelte +35 -34
- package/dist/shadcn/components/ui/select/select-content.svelte.d.ts +1 -1
- package/dist/shadcn/components/ui/select/select-group-heading.svelte +15 -14
- package/dist/shadcn/components/ui/select/select-group.svelte +2 -2
- package/dist/shadcn/components/ui/select/select-item.svelte +31 -31
- package/dist/shadcn/components/ui/select/select-label.svelte +14 -13
- package/dist/shadcn/components/ui/select/select-label.svelte.d.ts +1 -1
- package/dist/shadcn/components/ui/select/select-scroll-down-button.svelte +13 -13
- package/dist/shadcn/components/ui/select/select-scroll-up-button.svelte +13 -13
- package/dist/shadcn/components/ui/select/select-separator.svelte +13 -12
- package/dist/shadcn/components/ui/select/select-trigger.svelte +26 -26
- package/dist/shadcn/components/ui/select/select-trigger.svelte.d.ts +2 -2
- package/dist/shadcn/components/ui/separator/separator.svelte +14 -14
- package/dist/shadcn/components/ui/textarea/textarea.svelte +22 -21
- package/dist/shadcn/components/ui/textarea/textarea.svelte.d.ts +1 -1
- package/dist/shadcn/utils.d.ts +4 -4
- package/dist/utils/datetime/index.d.ts +68 -68
- package/dist/utils/datetime/index.js +124 -124
- package/dist/utils/email/README.md +60 -60
- package/dist/utils/email/aws-signer.d.ts +1 -1
- package/dist/utils/email/aws-signer.js +39 -39
- package/dist/utils/email/ses.d.ts +8 -10
- package/dist/utils/email/ses.js +15 -23
- package/dist/utils/form/index.d.ts +11 -11
- package/dist/utils/form/index.js +23 -24
- package/dist/utils/form/virtual-form.d.ts +5 -5
- package/dist/utils/form/virtual-form.js +58 -58
- package/dist/utils/search.d.ts +1 -1
- package/dist/utils/search.js +22 -22
- package/dist/utils/types/arktype.d.ts +2 -2
- package/dist/utils/types/arktype.js +3 -3
- package/dist/utils/types/db.d.ts +2 -1
- package/dist/utils/types/db.js +7 -7
- package/package.json +69 -54
|
@@ -1,57 +1,58 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
export type ContextMenuState = {
|
|
3
|
+
open: boolean;
|
|
4
|
+
position: { x: number; y: number };
|
|
5
|
+
};
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<script lang="ts">
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
9
|
+
import { onDestroy, setContext, type Snippet } from 'svelte';
|
|
10
|
+
|
|
11
|
+
import { contextMenuState } from './context-menu-state.svelte';
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
children: Snippet<[]>;
|
|
15
|
+
onOpenChange?: (open: boolean) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let { children, onOpenChange }: Props = $props();
|
|
19
|
+
|
|
20
|
+
const menuId = Symbol('context-menu');
|
|
21
|
+
|
|
22
|
+
let menuState = $state<ContextMenuState>({
|
|
23
|
+
open: false,
|
|
24
|
+
position: { x: 0, y: 0 }
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Watch for changes to menuState.open and sync with global store
|
|
28
|
+
$effect(() => {
|
|
29
|
+
if (menuState.open) {
|
|
30
|
+
contextMenuState.openMenu(menuId);
|
|
31
|
+
} else if (contextMenuState.isThisMenuOpen(menuId)) {
|
|
32
|
+
contextMenuState.closeMenu();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Watch for global store changes and close this menu if another opens
|
|
37
|
+
$effect(() => {
|
|
38
|
+
if (contextMenuState.open && !contextMenuState.isThisMenuOpen(menuId)) {
|
|
39
|
+
menuState.open = false;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Call onOpenChange callback when open state changes
|
|
44
|
+
$effect(() => {
|
|
45
|
+
onOpenChange?.(menuState.open);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Cleanup scroll lock when component is destroyed
|
|
49
|
+
onDestroy(() => {
|
|
50
|
+
if (contextMenuState.isThisMenuOpen(menuId)) {
|
|
51
|
+
contextMenuState.closeMenu();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
setContext('context-menu', menuState);
|
|
55
56
|
</script>
|
|
56
57
|
|
|
57
58
|
{@render children()}
|
|
@@ -1,99 +1,100 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
2
|
+
import { cn } from '../../../shadcn/utils.js';
|
|
3
|
+
import { getContext, onMount, type Snippet } from 'svelte';
|
|
4
|
+
import { scale } from 'svelte/transition';
|
|
5
|
+
|
|
6
|
+
import type { ContextMenuState } from './ContextMenu.svelte';
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
children: Snippet<[]>;
|
|
10
|
+
class?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let { children, class: className }: Props = $props();
|
|
14
|
+
|
|
15
|
+
const menuState: ContextMenuState = getContext('context-menu');
|
|
16
|
+
|
|
17
|
+
let menuElement: HTMLDivElement | null = $state(null);
|
|
18
|
+
let adjustedPosition = $state({ x: 0, y: 0 });
|
|
19
|
+
|
|
20
|
+
function handleDocumentClick(event: MouseEvent) {
|
|
21
|
+
if (menuElement && !menuElement.contains(event.target as Node)) {
|
|
22
|
+
menuState.open = false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function adjustPositionToFitScreen() {
|
|
27
|
+
if (!menuElement) return;
|
|
28
|
+
|
|
29
|
+
const rect = menuElement.getBoundingClientRect();
|
|
30
|
+
const viewportWidth = window.innerWidth;
|
|
31
|
+
const viewportHeight = window.innerHeight;
|
|
32
|
+
|
|
33
|
+
let x = menuState.position.x;
|
|
34
|
+
let y = menuState.position.y;
|
|
35
|
+
|
|
36
|
+
// Adjust horizontal position if menu goes off right edge
|
|
37
|
+
if (x + rect.width > viewportWidth) {
|
|
38
|
+
x = viewportWidth - rect.width - 8; // 8px padding from edge
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Adjust horizontal position if menu goes off left edge
|
|
42
|
+
if (x < 0) {
|
|
43
|
+
x = 8; // 8px padding from edge
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Adjust vertical position if menu goes off bottom edge
|
|
47
|
+
if (y + rect.height > viewportHeight) {
|
|
48
|
+
y = viewportHeight - rect.height - 8; // 8px padding from edge
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Adjust vertical position if menu goes off top edge
|
|
52
|
+
if (y < 0) {
|
|
53
|
+
y = 8; // 8px padding from edge
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
adjustedPosition = { x, y };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
$effect(() => {
|
|
60
|
+
if (menuState.open && menuElement) {
|
|
61
|
+
// Use requestAnimationFrame to ensure DOM has updated
|
|
62
|
+
requestAnimationFrame(() => {
|
|
63
|
+
adjustPositionToFitScreen();
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
onMount(() => {
|
|
69
|
+
document.addEventListener('click', handleDocumentClick);
|
|
70
|
+
|
|
71
|
+
return () => {
|
|
72
|
+
document.removeEventListener('click', handleDocumentClick);
|
|
73
|
+
};
|
|
74
|
+
});
|
|
74
75
|
</script>
|
|
75
76
|
|
|
76
77
|
{#if menuState.open}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
<div
|
|
79
|
+
bind:this={menuElement}
|
|
80
|
+
style="left: {adjustedPosition.x}px; top: {adjustedPosition.y}px;"
|
|
81
|
+
class={cn('context-menu-content', className)}
|
|
82
|
+
transition:scale={{ duration: 150, start: 0.95 }}
|
|
83
|
+
>
|
|
84
|
+
{@render children()}
|
|
85
|
+
</div>
|
|
85
86
|
{/if}
|
|
86
87
|
|
|
87
88
|
<style>
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
89
|
+
.context-menu-content {
|
|
90
|
+
position: fixed;
|
|
91
|
+
background-color: white;
|
|
92
|
+
border: 1px solid #ddd;
|
|
93
|
+
border-radius: 8px;
|
|
94
|
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
95
|
+
padding: 4px;
|
|
96
|
+
min-width: 150px;
|
|
97
|
+
z-index: 50;
|
|
98
|
+
transform-origin: top left;
|
|
99
|
+
}
|
|
99
100
|
</style>
|
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
import { cn } from '../../../shadcn/utils.js';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
variant?: 'default' | 'destructive';
|
|
7
|
-
disabled?: boolean;
|
|
8
|
-
}
|
|
4
|
+
import { cn } from '../../../shadcn/utils.js';
|
|
9
5
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
variant?: 'default' | 'destructive';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
children,
|
|
13
|
+
class: className,
|
|
14
|
+
disabled = false,
|
|
15
|
+
onclick,
|
|
16
|
+
variant = 'default',
|
|
17
|
+
...restProps
|
|
18
|
+
}: Props = $props();
|
|
18
19
|
</script>
|
|
19
20
|
|
|
20
21
|
<div
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
class={cn(
|
|
23
|
+
'flex cursor-pointer items-center gap-2 rounded px-3 py-2 text-sm hover:bg-gray-100',
|
|
24
|
+
variant === 'destructive' && 'text-red-600 hover:bg-red-50',
|
|
25
|
+
disabled && 'pointer-events-none opacity-50',
|
|
26
|
+
className
|
|
27
|
+
)}
|
|
28
|
+
{onclick}
|
|
29
|
+
role="menuitem"
|
|
30
|
+
tabindex={disabled ? -1 : 0}
|
|
31
|
+
{...restProps}
|
|
31
32
|
>
|
|
32
|
-
|
|
33
|
+
{@render children?.()}
|
|
33
34
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
2
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
-
variant?: 'default' | 'destructive';
|
|
4
3
|
disabled?: boolean;
|
|
4
|
+
variant?: 'default' | 'destructive';
|
|
5
5
|
}
|
|
6
6
|
declare const ContextMenuItem: import("svelte").Component<Props, {}, "">;
|
|
7
7
|
type ContextMenuItem = ReturnType<typeof ContextMenuItem>;
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
import type { ContextMenuState } from './ContextMenu.svelte';
|
|
2
|
+
import { getContext, type Snippet } from 'svelte';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
children: Snippet<[]>;
|
|
7
|
-
}
|
|
4
|
+
import type { ContextMenuState } from './ContextMenu.svelte';
|
|
8
5
|
|
|
9
|
-
|
|
6
|
+
interface Props {
|
|
7
|
+
children: Snippet<[]>;
|
|
8
|
+
}
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
let { children }: Props = $props();
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
const menuState: ContextMenuState = getContext('context-menu');
|
|
13
|
+
|
|
14
|
+
function handleContextMenu(event: MouseEvent) {
|
|
15
|
+
event.preventDefault();
|
|
16
|
+
menuState.position.x = event.clientX;
|
|
17
|
+
menuState.position.y = event.clientY;
|
|
18
|
+
menuState.open = true;
|
|
19
|
+
}
|
|
19
20
|
</script>
|
|
20
21
|
|
|
21
|
-
<div role="button" tabindex="-1"
|
|
22
|
-
|
|
22
|
+
<div oncontextmenu={handleContextMenu} role="button" tabindex="-1">
|
|
23
|
+
{@render children()}
|
|
23
24
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const contextMenuState: {
|
|
2
|
-
readonly open: boolean;
|
|
3
|
-
readonly currentId: symbol | null;
|
|
4
|
-
openMenu(id: symbol): void;
|
|
5
2
|
closeMenu(): void;
|
|
3
|
+
readonly currentId: symbol | null;
|
|
6
4
|
isThisMenuOpen(id: symbol): boolean;
|
|
5
|
+
readonly open: boolean;
|
|
6
|
+
openMenu(id: symbol): void;
|
|
7
7
|
};
|
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
const globalMenuState = $state({
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
id: null,
|
|
3
|
+
open: false
|
|
4
4
|
});
|
|
5
5
|
export const contextMenuState = {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
closeMenu() {
|
|
7
|
+
globalMenuState.open = false;
|
|
8
|
+
globalMenuState.id = null;
|
|
9
|
+
// Restore scrolling when menu closes
|
|
10
|
+
if (typeof document !== 'undefined') {
|
|
11
|
+
document.body.style.overflow = '';
|
|
12
|
+
}
|
|
8
13
|
},
|
|
9
14
|
get currentId() {
|
|
10
15
|
return globalMenuState.id;
|
|
11
16
|
},
|
|
17
|
+
isThisMenuOpen(id) {
|
|
18
|
+
return globalMenuState.open && globalMenuState.id === id;
|
|
19
|
+
},
|
|
20
|
+
get open() {
|
|
21
|
+
return globalMenuState.open;
|
|
22
|
+
},
|
|
12
23
|
openMenu(id) {
|
|
13
24
|
globalMenuState.open = true;
|
|
14
25
|
globalMenuState.id = id;
|
|
@@ -16,16 +27,5 @@ export const contextMenuState = {
|
|
|
16
27
|
if (typeof document !== 'undefined') {
|
|
17
28
|
document.body.style.overflow = 'hidden';
|
|
18
29
|
}
|
|
19
|
-
},
|
|
20
|
-
closeMenu() {
|
|
21
|
-
globalMenuState.open = false;
|
|
22
|
-
globalMenuState.id = null;
|
|
23
|
-
// Restore scrolling when menu closes
|
|
24
|
-
if (typeof document !== 'undefined') {
|
|
25
|
-
document.body.style.overflow = '';
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
isThisMenuOpen(id) {
|
|
29
|
-
return globalMenuState.open && globalMenuState.id === id;
|
|
30
30
|
}
|
|
31
31
|
};
|
|
@@ -1,80 +1,81 @@
|
|
|
1
|
-
<script
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
1
|
+
<script generics="T" lang="ts">
|
|
2
|
+
import { onDestroy, type Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
import type { DragManager } from './drag-manager.js';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
children: Snippet<[]>;
|
|
8
|
+
class?: string;
|
|
9
|
+
data: T;
|
|
10
|
+
manager: DragManager<T>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let { children, class: className, data, manager }: Props = $props();
|
|
14
|
+
|
|
15
|
+
let isDragging = $state(false);
|
|
16
|
+
let mouseX = $state(0);
|
|
17
|
+
let mouseY = $state(0);
|
|
18
|
+
|
|
19
|
+
function startDrag(e: MouseEvent) {
|
|
20
|
+
if (e.button !== 0) return;
|
|
21
|
+
|
|
22
|
+
e.preventDefault();
|
|
23
|
+
isDragging = true;
|
|
24
|
+
manager.drag(data);
|
|
25
|
+
|
|
26
|
+
mouseX = e.clientX;
|
|
27
|
+
mouseY = e.clientY;
|
|
28
|
+
|
|
29
|
+
// Force grabbing cursor on the body
|
|
30
|
+
document.body.style.cursor = 'grabbing';
|
|
31
|
+
|
|
32
|
+
window.addEventListener('mousemove', moveDrag);
|
|
33
|
+
window.addEventListener('mouseup', endDrag);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function moveDrag(e: MouseEvent) {
|
|
37
|
+
mouseX = e.clientX;
|
|
38
|
+
mouseY = e.clientY;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function endDrag() {
|
|
42
|
+
isDragging = false;
|
|
43
|
+
manager.stop();
|
|
44
|
+
|
|
45
|
+
// Reset cursor
|
|
46
|
+
document.body.style.cursor = '';
|
|
47
|
+
|
|
48
|
+
window.removeEventListener('mousemove', moveDrag);
|
|
49
|
+
window.removeEventListener('mouseup', endDrag);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
onDestroy(() => {
|
|
53
|
+
if (isDragging) {
|
|
54
|
+
manager.stop();
|
|
55
|
+
}
|
|
56
|
+
if (typeof window !== 'undefined') {
|
|
57
|
+
window.removeEventListener('mousemove', moveDrag);
|
|
58
|
+
window.removeEventListener('mouseup', endDrag);
|
|
59
|
+
document.body.style.cursor = ''; // safe in browser only
|
|
60
|
+
}
|
|
61
|
+
});
|
|
61
62
|
</script>
|
|
62
63
|
|
|
63
64
|
<div
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
class={`relative select-none ${isDragging ? 'opacity-30 grayscale' : 'cursor-grab'} ${className ?? ''}`}
|
|
66
|
+
aria-label="Draggable item"
|
|
67
|
+
onmousedown={startDrag}
|
|
68
|
+
role="button"
|
|
69
|
+
tabindex="0"
|
|
69
70
|
>
|
|
70
|
-
|
|
71
|
+
{@render children()}
|
|
71
72
|
</div>
|
|
72
73
|
|
|
73
74
|
{#if isDragging}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
<div
|
|
76
|
+
style={`top:${mouseY}px; left:${mouseX}px;`}
|
|
77
|
+
class="pointer-events-none fixed z-9999 -translate-x-1/2 -translate-y-1/2 scale-115 transform opacity-95 shadow-xl"
|
|
78
|
+
>
|
|
79
|
+
{@render children()}
|
|
80
|
+
</div>
|
|
80
81
|
{/if}
|
|
@@ -2,10 +2,10 @@ import { type Snippet } from 'svelte';
|
|
|
2
2
|
import type { DragManager } from './drag-manager.js';
|
|
3
3
|
declare function $$render<T>(): {
|
|
4
4
|
props: {
|
|
5
|
-
data: T;
|
|
6
|
-
manager: DragManager<T>;
|
|
7
5
|
children: Snippet<[]>;
|
|
8
6
|
class?: string;
|
|
7
|
+
data: T;
|
|
8
|
+
manager: DragManager<T>;
|
|
9
9
|
};
|
|
10
10
|
exports: {};
|
|
11
11
|
bindings: "";
|