@threadlabs/looma 0.1.16 → 0.1.18
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 +2 -1
- package/dist/{chunk-SVINNT3E.js → chunk-DTQVRGVL.js} +29 -29
- package/dist/{chunk-G53JEAQK.js → chunk-SZJQ3NPX.js} +6 -3
- package/dist/chunk-YHXJC5M5.js +341 -0
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/looma.cjs.js +1 -1
- package/dist/cjs/{manager-BOpVXb92.js → manager-C9j3HZay.js} +5 -2
- package/dist/cjs/positioning-i0WrCAdF.js +384 -0
- package/dist/cjs/ui-affordance-scope.cjs.entry.js +3 -113
- package/dist/cjs/ui-context-menu.cjs.entry.js +43 -5
- package/dist/cjs/ui-dialog.cjs.entry.js +1 -1
- package/dist/cjs/ui-menu.cjs.entry.js +83 -2
- package/dist/cjs/ui-popover.cjs.entry.js +43 -3
- package/dist/cjs/ui-toast-region.cjs.entry.js +17 -2
- package/dist/cjs/ui-tooltip.cjs.entry.js +95 -27
- package/dist/cjs/ui-tree-item.cjs.entry.js +1 -1
- package/dist/collection/components/ui-context-menu/ui-context-menu.css +21 -4
- package/dist/collection/components/ui-context-menu/ui-context-menu.js +43 -4
- package/dist/collection/components/ui-menu/ui-menu.css +39 -0
- package/dist/collection/components/ui-menu/ui-menu.js +128 -1
- package/dist/collection/components/ui-popover/ui-popover.css +31 -0
- package/dist/collection/components/ui-popover/ui-popover.js +87 -1
- package/dist/collection/components/ui-toast-region/ui-toast-region.css +6 -0
- package/dist/collection/components/ui-toast-region/ui-toast-region.js +16 -1
- package/dist/collection/components/ui-tooltip/ui-tooltip.css +20 -0
- package/dist/collection/components/ui-tooltip/ui-tooltip.js +160 -25
- package/dist/collection/components/ui-tree-item/ui-tree-item.css +10 -6
- package/dist/collection/input-modality.js +24 -0
- package/dist/collection/overlay/manager.js +5 -2
- package/dist/collection/overlay/positioning.js +246 -0
- package/dist/components/p-CEYIKqYc.js +1 -0
- package/dist/components/p-DOulVJT7.js +1 -0
- package/dist/components/p-PM9a74r7.js +1 -0
- package/dist/components/ui-affordance-scope.js +1 -1
- package/dist/components/ui-context-menu.js +1 -1
- package/dist/components/ui-dialog.js +1 -1
- package/dist/components/ui-menu.js +1 -1
- package/dist/components/ui-popover.js +1 -1
- package/dist/components/ui-toast-region.js +1 -1
- package/dist/components/ui-tooltip.js +1 -1
- package/dist/components/ui-tree-item.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/looma.js +1 -1
- package/dist/esm/{manager-CR7f2MQC.js → manager-PM9a74r7.js} +5 -2
- package/dist/esm/positioning-Bu0dmLBE.js +379 -0
- package/dist/esm/ui-affordance-scope.entry.js +1 -111
- package/dist/esm/ui-context-menu.entry.js +43 -5
- package/dist/esm/ui-dialog.entry.js +1 -1
- package/dist/esm/ui-menu.entry.js +83 -2
- package/dist/esm/ui-popover.entry.js +43 -3
- package/dist/esm/ui-toast-region.entry.js +17 -2
- package/dist/esm/ui-tooltip.entry.js +95 -27
- package/dist/esm/ui-tree-item.entry.js +1 -1
- package/dist/index.cjs +779 -59
- package/dist/index.d.cts +44 -1
- package/dist/index.d.ts +44 -1
- package/dist/index.js +235 -4
- package/dist/looma/looma.esm.js +1 -1
- package/dist/looma/p-063f5a89.entry.js +1 -0
- package/dist/looma/{p-c6721aba.entry.js → p-11083743.entry.js} +1 -1
- package/dist/looma/p-1674cda4.entry.js +1 -0
- package/dist/looma/p-2e6f791e.entry.js +1 -0
- package/dist/looma/p-54c41576.entry.js +1 -0
- package/dist/looma/p-9194a99d.entry.js +1 -0
- package/dist/looma/p-Bu0dmLBE.js +1 -0
- package/dist/looma/p-PM9a74r7.js +1 -0
- package/dist/looma/p-caa8fc7b.entry.js +1 -0
- package/dist/looma/{p-ef9ca2ed.entry.js → p-d01960c2.entry.js} +2 -2
- package/dist/types/components/ui-context-menu/ui-context-menu.d.ts +6 -0
- package/dist/types/components/ui-menu/ui-menu.d.ts +13 -0
- package/dist/types/components/ui-popover/ui-popover.d.ts +9 -0
- package/dist/types/components/ui-toast-region/ui-toast-region.d.ts +2 -0
- package/dist/types/components/ui-tooltip/ui-tooltip.d.ts +16 -1
- package/dist/types/components.d.ts +71 -0
- package/dist/types/input-modality.d.ts +6 -0
- package/dist/types/overlay/manager.d.ts +3 -0
- package/dist/types/overlay/positioning.d.ts +33 -0
- package/dist/ui-affordance-scope.entry-2W7ZKAGK.js +54 -0
- package/dist/{ui-avatar-group.entry-DQDP325O.js → ui-avatar-group.entry-SE5JG2FT.js} +1 -1
- package/dist/{ui-avatar.entry-WYIDMOFE.js → ui-avatar.entry-46JDI25A.js} +1 -1
- package/dist/{ui-badge.entry-VGHXPEDT.js → ui-badge.entry-U7G3MEC5.js} +1 -1
- package/dist/{ui-button.entry-LKPLOJ22.js → ui-button.entry-DELD6KMH.js} +1 -1
- package/dist/{ui-checkbox.entry-J74HEA22.js → ui-checkbox.entry-ZUG2P642.js} +1 -1
- package/dist/{ui-context-menu.entry-MQM2FCLI.js → ui-context-menu.entry-L4HTK3PV.js} +43 -6
- package/dist/{ui-dialog.entry-DQMMDO4Z.js → ui-dialog.entry-TQPYD2YI.js} +2 -2
- package/dist/{ui-disclosure.entry-ONF7UZDC.js → ui-disclosure.entry-23TII4YU.js} +1 -1
- package/dist/{ui-floating-action-button.entry-FKTGVC5T.js → ui-floating-action-button.entry-FOQYAFJI.js} +1 -1
- package/dist/{ui-form-field.entry-M3ISWQNU.js → ui-form-field.entry-SCPG4STY.js} +1 -1
- package/dist/{ui-icon-button.entry-AWFIQUHM.js → ui-icon-button.entry-U45ZVAC3.js} +1 -1
- package/dist/{ui-input.entry-JZ6RETMT.js → ui-input.entry-3AIA3G4C.js} +1 -1
- package/dist/{ui-menu-item.entry-5MFR5LFL.js → ui-menu-item.entry-3QO5TG2J.js} +1 -1
- package/dist/ui-menu.entry-JACWGDDG.js +184 -0
- package/dist/{ui-popover.entry-ELCMKO6Y.js → ui-popover.entry-2XP4H3S2.js} +46 -4
- package/dist/{ui-radio-group.entry-RJHUPPEM.js → ui-radio-group.entry-73IKFMDK.js} +1 -1
- package/dist/{ui-radio.entry-3VRDPOY4.js → ui-radio.entry-INJVXUKE.js} +1 -1
- package/dist/{ui-search-result-row.entry-J34YPAV7.js → ui-search-result-row.entry-4J732TDC.js} +1 -1
- package/dist/{ui-search-shell.entry-IJ4UUP27.js → ui-search-shell.entry-3C2WRVE2.js} +1 -1
- package/dist/{ui-select.entry-C6YD3HQ5.js → ui-select.entry-3ZLDGAKX.js} +1 -1
- package/dist/{ui-switch.entry-UZDF5QTI.js → ui-switch.entry-5MJRLR2P.js} +1 -1
- package/dist/{ui-tabs.entry-YRAKWOMR.js → ui-tabs.entry-F5H7OPBO.js} +1 -1
- package/dist/{ui-textarea.entry-JLDKFT3K.js → ui-textarea.entry-BNJ375JB.js} +1 -1
- package/dist/{ui-toast-region.entry-GC7C7KXF.js → ui-toast-region.entry-ZUIPJ2JH.js} +20 -3
- package/dist/ui-tooltip.entry-DZ4RMF35.js +214 -0
- package/dist/{ui-top-bar.entry-5W5UA5KV.js → ui-top-bar.entry-VKRXIUU6.js} +1 -1
- package/dist/{ui-tree-item.entry-3LM7IXIK.js → ui-tree-item.entry-NFUQ45OL.js} +2 -2
- package/dist/{ui-tree.entry-X4FU42A6.js → ui-tree.entry-H4CWDYI6.js} +1 -1
- package/editor/{chunk-RTHHTPWK.js → chunk-3QMBK3XZ.js} +245 -41
- package/editor/{chunk-OHD4OS32.js → chunk-OXFYYLUC.js} +632 -236
- package/editor/{chunk-CX4QDKSV.js → chunk-ZOUKEZ77.js} +21 -1
- package/editor/extensions/index.d.ts +49 -1
- package/editor/extensions/index.js +15 -3
- package/editor/index.d.ts +3 -2
- package/editor/index.js +16 -4
- package/editor/ui.d.ts +9 -1
- package/editor/ui.js +2 -2
- package/editor.css +173 -4
- package/package.json +1 -1
- package/styles.css +1 -7
- package/tokens.css +14 -2
- package/vue/editor/index.d.ts +103 -4
- package/vue/editor/index.js +199 -114
- package/dist/components/p-CR7f2MQC.js +0 -1
- package/dist/components/p-QiwSQmKJ.js +0 -1
- package/dist/looma/p-2ae73d5b.entry.js +0 -1
- package/dist/looma/p-3ac2e0d4.entry.js +0 -1
- package/dist/looma/p-65c25c94.entry.js +0 -1
- package/dist/looma/p-8c09c724.entry.js +0 -1
- package/dist/looma/p-95cd639d.entry.js +0 -1
- package/dist/looma/p-96f73d07.entry.js +0 -1
- package/dist/looma/p-CR7f2MQC.js +0 -1
- package/dist/ui-affordance-scope.entry-PFP2TDKO.js +0 -145
- package/dist/ui-menu.entry-IOEIDATQ.js +0 -98
- package/dist/ui-tooltip.entry-F26XDTYX.js +0 -145
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
const DEFAULT_AFFORDANCE_NEAR_RADIUS = 16;
|
|
2
|
+
let anchorSequence = 0;
|
|
3
|
+
const anchorBindings = new WeakMap();
|
|
4
|
+
function bindAnchorName(anchor, name) {
|
|
5
|
+
const binding = anchorBindings.get(anchor) ?? {
|
|
6
|
+
original: anchor.style.getPropertyValue("anchor-name"),
|
|
7
|
+
names: new Set(),
|
|
8
|
+
};
|
|
9
|
+
binding.names.add(name);
|
|
10
|
+
anchorBindings.set(anchor, binding);
|
|
11
|
+
const values = [binding.original, ...binding.names].filter(Boolean);
|
|
12
|
+
anchor.style.setProperty("anchor-name", values.join(", "));
|
|
13
|
+
}
|
|
14
|
+
function unbindAnchorName(anchor, name) {
|
|
15
|
+
const binding = anchorBindings.get(anchor);
|
|
16
|
+
if (!binding)
|
|
17
|
+
return;
|
|
18
|
+
binding.names.delete(name);
|
|
19
|
+
if (binding.names.size) {
|
|
20
|
+
const values = [binding.original, ...binding.names].filter(Boolean);
|
|
21
|
+
anchor.style.setProperty("anchor-name", values.join(", "));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (binding.original)
|
|
25
|
+
anchor.style.setProperty("anchor-name", binding.original);
|
|
26
|
+
else
|
|
27
|
+
anchor.style.removeProperty("anchor-name");
|
|
28
|
+
anchorBindings.delete(anchor);
|
|
29
|
+
}
|
|
30
|
+
function supportsAnchorPositioning(owner) {
|
|
31
|
+
const css = owner.CSS;
|
|
32
|
+
return typeof css?.supports === "function"
|
|
33
|
+
&& css.supports("anchor-name: --ui-anchor-test")
|
|
34
|
+
&& css.supports("position-anchor: --ui-anchor-test")
|
|
35
|
+
&& css.supports("top: anchor(bottom)");
|
|
36
|
+
}
|
|
37
|
+
function topLayerOpen(surface) {
|
|
38
|
+
try {
|
|
39
|
+
return surface.matches(":popover-open");
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return !surface.hidden;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function showInTopLayer(surface) {
|
|
46
|
+
surface.setAttribute("popover", "manual");
|
|
47
|
+
surface.hidden = false;
|
|
48
|
+
if (typeof surface.showPopover === "function" && !topLayerOpen(surface)) {
|
|
49
|
+
try {
|
|
50
|
+
surface.showPopover();
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// A disconnected or already-transitioning surface still receives the
|
|
54
|
+
// fixed-position fallback below and will be retried on the next sync.
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function hideFromTopLayer(surface) {
|
|
59
|
+
if (typeof surface.hidePopover === "function" && topLayerOpen(surface)) {
|
|
60
|
+
try {
|
|
61
|
+
surface.hidePopover();
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// The surface may have been disconnected between state and DOM updates.
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
surface.hidden = true;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Places unanchored floating UI, such as a toast region, in the browser top
|
|
71
|
+
* layer. Its viewport position remains CSS-owned; the controller only provides
|
|
72
|
+
* the native Popover API boundary and its no-Popover fallback.
|
|
73
|
+
*/
|
|
74
|
+
function createViewportSurface(surface) {
|
|
75
|
+
surface.setAttribute("popover", "manual");
|
|
76
|
+
surface.dataset.uiPositioning = "viewport";
|
|
77
|
+
return {
|
|
78
|
+
show() {
|
|
79
|
+
showInTopLayer(surface);
|
|
80
|
+
},
|
|
81
|
+
hide() {
|
|
82
|
+
hideFromTopLayer(surface);
|
|
83
|
+
},
|
|
84
|
+
destroy() {
|
|
85
|
+
hideFromTopLayer(surface);
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function fallbackPosition(surface, anchor, placement, gap, viewportGap) {
|
|
90
|
+
const owner = surface.ownerDocument.defaultView ?? window;
|
|
91
|
+
const viewport = getVisualViewportRect(owner);
|
|
92
|
+
const rect = surface.getBoundingClientRect();
|
|
93
|
+
const preferTop = placement.startsWith("top");
|
|
94
|
+
const preferEnd = placement.endsWith("end");
|
|
95
|
+
const spaceBelow = viewport.bottom - anchor.bottom - viewportGap;
|
|
96
|
+
const spaceAbove = anchor.top - viewport.top - viewportGap;
|
|
97
|
+
const useTop = preferTop
|
|
98
|
+
? !(spaceAbove < rect.height + gap && spaceBelow > spaceAbove)
|
|
99
|
+
: spaceBelow < rect.height + gap && spaceAbove > spaceBelow;
|
|
100
|
+
const unclampedTop = useTop
|
|
101
|
+
? anchor.top - rect.height - gap
|
|
102
|
+
: anchor.bottom + gap;
|
|
103
|
+
const unclampedLeft = preferEnd
|
|
104
|
+
? anchor.right - rect.width
|
|
105
|
+
: anchor.left;
|
|
106
|
+
const shifted = clampRectToViewport({
|
|
107
|
+
left: unclampedLeft,
|
|
108
|
+
top: unclampedTop,
|
|
109
|
+
width: rect.width,
|
|
110
|
+
height: rect.height,
|
|
111
|
+
}, viewport, viewportGap);
|
|
112
|
+
surface.style.left = `${Math.round(unclampedLeft + shifted.x)}px`;
|
|
113
|
+
surface.style.top = `${Math.round(unclampedTop + shifted.y)}px`;
|
|
114
|
+
surface.style.right = "auto";
|
|
115
|
+
surface.style.bottom = "auto";
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* One lightweight positioning controller for Looma floating UI. Native
|
|
119
|
+
* Popover provides the top layer and CSS Anchor Positioning follows a named
|
|
120
|
+
* element. Browsers without Anchor Positioning use the same flip/shift
|
|
121
|
+
* geometry through scroll/resize listeners that exist only while open.
|
|
122
|
+
*/
|
|
123
|
+
function createAnchoredSurface(surface, options = {}) {
|
|
124
|
+
const owner = surface.ownerDocument.defaultView ?? window;
|
|
125
|
+
const placement = options.placement ?? "bottom-start";
|
|
126
|
+
const gap = Math.max(0, options.gap ?? 4);
|
|
127
|
+
const viewportGap = Math.max(0, options.viewportGap ?? 8);
|
|
128
|
+
const nativeAnchor = supportsAnchorPositioning(owner);
|
|
129
|
+
const anchorName = `--ui-anchor-${++anchorSequence}`;
|
|
130
|
+
let anchor = options.anchor ?? null;
|
|
131
|
+
let point = null;
|
|
132
|
+
let open = false;
|
|
133
|
+
let frame = null;
|
|
134
|
+
let listenerAbort = null;
|
|
135
|
+
surface.setAttribute("popover", "manual");
|
|
136
|
+
surface.dataset.uiPositioning = nativeAnchor ? "anchor" : "fallback";
|
|
137
|
+
surface.style.position = "fixed";
|
|
138
|
+
surface.style.margin = "0";
|
|
139
|
+
const bindAnchor = (next) => {
|
|
140
|
+
if (anchor)
|
|
141
|
+
unbindAnchorName(anchor, anchorName);
|
|
142
|
+
anchor = next;
|
|
143
|
+
if (!anchor) {
|
|
144
|
+
surface.style.removeProperty("position-anchor");
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
bindAnchorName(anchor, anchorName);
|
|
148
|
+
surface.style.setProperty("position-anchor", anchorName);
|
|
149
|
+
};
|
|
150
|
+
const positionNative = () => {
|
|
151
|
+
const blockEnd = placement.startsWith("bottom");
|
|
152
|
+
const inlineEnd = placement.endsWith("end");
|
|
153
|
+
surface.style.top = blockEnd ? `calc(anchor(bottom) + ${gap}px)` : "auto";
|
|
154
|
+
surface.style.bottom = blockEnd ? "auto" : `calc(anchor(top) + ${gap}px)`;
|
|
155
|
+
surface.style.left = inlineEnd ? "auto" : "anchor(left)";
|
|
156
|
+
surface.style.right = inlineEnd ? "anchor(right)" : "auto";
|
|
157
|
+
surface.style.setProperty("position-try-fallbacks", "flip-block, flip-inline");
|
|
158
|
+
};
|
|
159
|
+
const position = () => {
|
|
160
|
+
frame = null;
|
|
161
|
+
if (!open)
|
|
162
|
+
return;
|
|
163
|
+
if (point) {
|
|
164
|
+
fallbackPosition(surface, {
|
|
165
|
+
left: point.x,
|
|
166
|
+
right: point.x,
|
|
167
|
+
top: point.y,
|
|
168
|
+
bottom: point.y}, "bottom-start", gap, viewportGap);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (!anchor)
|
|
172
|
+
return;
|
|
173
|
+
if (nativeAnchor)
|
|
174
|
+
positionNative();
|
|
175
|
+
else
|
|
176
|
+
fallbackPosition(surface, anchor.getBoundingClientRect(), placement, gap, viewportGap);
|
|
177
|
+
};
|
|
178
|
+
const schedule = () => {
|
|
179
|
+
if (!open || frame !== null)
|
|
180
|
+
return;
|
|
181
|
+
frame = owner.requestAnimationFrame(position);
|
|
182
|
+
};
|
|
183
|
+
const syncFallbackListeners = () => {
|
|
184
|
+
const needsListeners = open && (point !== null || !nativeAnchor);
|
|
185
|
+
if (!needsListeners) {
|
|
186
|
+
listenerAbort?.abort();
|
|
187
|
+
listenerAbort = null;
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (listenerAbort)
|
|
191
|
+
return;
|
|
192
|
+
listenerAbort = new AbortController();
|
|
193
|
+
const signal = listenerAbort.signal;
|
|
194
|
+
owner.addEventListener("resize", schedule, { passive: true, signal });
|
|
195
|
+
owner.addEventListener("scroll", schedule, { passive: true, capture: true, signal });
|
|
196
|
+
owner.visualViewport?.addEventListener("resize", schedule, { passive: true, signal });
|
|
197
|
+
owner.visualViewport?.addEventListener("scroll", schedule, { passive: true, signal });
|
|
198
|
+
};
|
|
199
|
+
bindAnchor(anchor);
|
|
200
|
+
return {
|
|
201
|
+
setAnchor(next) {
|
|
202
|
+
point = null;
|
|
203
|
+
bindAnchor(next);
|
|
204
|
+
syncFallbackListeners();
|
|
205
|
+
schedule();
|
|
206
|
+
},
|
|
207
|
+
show() {
|
|
208
|
+
point = null;
|
|
209
|
+
open = true;
|
|
210
|
+
syncFallbackListeners();
|
|
211
|
+
showInTopLayer(surface);
|
|
212
|
+
position();
|
|
213
|
+
},
|
|
214
|
+
showAtPoint(nextPoint) {
|
|
215
|
+
point = nextPoint;
|
|
216
|
+
open = true;
|
|
217
|
+
syncFallbackListeners();
|
|
218
|
+
showInTopLayer(surface);
|
|
219
|
+
position();
|
|
220
|
+
},
|
|
221
|
+
hide() {
|
|
222
|
+
open = false;
|
|
223
|
+
point = null;
|
|
224
|
+
syncFallbackListeners();
|
|
225
|
+
if (frame !== null)
|
|
226
|
+
owner.cancelAnimationFrame(frame);
|
|
227
|
+
frame = null;
|
|
228
|
+
hideFromTopLayer(surface);
|
|
229
|
+
},
|
|
230
|
+
refresh: schedule,
|
|
231
|
+
destroy() {
|
|
232
|
+
open = false;
|
|
233
|
+
listenerAbort?.abort();
|
|
234
|
+
listenerAbort = null;
|
|
235
|
+
if (frame !== null)
|
|
236
|
+
owner.cancelAnimationFrame(frame);
|
|
237
|
+
frame = null;
|
|
238
|
+
hideFromTopLayer(surface);
|
|
239
|
+
bindAnchor(null);
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function getVisualViewportRect(owner = window) {
|
|
244
|
+
const viewport = owner.visualViewport;
|
|
245
|
+
const left = viewport?.offsetLeft ?? 0;
|
|
246
|
+
const top = viewport?.offsetTop ?? 0;
|
|
247
|
+
const width = viewport?.width ?? owner.innerWidth;
|
|
248
|
+
const height = viewport?.height ?? owner.innerHeight;
|
|
249
|
+
return {
|
|
250
|
+
left,
|
|
251
|
+
top,
|
|
252
|
+
right: left + width,
|
|
253
|
+
bottom: top + height,
|
|
254
|
+
width,
|
|
255
|
+
height,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function clampRectToViewport(rect, viewport = getVisualViewportRect(), gutter = 0) {
|
|
259
|
+
const availableWidth = Math.max(0, viewport.width - (gutter * 2));
|
|
260
|
+
const availableHeight = Math.max(0, viewport.height - (gutter * 2));
|
|
261
|
+
const targetLeft = rect.width > availableWidth
|
|
262
|
+
? viewport.left + gutter
|
|
263
|
+
: Math.min(Math.max(rect.left, viewport.left + gutter), viewport.right - gutter - rect.width);
|
|
264
|
+
const targetTop = rect.height > availableHeight
|
|
265
|
+
? viewport.top + gutter
|
|
266
|
+
: Math.min(Math.max(rect.top, viewport.top + gutter), viewport.bottom - gutter - rect.height);
|
|
267
|
+
return { x: targetLeft - rect.left, y: targetTop - rect.top };
|
|
268
|
+
}
|
|
269
|
+
function distanceFromPointToRect(point, rect) {
|
|
270
|
+
const dx = Math.max(rect.left - point.x, 0, point.x - rect.right);
|
|
271
|
+
const dy = Math.max(rect.top - point.y, 0, point.y - rect.bottom);
|
|
272
|
+
return Math.hypot(dx, dy);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Coordinates anticipatory UI within one interaction scope.
|
|
276
|
+
*
|
|
277
|
+
* The coordinator deliberately owns one pointer listener and one animation-frame
|
|
278
|
+
* update for the whole scope. Anchors remain the only hit-testable controls; the
|
|
279
|
+
* reflected state is presentation-only, so overlapping near regions do not steal
|
|
280
|
+
* pointer input from each other or from surrounding content.
|
|
281
|
+
*/
|
|
282
|
+
function createProximityCoordinator(scope, options = {}) {
|
|
283
|
+
const owner = scope.ownerDocument.defaultView ?? window;
|
|
284
|
+
const pointerTarget = options.pointerTarget ?? scope;
|
|
285
|
+
const anchorSelector = options.anchorSelector ?? "[data-ui-affordance]";
|
|
286
|
+
const configuredRadius = options.nearRadius ?? DEFAULT_AFFORDANCE_NEAR_RADIUS;
|
|
287
|
+
const nearRadius = Number.isFinite(configuredRadius)
|
|
288
|
+
? Math.max(0, configuredRadius)
|
|
289
|
+
: DEFAULT_AFFORDANCE_NEAR_RADIUS;
|
|
290
|
+
const abort = new AbortController();
|
|
291
|
+
let anchors = [];
|
|
292
|
+
let frame = null;
|
|
293
|
+
let point = null;
|
|
294
|
+
let geometryDirty = false;
|
|
295
|
+
const clear = () => {
|
|
296
|
+
for (const { element } of anchors) {
|
|
297
|
+
if (element.hasAttribute("data-ui-proximity")) {
|
|
298
|
+
element.removeAttribute("data-ui-proximity");
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (scope.hasAttribute("data-ui-interaction")) {
|
|
302
|
+
scope.removeAttribute("data-ui-interaction");
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
const measure = () => {
|
|
306
|
+
anchors = Array.from(scope.querySelectorAll(anchorSelector))
|
|
307
|
+
.filter((element) => !element.hasAttribute("disabled") && element.getAttribute("aria-disabled") !== "true")
|
|
308
|
+
.map((element) => ({ element, rect: element.getBoundingClientRect() }));
|
|
309
|
+
geometryDirty = false;
|
|
310
|
+
};
|
|
311
|
+
const update = () => {
|
|
312
|
+
frame = null;
|
|
313
|
+
if (geometryDirty)
|
|
314
|
+
measure();
|
|
315
|
+
if (!point) {
|
|
316
|
+
clear();
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
let engaged = false;
|
|
320
|
+
for (const anchor of anchors) {
|
|
321
|
+
const near = distanceFromPointToRect(point, anchor.rect) <= nearRadius;
|
|
322
|
+
if (near && anchor.element.getAttribute("data-ui-proximity") !== "near") {
|
|
323
|
+
anchor.element.setAttribute("data-ui-proximity", "near");
|
|
324
|
+
}
|
|
325
|
+
else if (!near && anchor.element.hasAttribute("data-ui-proximity")) {
|
|
326
|
+
anchor.element.removeAttribute("data-ui-proximity");
|
|
327
|
+
}
|
|
328
|
+
engaged ||= near;
|
|
329
|
+
}
|
|
330
|
+
if (engaged && scope.getAttribute("data-ui-interaction") !== "engaged") {
|
|
331
|
+
scope.setAttribute("data-ui-interaction", "engaged");
|
|
332
|
+
}
|
|
333
|
+
else if (!engaged && scope.hasAttribute("data-ui-interaction")) {
|
|
334
|
+
scope.removeAttribute("data-ui-interaction");
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
const schedule = () => {
|
|
338
|
+
if (frame !== null)
|
|
339
|
+
return;
|
|
340
|
+
frame = owner.requestAnimationFrame(update);
|
|
341
|
+
};
|
|
342
|
+
const onPointerMove = (event) => {
|
|
343
|
+
const pointer = event;
|
|
344
|
+
if (pointer.pointerType === "touch") {
|
|
345
|
+
point = null;
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
point = { x: pointer.clientX, y: pointer.clientY };
|
|
349
|
+
}
|
|
350
|
+
schedule();
|
|
351
|
+
};
|
|
352
|
+
const invalidate = () => {
|
|
353
|
+
geometryDirty = true;
|
|
354
|
+
schedule();
|
|
355
|
+
};
|
|
356
|
+
pointerTarget.addEventListener("pointermove", onPointerMove, {
|
|
357
|
+
passive: true,
|
|
358
|
+
signal: abort.signal,
|
|
359
|
+
});
|
|
360
|
+
owner.addEventListener("resize", invalidate, { passive: true, signal: abort.signal });
|
|
361
|
+
owner.addEventListener("scroll", invalidate, { passive: true, capture: true, signal: abort.signal });
|
|
362
|
+
owner.visualViewport?.addEventListener("resize", invalidate, { passive: true, signal: abort.signal });
|
|
363
|
+
owner.visualViewport?.addEventListener("scroll", invalidate, { passive: true, signal: abort.signal });
|
|
364
|
+
measure();
|
|
365
|
+
return {
|
|
366
|
+
refresh: invalidate,
|
|
367
|
+
destroy() {
|
|
368
|
+
abort.abort();
|
|
369
|
+
if (frame !== null)
|
|
370
|
+
owner.cancelAnimationFrame(frame);
|
|
371
|
+
frame = null;
|
|
372
|
+
point = null;
|
|
373
|
+
clear();
|
|
374
|
+
anchors = [];
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export { DEFAULT_AFFORDANCE_NEAR_RADIUS as D, createAnchoredSurface as a, createViewportSurface as b, createProximityCoordinator as c };
|
|
@@ -1,115 +1,5 @@
|
|
|
1
1
|
import { r as registerInstance, g as getElement, h, H as Host } from './index-CEeiinfk.js';
|
|
2
|
-
|
|
3
|
-
const DEFAULT_AFFORDANCE_NEAR_RADIUS = 16;
|
|
4
|
-
function distanceFromPointToRect(point, rect) {
|
|
5
|
-
const dx = Math.max(rect.left - point.x, 0, point.x - rect.right);
|
|
6
|
-
const dy = Math.max(rect.top - point.y, 0, point.y - rect.bottom);
|
|
7
|
-
return Math.hypot(dx, dy);
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Coordinates anticipatory UI within one interaction scope.
|
|
11
|
-
*
|
|
12
|
-
* The coordinator deliberately owns one pointer listener and one animation-frame
|
|
13
|
-
* update for the whole scope. Anchors remain the only hit-testable controls; the
|
|
14
|
-
* reflected state is presentation-only, so overlapping near regions do not steal
|
|
15
|
-
* pointer input from each other or from surrounding content.
|
|
16
|
-
*/
|
|
17
|
-
function createProximityCoordinator(scope, options = {}) {
|
|
18
|
-
const owner = scope.ownerDocument.defaultView ?? window;
|
|
19
|
-
const pointerTarget = options.pointerTarget ?? scope;
|
|
20
|
-
const anchorSelector = options.anchorSelector ?? "[data-ui-affordance]";
|
|
21
|
-
const configuredRadius = options.nearRadius ?? DEFAULT_AFFORDANCE_NEAR_RADIUS;
|
|
22
|
-
const nearRadius = Number.isFinite(configuredRadius)
|
|
23
|
-
? Math.max(0, configuredRadius)
|
|
24
|
-
: DEFAULT_AFFORDANCE_NEAR_RADIUS;
|
|
25
|
-
const abort = new AbortController();
|
|
26
|
-
let anchors = [];
|
|
27
|
-
let frame = null;
|
|
28
|
-
let point = null;
|
|
29
|
-
let geometryDirty = false;
|
|
30
|
-
const clear = () => {
|
|
31
|
-
for (const { element } of anchors) {
|
|
32
|
-
if (element.hasAttribute("data-ui-proximity")) {
|
|
33
|
-
element.removeAttribute("data-ui-proximity");
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
if (scope.hasAttribute("data-ui-interaction")) {
|
|
37
|
-
scope.removeAttribute("data-ui-interaction");
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
const measure = () => {
|
|
41
|
-
anchors = Array.from(scope.querySelectorAll(anchorSelector))
|
|
42
|
-
.filter((element) => !element.hasAttribute("disabled") && element.getAttribute("aria-disabled") !== "true")
|
|
43
|
-
.map((element) => ({ element, rect: element.getBoundingClientRect() }));
|
|
44
|
-
geometryDirty = false;
|
|
45
|
-
};
|
|
46
|
-
const update = () => {
|
|
47
|
-
frame = null;
|
|
48
|
-
if (geometryDirty)
|
|
49
|
-
measure();
|
|
50
|
-
if (!point) {
|
|
51
|
-
clear();
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
let engaged = false;
|
|
55
|
-
for (const anchor of anchors) {
|
|
56
|
-
const near = distanceFromPointToRect(point, anchor.rect) <= nearRadius;
|
|
57
|
-
if (near && anchor.element.getAttribute("data-ui-proximity") !== "near") {
|
|
58
|
-
anchor.element.setAttribute("data-ui-proximity", "near");
|
|
59
|
-
}
|
|
60
|
-
else if (!near && anchor.element.hasAttribute("data-ui-proximity")) {
|
|
61
|
-
anchor.element.removeAttribute("data-ui-proximity");
|
|
62
|
-
}
|
|
63
|
-
engaged ||= near;
|
|
64
|
-
}
|
|
65
|
-
if (engaged && scope.getAttribute("data-ui-interaction") !== "engaged") {
|
|
66
|
-
scope.setAttribute("data-ui-interaction", "engaged");
|
|
67
|
-
}
|
|
68
|
-
else if (!engaged && scope.hasAttribute("data-ui-interaction")) {
|
|
69
|
-
scope.removeAttribute("data-ui-interaction");
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
const schedule = () => {
|
|
73
|
-
if (frame !== null)
|
|
74
|
-
return;
|
|
75
|
-
frame = owner.requestAnimationFrame(update);
|
|
76
|
-
};
|
|
77
|
-
const onPointerMove = (event) => {
|
|
78
|
-
const pointer = event;
|
|
79
|
-
if (pointer.pointerType === "touch") {
|
|
80
|
-
point = null;
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
point = { x: pointer.clientX, y: pointer.clientY };
|
|
84
|
-
}
|
|
85
|
-
schedule();
|
|
86
|
-
};
|
|
87
|
-
const invalidate = () => {
|
|
88
|
-
geometryDirty = true;
|
|
89
|
-
schedule();
|
|
90
|
-
};
|
|
91
|
-
pointerTarget.addEventListener("pointermove", onPointerMove, {
|
|
92
|
-
passive: true,
|
|
93
|
-
signal: abort.signal,
|
|
94
|
-
});
|
|
95
|
-
owner.addEventListener("resize", invalidate, { passive: true, signal: abort.signal });
|
|
96
|
-
owner.addEventListener("scroll", invalidate, { passive: true, capture: true, signal: abort.signal });
|
|
97
|
-
owner.visualViewport?.addEventListener("resize", invalidate, { passive: true, signal: abort.signal });
|
|
98
|
-
owner.visualViewport?.addEventListener("scroll", invalidate, { passive: true, signal: abort.signal });
|
|
99
|
-
measure();
|
|
100
|
-
return {
|
|
101
|
-
refresh: invalidate,
|
|
102
|
-
destroy() {
|
|
103
|
-
abort.abort();
|
|
104
|
-
if (frame !== null)
|
|
105
|
-
owner.cancelAnimationFrame(frame);
|
|
106
|
-
frame = null;
|
|
107
|
-
point = null;
|
|
108
|
-
clear();
|
|
109
|
-
anchors = [];
|
|
110
|
-
},
|
|
111
|
-
};
|
|
112
|
-
}
|
|
2
|
+
import { D as DEFAULT_AFFORDANCE_NEAR_RADIUS, c as createProximityCoordinator } from './positioning-Bu0dmLBE.js';
|
|
113
3
|
|
|
114
4
|
const uiAffordanceScopeCss = () => `:host{display:contents;--ui-affordance-scope-engaged:0}:host([data-ui-interaction='engaged']){--ui-affordance-scope-engaged:1}`;
|
|
115
5
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { r as registerInstance, g as getElement, h, H as Host } from './index-CEeiinfk.js';
|
|
2
|
-
import { o as openOverlay, c as closeOverlay, r as requestTopOverlayClose } from './manager-
|
|
2
|
+
import { o as openOverlay, c as closeOverlay, r as requestTopOverlayClose } from './manager-PM9a74r7.js';
|
|
3
3
|
import { d as dispatchDetail } from './events-JwSoedEO.js';
|
|
4
|
+
import { a as createAnchoredSurface } from './positioning-Bu0dmLBE.js';
|
|
4
5
|
|
|
5
|
-
const uiContextMenuCss = () => `:host{display:contents}.menu{position:fixed;z-index:var(--ui-z-overlay, 1000);min-width:12rem}.menu
|
|
6
|
+
const uiContextMenuCss = () => `:host{display:contents}:host([data-focus-trigger='pointer']) ::slotted(ui-menu-item:focus){outline:none}.menu{position:fixed;inset:auto;margin:0;z-index:var(--ui-z-overlay, 1000);min-width:12rem;opacity:0;transform:translateY(-4px) scale(0.99);transition:opacity var(--ui-motion-fast) var(--ui-motion-ease), transform var(--ui-motion-fast) var(--ui-motion-ease), display var(--ui-motion-fast) allow-discrete, overlay var(--ui-motion-fast) allow-discrete}.menu:popover-open{opacity:1;transform:translateY(0) scale(1)}@starting-style{.menu:popover-open{opacity:0;transform:translateY(-4px) scale(0.99)}}.menu[hidden]{display:none !important}@media (prefers-reduced-motion: reduce){.menu{transition:none}}`;
|
|
6
7
|
|
|
7
8
|
const UIContextMenu = class {
|
|
8
9
|
constructor(hostRef) {
|
|
@@ -16,11 +17,14 @@ const UIContextMenu = class {
|
|
|
16
17
|
/** Optional id of the region that should also respond to a context-menu gesture. */
|
|
17
18
|
for;
|
|
18
19
|
internalOpen = false;
|
|
20
|
+
focusTrigger = 'programmatic';
|
|
19
21
|
overlayId = `ui-context-menu-${Math.random().toString(36).slice(2, 11)}`;
|
|
20
22
|
trigger = null;
|
|
21
23
|
contextTarget = null;
|
|
22
24
|
pointerX = 0;
|
|
23
25
|
pointerY = 0;
|
|
26
|
+
pointPositioned = false;
|
|
27
|
+
surface = null;
|
|
24
28
|
syncFromProp() {
|
|
25
29
|
this.internalOpen = this.open;
|
|
26
30
|
}
|
|
@@ -31,6 +35,12 @@ const UIContextMenu = class {
|
|
|
31
35
|
syncOverlay() {
|
|
32
36
|
this.syncTriggerState();
|
|
33
37
|
if (this.internalOpen) {
|
|
38
|
+
if (this.pointPositioned) {
|
|
39
|
+
this.surface?.showAtPoint({ x: this.pointerX, y: this.pointerY });
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
this.surface?.show();
|
|
43
|
+
}
|
|
34
44
|
openOverlay({
|
|
35
45
|
id: this.overlayId,
|
|
36
46
|
modal: false,
|
|
@@ -40,6 +50,7 @@ const UIContextMenu = class {
|
|
|
40
50
|
});
|
|
41
51
|
}
|
|
42
52
|
else {
|
|
53
|
+
this.surface?.hide();
|
|
43
54
|
closeOverlay(this.overlayId);
|
|
44
55
|
}
|
|
45
56
|
}
|
|
@@ -48,18 +59,33 @@ const UIContextMenu = class {
|
|
|
48
59
|
this.internalOpen = this.internalOpen || this.defaultOpen;
|
|
49
60
|
this.resolveTargets();
|
|
50
61
|
this.attachTargetListeners();
|
|
62
|
+
this.setupSurface();
|
|
51
63
|
this.syncTriggerState();
|
|
52
64
|
this.syncOverlay();
|
|
53
65
|
}
|
|
54
66
|
componentDidUpdate() {
|
|
55
67
|
this.resolveTargets();
|
|
56
68
|
this.attachTargetListeners();
|
|
69
|
+
if (!this.pointPositioned)
|
|
70
|
+
this.surface?.setAnchor(this.trigger);
|
|
57
71
|
this.syncTriggerState();
|
|
58
72
|
}
|
|
59
73
|
disconnectedCallback() {
|
|
60
74
|
this.detachTargetListeners();
|
|
75
|
+
this.surface?.destroy();
|
|
76
|
+
this.surface = null;
|
|
61
77
|
closeOverlay(this.overlayId);
|
|
62
78
|
}
|
|
79
|
+
setupSurface() {
|
|
80
|
+
const menu = this.host.shadowRoot?.querySelector('.menu');
|
|
81
|
+
if (!menu)
|
|
82
|
+
return;
|
|
83
|
+
this.surface?.destroy();
|
|
84
|
+
this.surface = createAnchoredSurface(menu, {
|
|
85
|
+
anchor: this.trigger,
|
|
86
|
+
placement: 'bottom-start',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
63
89
|
resolveTargets() {
|
|
64
90
|
const previousTrigger = this.trigger;
|
|
65
91
|
const previousContextTarget = this.contextTarget;
|
|
@@ -99,6 +125,11 @@ const UIContextMenu = class {
|
|
|
99
125
|
openMenu(x, y, trigger) {
|
|
100
126
|
this.pointerX = x;
|
|
101
127
|
this.pointerY = y;
|
|
128
|
+
this.focusTrigger = trigger;
|
|
129
|
+
this.pointPositioned = true;
|
|
130
|
+
// Context-click can reposition an already-open trigger menu, so do not
|
|
131
|
+
// depend on a state transition to run the positioning controller.
|
|
132
|
+
this.surface?.showAtPoint({ x, y });
|
|
102
133
|
this.internalOpen = true;
|
|
103
134
|
dispatchDetail(this.host, 'open', {
|
|
104
135
|
open: true,
|
|
@@ -110,8 +141,14 @@ const UIContextMenu = class {
|
|
|
110
141
|
openFromTrigger(trigger) {
|
|
111
142
|
if (!this.trigger)
|
|
112
143
|
return;
|
|
113
|
-
|
|
114
|
-
this.
|
|
144
|
+
this.pointPositioned = false;
|
|
145
|
+
this.internalOpen = true;
|
|
146
|
+
dispatchDetail(this.host, 'open', {
|
|
147
|
+
open: true,
|
|
148
|
+
reason: 'action',
|
|
149
|
+
trigger,
|
|
150
|
+
});
|
|
151
|
+
this.focusFirstItem();
|
|
115
152
|
}
|
|
116
153
|
closeMenu(reason, trigger, returnFocus = true) {
|
|
117
154
|
if (!this.internalOpen)
|
|
@@ -156,6 +193,7 @@ const UIContextMenu = class {
|
|
|
156
193
|
onKeydown = (event) => {
|
|
157
194
|
if (!this.internalOpen)
|
|
158
195
|
return;
|
|
196
|
+
this.focusTrigger = 'keyboard';
|
|
159
197
|
if (event.key === 'Escape') {
|
|
160
198
|
event.preventDefault();
|
|
161
199
|
requestTopOverlayClose('escape', 'keyboard');
|
|
@@ -180,7 +218,7 @@ const UIContextMenu = class {
|
|
|
180
218
|
this.closeMenu('action', 'pointer');
|
|
181
219
|
};
|
|
182
220
|
render() {
|
|
183
|
-
return (h(Host, { key: '
|
|
221
|
+
return (h(Host, { key: '4db0d5b55ead41925aa682b1e383b5735b49bf56', "data-open": this.internalOpen ? '' : undefined, "data-focus-trigger": this.internalOpen ? this.focusTrigger : undefined, onKeyDown: this.onKeydown, onClick: this.onItemClick }, h("slot", { key: '462925d53db169c13e485789ae91e28b0abd3e40', name: "trigger" }), h("div", { key: 'cac8f3b11c4872d38e976f210ce9a43fd854b335', class: "menu", "data-open": this.internalOpen ? '' : undefined }, h("ui-menu", { key: 'ba50f74e11466da2240f7568479d5d10a614b394', open: this.internalOpen }, h("slot", { key: '1fcb45bf124e2377ac6c7fc236d2babf0d9e3bae' })))));
|
|
184
222
|
}
|
|
185
223
|
static get watchers() { return {
|
|
186
224
|
"open": [{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as registerInstance, g as getElement, h, H as Host } from './index-CEeiinfk.js';
|
|
2
|
-
import { o as openOverlay, c as closeOverlay, r as requestTopOverlayClose } from './manager-
|
|
2
|
+
import { o as openOverlay, c as closeOverlay, r as requestTopOverlayClose } from './manager-PM9a74r7.js';
|
|
3
3
|
import { d as dispatchDetail } from './events-JwSoedEO.js';
|
|
4
4
|
|
|
5
5
|
const uiDialogCss = () => `:host{display:block}:host:not([data-open]){display:none}:host dialog{--ui-dialog-duration:var(--ui-motion-base);--ui-dialog-viewport-gap:var(--ui-space-4, 1rem);position:fixed;inset:0;inline-size:min( calc(100% - (var(--ui-dialog-viewport-gap) * 2)), var(--ui-dialog-max-width, 440px) );max-inline-size:none;max-block-size:calc(100dvh - (var(--ui-dialog-viewport-gap) * 2));margin:auto;padding:var(--ui-space-4);overflow:auto;background:var(--ui-surface-elevated);border:1px solid var(--ui-border-default);border-radius:var(--ui-radius-dialog);box-shadow:var(--ui-shadow-dialog);visibility:hidden;pointer-events:none;opacity:0;transform:scale(0.96);transition:opacity var(--ui-dialog-duration) var(--ui-motion-ease), transform var(--ui-dialog-duration) var(--ui-motion-ease), visibility var(--ui-dialog-duration), display var(--ui-dialog-duration) var(--ui-motion-ease) allow-discrete, overlay var(--ui-dialog-duration) var(--ui-motion-ease) allow-discrete}:host dialog[open]{visibility:visible;pointer-events:auto;opacity:1;transform:scale(1);animation:ui-dialog-enter var(--ui-dialog-duration) var(--ui-motion-ease)}@keyframes ui-dialog-enter{from{opacity:0;transform:scale(0.96)}}:host dialog::backdrop{background-color:transparent;transition:background-color var(--ui-dialog-duration) var(--ui-motion-ease), display var(--ui-dialog-duration) var(--ui-motion-ease) allow-discrete, overlay var(--ui-dialog-duration) var(--ui-motion-ease) allow-discrete}:host dialog[open]::backdrop{background-color:var(--ui-overlay-backdrop);animation:ui-dialog-backdrop-enter var(--ui-dialog-duration) var(--ui-motion-ease)}@keyframes ui-dialog-backdrop-enter{from{background-color:transparent}}`;
|