@djcali570/component-lib 0.1.92 → 0.1.93
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/ContextMenu5.svelte +83 -33
- package/package.json +1 -1
package/dist/ContextMenu5.svelte
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
|
+
import { fly } from 'svelte/transition';
|
|
3
4
|
import type { Snippet } from 'svelte';
|
|
4
5
|
import type { ContextMenu5ColorScheme } from './types.js';
|
|
5
|
-
|
|
6
|
+
|
|
7
|
+
// portal action
|
|
8
|
+
function portal(node: HTMLElement, target: HTMLElement = document.body) {
|
|
9
|
+
target.appendChild(node);
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
destroy() {
|
|
13
|
+
if (node.parentNode) {
|
|
14
|
+
node.parentNode.removeChild(node);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
6
19
|
|
|
7
20
|
// Props
|
|
8
21
|
let {
|
|
@@ -24,11 +37,11 @@
|
|
|
24
37
|
// Default colors
|
|
25
38
|
const defaultColorScheme: ContextMenu5ColorScheme = {
|
|
26
39
|
contentBgColor: '#121212',
|
|
27
|
-
contentBorderColor: '#191919',
|
|
28
40
|
iconFillColor: '#121212',
|
|
29
41
|
iconBorderColor: '#121212',
|
|
30
42
|
iconColor: '#F5F5F5'
|
|
31
43
|
};
|
|
44
|
+
|
|
32
45
|
const colorScheme = $derived({
|
|
33
46
|
...defaultColorScheme,
|
|
34
47
|
...partialColorScheme
|
|
@@ -38,9 +51,32 @@
|
|
|
38
51
|
let triggerEl: HTMLElement | null = null;
|
|
39
52
|
let menuEl: HTMLElement | null = $state(null);
|
|
40
53
|
|
|
54
|
+
// menu position
|
|
55
|
+
let position = $state({
|
|
56
|
+
x: 0,
|
|
57
|
+
y: 0,
|
|
58
|
+
width: 0
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
function updatePosition() {
|
|
62
|
+
if (!triggerEl) return;
|
|
63
|
+
|
|
64
|
+
const rect = triggerEl.getBoundingClientRect();
|
|
65
|
+
|
|
66
|
+
position = {
|
|
67
|
+
x: rect.left,
|
|
68
|
+
y: rect.bottom,
|
|
69
|
+
width: rect.width
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
41
73
|
// Toggle menu
|
|
42
74
|
function toggle() {
|
|
43
75
|
open = !open;
|
|
76
|
+
|
|
77
|
+
if (open) {
|
|
78
|
+
updatePosition();
|
|
79
|
+
}
|
|
44
80
|
}
|
|
45
81
|
|
|
46
82
|
// Close menu
|
|
@@ -53,6 +89,7 @@
|
|
|
53
89
|
if (!open) return;
|
|
54
90
|
|
|
55
91
|
const target = e.target as Node;
|
|
92
|
+
|
|
56
93
|
if (menuEl && triggerEl && !menuEl.contains(target) && !triggerEl.contains(target)) {
|
|
57
94
|
closeMenu();
|
|
58
95
|
}
|
|
@@ -67,18 +104,23 @@
|
|
|
67
104
|
document.addEventListener('pointerdown', handlePointerDown);
|
|
68
105
|
document.addEventListener('keydown', handleKeyDown);
|
|
69
106
|
|
|
107
|
+
window.addEventListener('scroll', updatePosition, true);
|
|
108
|
+
window.addEventListener('resize', updatePosition);
|
|
109
|
+
|
|
70
110
|
return () => {
|
|
71
111
|
document.removeEventListener('pointerdown', handlePointerDown);
|
|
72
112
|
document.removeEventListener('keydown', handleKeyDown);
|
|
113
|
+
|
|
114
|
+
window.removeEventListener('scroll', updatePosition, true);
|
|
115
|
+
window.removeEventListener('resize', updatePosition);
|
|
73
116
|
};
|
|
74
117
|
});
|
|
75
118
|
</script>
|
|
76
119
|
|
|
120
|
+
<!-- Trigger -->
|
|
77
121
|
<div
|
|
78
122
|
class="context5"
|
|
79
123
|
style="
|
|
80
|
-
--context5__ContentBgColor: {colorScheme.contentBgColor};
|
|
81
|
-
--context5__ContentBorderColor: {colorScheme.contentBorderColor};
|
|
82
124
|
--context5__IconBorderColor: {colorScheme.iconBorderColor};
|
|
83
125
|
--context5__IconColor: {colorScheme.iconColor};
|
|
84
126
|
--context5__IconFillColor: {colorScheme.iconFillColor};
|
|
@@ -105,22 +147,30 @@
|
|
|
105
147
|
</svg>
|
|
106
148
|
{/if}
|
|
107
149
|
</button>
|
|
150
|
+
</div>
|
|
108
151
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
152
|
+
<!-- Portal Menu -->
|
|
153
|
+
{#if open}
|
|
154
|
+
<div
|
|
155
|
+
use:portal
|
|
156
|
+
bind:this={menuEl}
|
|
157
|
+
role="menu"
|
|
158
|
+
class="context5__menu context5__portal"
|
|
159
|
+
style="
|
|
160
|
+
left:{menuAlign === 'right' ? position.x + position.width : position.x}px;
|
|
161
|
+
top:{position.y}px;
|
|
162
|
+
--context5__ContentBgColor: {colorScheme.contentBgColor};
|
|
163
|
+
--context5__ContentBorderColor: {colorScheme.contentBorderColor};
|
|
164
|
+
"
|
|
165
|
+
class:right={menuAlign === 'right'}
|
|
166
|
+
class:left={menuAlign === 'left'}
|
|
167
|
+
transition:fly={{ y: 8 }}
|
|
168
|
+
>
|
|
169
|
+
<div class="context5__content">
|
|
170
|
+
{@render content()}
|
|
121
171
|
</div>
|
|
122
|
-
|
|
123
|
-
|
|
172
|
+
</div>
|
|
173
|
+
{/if}
|
|
124
174
|
|
|
125
175
|
<style>
|
|
126
176
|
.context5 {
|
|
@@ -137,7 +187,6 @@
|
|
|
137
187
|
flex-shrink: 0;
|
|
138
188
|
}
|
|
139
189
|
|
|
140
|
-
/* force ANY svg inside to obey the container */
|
|
141
190
|
.context5__icon :global(*) {
|
|
142
191
|
width: 100% !important;
|
|
143
192
|
height: 100% !important;
|
|
@@ -145,39 +194,40 @@
|
|
|
145
194
|
}
|
|
146
195
|
|
|
147
196
|
.context5__btn {
|
|
148
|
-
width: 30px;
|
|
149
|
-
height: 30px;
|
|
150
|
-
padding: 0;
|
|
151
|
-
border-radius: 50%;
|
|
197
|
+
width: 30px;
|
|
198
|
+
height: 30px;
|
|
199
|
+
padding: 0;
|
|
200
|
+
border-radius: 50%;
|
|
152
201
|
cursor: pointer;
|
|
153
202
|
background-color: var(--context5__IconFillColor);
|
|
154
|
-
border:
|
|
155
|
-
|
|
156
|
-
-webkit-tap-highlight-color: transparent; /* removes blue flash on touch devices */
|
|
157
|
-
display: flex; /* center the icon inside */
|
|
203
|
+
border: 1px solid var(--context5__IconBorderColor);
|
|
204
|
+
display: flex;
|
|
158
205
|
align-items: center;
|
|
159
206
|
justify-content: center;
|
|
160
|
-
|
|
207
|
+
outline: none;
|
|
208
|
+
-webkit-tap-highlight-color: transparent;
|
|
161
209
|
}
|
|
162
210
|
|
|
163
211
|
.context5__btn > svg {
|
|
164
212
|
color: var(--context5__IconColor);
|
|
165
213
|
}
|
|
166
214
|
|
|
215
|
+
.context5__portal {
|
|
216
|
+
position: fixed;
|
|
217
|
+
z-index: 9999;
|
|
218
|
+
}
|
|
219
|
+
|
|
167
220
|
.context5__menu {
|
|
168
|
-
|
|
169
|
-
margin-top: 0.5rem;
|
|
170
|
-
z-index: 1000;
|
|
221
|
+
margin-top: 0.25rem;
|
|
171
222
|
transform-origin: top;
|
|
172
223
|
}
|
|
173
224
|
|
|
174
225
|
.context5__menu.right {
|
|
175
|
-
|
|
226
|
+
transform: translateX(-100%);
|
|
176
227
|
transform-origin: top right;
|
|
177
228
|
}
|
|
178
229
|
|
|
179
230
|
.context5__menu.left {
|
|
180
|
-
left: 0;
|
|
181
231
|
transform-origin: top left;
|
|
182
232
|
}
|
|
183
233
|
|