@x33025/sveltely 0.0.26 → 0.0.28
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.
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { tick } from 'svelte';
|
|
2
3
|
import type { Snippet } from 'svelte';
|
|
3
4
|
import { portalContent } from '../../actions/portal';
|
|
4
5
|
|
|
@@ -23,9 +24,11 @@
|
|
|
23
24
|
let isOpen = $state(false);
|
|
24
25
|
let triggerEl = $state<HTMLElement | null>(null);
|
|
25
26
|
let menuEl = $state<HTMLElement | null>(null);
|
|
27
|
+
let contentEl = $state<HTMLElement | null>(null);
|
|
26
28
|
let menuCoords = $state({ top: 0, left: 0 });
|
|
27
29
|
let menuTransform = $state('none');
|
|
28
30
|
let resolvedAnchor = $state<'top' | 'bottom' | 'leading' | 'trailing'>('bottom');
|
|
31
|
+
let computedMenuRadius = $state<string | null>(null);
|
|
29
32
|
|
|
30
33
|
type Point = { x: number; y: number };
|
|
31
34
|
|
|
@@ -87,7 +90,46 @@
|
|
|
87
90
|
];
|
|
88
91
|
};
|
|
89
92
|
|
|
90
|
-
|
|
93
|
+
const parsePx = (value: string) => {
|
|
94
|
+
const first = value.split(' ')[0];
|
|
95
|
+
const parsed = Number.parseFloat(first);
|
|
96
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
function updateComputedMenuRadius() {
|
|
100
|
+
if (!menuEl || !contentEl) {
|
|
101
|
+
computedMenuRadius = null;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const itemEl = contentEl.querySelector<HTMLElement>('.dropdown-item');
|
|
106
|
+
if (!itemEl) {
|
|
107
|
+
computedMenuRadius = null;
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const itemRect = itemEl.getBoundingClientRect();
|
|
112
|
+
const itemStyle = getComputedStyle(itemEl);
|
|
113
|
+
const itemRadius = parsePx(itemStyle.borderTopLeftRadius);
|
|
114
|
+
const effectiveItemRadius = Math.min(itemRadius, itemRect.height / 2, itemRect.width / 2);
|
|
115
|
+
|
|
116
|
+
const contentStyle = getComputedStyle(contentEl);
|
|
117
|
+
const contentPadding = Math.min(
|
|
118
|
+
parsePx(contentStyle.paddingTop),
|
|
119
|
+
parsePx(contentStyle.paddingLeft)
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const menuRect = menuEl.getBoundingClientRect();
|
|
123
|
+
const outerRadius = Math.min(
|
|
124
|
+
effectiveItemRadius + contentPadding,
|
|
125
|
+
menuRect.height / 2,
|
|
126
|
+
menuRect.width / 2
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
computedMenuRadius = `${outerRadius}px`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function open() {
|
|
91
133
|
if (triggerEl) {
|
|
92
134
|
const rect = triggerEl.getBoundingClientRect();
|
|
93
135
|
const spaceAbove = rect.top;
|
|
@@ -125,10 +167,13 @@
|
|
|
125
167
|
}
|
|
126
168
|
}
|
|
127
169
|
isOpen = true;
|
|
170
|
+
await tick();
|
|
171
|
+
updateComputedMenuRadius();
|
|
128
172
|
}
|
|
129
173
|
|
|
130
174
|
function close() {
|
|
131
175
|
isOpen = false;
|
|
176
|
+
computedMenuRadius = null;
|
|
132
177
|
}
|
|
133
178
|
|
|
134
179
|
function toggle() {
|
|
@@ -170,6 +215,11 @@
|
|
|
170
215
|
function handleSelect() {
|
|
171
216
|
if (closeOnSelect) close();
|
|
172
217
|
}
|
|
218
|
+
|
|
219
|
+
$effect(() => {
|
|
220
|
+
if (!isOpen) return;
|
|
221
|
+
updateComputedMenuRadius();
|
|
222
|
+
});
|
|
173
223
|
</script>
|
|
174
224
|
|
|
175
225
|
<svelte:window
|
|
@@ -197,7 +247,8 @@
|
|
|
197
247
|
<div
|
|
198
248
|
use:portalContent
|
|
199
249
|
class="dropdown-menu fixed z-50 border border-gray-200 focus:outline-none"
|
|
200
|
-
style="top: {menuCoords.top}px; left: {menuCoords.left}px; transform: {menuTransform}; border-radius:
|
|
250
|
+
style="top: {menuCoords.top}px; left: {menuCoords.left}px; transform: {menuTransform}; border-radius: {computedMenuRadius ??
|
|
251
|
+
'var(--dropdown-border-radius)'}; background: var(--dropdown-background); box-shadow: var(--dropdown-shadow);"
|
|
201
252
|
role="menu"
|
|
202
253
|
aria-orientation="vertical"
|
|
203
254
|
tabindex="-1"
|
|
@@ -208,6 +259,7 @@
|
|
|
208
259
|
style="padding: var(--dropdown-content-padding);"
|
|
209
260
|
role="none"
|
|
210
261
|
onclick={handleSelect}
|
|
262
|
+
bind:this={contentEl}
|
|
211
263
|
>
|
|
212
264
|
{@render children()}
|
|
213
265
|
</div>
|
package/dist/style/index.css
CHANGED
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
.dropdown-item {
|
|
52
|
-
border-radius:
|
|
52
|
+
border-radius: var(--dropdown-item-border-radius);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
.dropdown-item:hover {
|
|
@@ -67,8 +67,9 @@
|
|
|
67
67
|
--sheet-blur: var(--blur-sm);
|
|
68
68
|
--sheet-shadow: var(--shadow-md);
|
|
69
69
|
|
|
70
|
-
--dropdown-border-radius: var(--radius-md);
|
|
71
70
|
--dropdown-content-padding: calc(var(--spacing));
|
|
71
|
+
--dropdown-item-border-radius: var(--radius-md);
|
|
72
|
+
--dropdown-border-radius: var(--radius-md);
|
|
72
73
|
--dropdown-background: var(--color-white);
|
|
73
74
|
--dropdown-shadow: var(--shadow-md);
|
|
74
75
|
--dropdown-item-highlight: var(--color-zinc-100);
|
package/dist/style.css
CHANGED
|
@@ -586,7 +586,7 @@
|
|
|
586
586
|
padding: 0;
|
|
587
587
|
}
|
|
588
588
|
.dropdown-item {
|
|
589
|
-
border-radius:
|
|
589
|
+
border-radius: var(--dropdown-item-border-radius);
|
|
590
590
|
}
|
|
591
591
|
.dropdown-item:hover {
|
|
592
592
|
background: var(--dropdown-item-highlight);
|
|
@@ -603,8 +603,9 @@
|
|
|
603
603
|
}
|
|
604
604
|
--sheet-blur: var(--blur-sm);
|
|
605
605
|
--sheet-shadow: var(--shadow-md);
|
|
606
|
-
--dropdown-border-radius: var(--radius-md);
|
|
607
606
|
--dropdown-content-padding: calc(var(--spacing));
|
|
607
|
+
--dropdown-item-border-radius: var(--radius-md);
|
|
608
|
+
--dropdown-border-radius: var(--radius-md);
|
|
608
609
|
--dropdown-background: var(--color-white);
|
|
609
610
|
--dropdown-shadow: var(--shadow-md);
|
|
610
611
|
--dropdown-item-highlight: var(--color-zinc-100);
|