@antadesign/anta 0.2.0 → 0.2.1
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 +40 -1
- package/dist/components/Progress.module.css +0 -5
- package/dist/components/Text.module.css +0 -6
- package/dist/elements/a-button.css +1 -756
- package/dist/elements/a-icon.css +1 -43
- package/dist/elements/a-icon.shapes.css +1 -377
- package/dist/elements/a-progress.css +1 -68
- package/dist/elements/a-tag.css +1 -196
- package/dist/elements/a-text.css +1 -90
- package/dist/elements/a-title.css +1 -64
- package/dist/elements/a-tooltip.css +1 -62
- package/dist/index.d.ts +1 -0
- package/dist/jsx-runtime.d.ts +17 -15
- package/dist/reset.css +1 -209
- package/dist/tokens.css +1 -285
- package/package.json +6 -4
- package/dist/components/Button.module.css +0 -2
- package/dist/components/Menu.d.ts +0 -61
- package/dist/components/Menu.js +0 -34
- package/dist/components/MenuGroup.d.ts +0 -24
- package/dist/components/MenuGroup.js +0 -19
- package/dist/components/MenuItem.d.ts +0 -49
- package/dist/components/MenuItem.js +0 -40
- package/dist/components/MenuSeparator.d.ts +0 -14
- package/dist/components/MenuSeparator.js +0 -7
- package/dist/components/Sticker.d.ts +0 -31
- package/dist/components/Sticker.js +0 -17
- package/dist/components/StickerAnimated.d.ts +0 -23
- package/dist/components/StickerAnimated.js +0 -28
- package/dist/components/__generated__/stickers/angry-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/angry-animated.js +0 -7
- package/dist/components/__generated__/stickers/angry.d.ts +0 -3
- package/dist/components/__generated__/stickers/angry.js +0 -7
- package/dist/components/__generated__/stickers/ask-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/ask-animated.js +0 -7
- package/dist/components/__generated__/stickers/ask.d.ts +0 -3
- package/dist/components/__generated__/stickers/ask.js +0 -7
- package/dist/components/__generated__/stickers/balance-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/balance-animated.js +0 -7
- package/dist/components/__generated__/stickers/balance.d.ts +0 -3
- package/dist/components/__generated__/stickers/balance.js +0 -7
- package/dist/components/__generated__/stickers/butterfly-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/butterfly-animated.js +0 -7
- package/dist/components/__generated__/stickers/butterfly-snake-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/butterfly-snake-animated.js +0 -7
- package/dist/components/__generated__/stickers/butterfly-snake.d.ts +0 -3
- package/dist/components/__generated__/stickers/butterfly-snake.js +0 -7
- package/dist/components/__generated__/stickers/butterfly.d.ts +0 -3
- package/dist/components/__generated__/stickers/butterfly.js +0 -7
- package/dist/components/__generated__/stickers/catch-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/catch-animated.js +0 -7
- package/dist/components/__generated__/stickers/catch.d.ts +0 -3
- package/dist/components/__generated__/stickers/catch.js +0 -7
- package/dist/components/__generated__/stickers/clap-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/clap-animated.js +0 -7
- package/dist/components/__generated__/stickers/clap.d.ts +0 -3
- package/dist/components/__generated__/stickers/clap.js +0 -7
- package/dist/components/__generated__/stickers/coding-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/coding-animated.js +0 -7
- package/dist/components/__generated__/stickers/coding.d.ts +0 -3
- package/dist/components/__generated__/stickers/coding.js +0 -7
- package/dist/components/__generated__/stickers/cowboy-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/cowboy-animated.js +0 -7
- package/dist/components/__generated__/stickers/cowboy.d.ts +0 -3
- package/dist/components/__generated__/stickers/cowboy.js +0 -7
- package/dist/components/__generated__/stickers/dance-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/dance-animated.js +0 -7
- package/dist/components/__generated__/stickers/dance.d.ts +0 -3
- package/dist/components/__generated__/stickers/dance.js +0 -7
- package/dist/components/__generated__/stickers/detective-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/detective-animated.js +0 -7
- package/dist/components/__generated__/stickers/detective.d.ts +0 -3
- package/dist/components/__generated__/stickers/detective.js +0 -7
- package/dist/components/__generated__/stickers/disapprove-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/disapprove-animated.js +0 -7
- package/dist/components/__generated__/stickers/disapprove.d.ts +0 -3
- package/dist/components/__generated__/stickers/disapprove.js +0 -7
- package/dist/components/__generated__/stickers/distracted-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/distracted-animated.js +0 -7
- package/dist/components/__generated__/stickers/distracted.d.ts +0 -3
- package/dist/components/__generated__/stickers/distracted.js +0 -7
- package/dist/components/__generated__/stickers/dive-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/dive-animated.js +0 -7
- package/dist/components/__generated__/stickers/dive.d.ts +0 -3
- package/dist/components/__generated__/stickers/dive.js +0 -7
- package/dist/components/__generated__/stickers/eat-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/eat-animated.js +0 -7
- package/dist/components/__generated__/stickers/eat.d.ts +0 -3
- package/dist/components/__generated__/stickers/eat.js +0 -7
- package/dist/components/__generated__/stickers/facepalm-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/facepalm-animated.js +0 -7
- package/dist/components/__generated__/stickers/facepalm.d.ts +0 -3
- package/dist/components/__generated__/stickers/facepalm.js +0 -7
- package/dist/components/__generated__/stickers/failed-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/failed-animated.js +0 -7
- package/dist/components/__generated__/stickers/failed.d.ts +0 -3
- package/dist/components/__generated__/stickers/failed.js +0 -7
- package/dist/components/__generated__/stickers/found-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/found-animated.js +0 -7
- package/dist/components/__generated__/stickers/found.d.ts +0 -3
- package/dist/components/__generated__/stickers/found.js +0 -7
- package/dist/components/__generated__/stickers/grow-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/grow-animated.js +0 -7
- package/dist/components/__generated__/stickers/grow.d.ts +0 -3
- package/dist/components/__generated__/stickers/grow.js +0 -7
- package/dist/components/__generated__/stickers/handstand-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/handstand-animated.js +0 -7
- package/dist/components/__generated__/stickers/handstand.d.ts +0 -3
- package/dist/components/__generated__/stickers/handstand.js +0 -7
- package/dist/components/__generated__/stickers/heart-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/heart-animated.js +0 -7
- package/dist/components/__generated__/stickers/heart.d.ts +0 -3
- package/dist/components/__generated__/stickers/heart.js +0 -7
- package/dist/components/__generated__/stickers/hello-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/hello-animated.js +0 -7
- package/dist/components/__generated__/stickers/hello.d.ts +0 -3
- package/dist/components/__generated__/stickers/hello.js +0 -7
- package/dist/components/__generated__/stickers/idea-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/idea-animated.js +0 -7
- package/dist/components/__generated__/stickers/idea.d.ts +0 -3
- package/dist/components/__generated__/stickers/idea.js +0 -7
- package/dist/components/__generated__/stickers/index.d.ts +0 -99
- package/dist/components/__generated__/stickers/index.js +0 -198
- package/dist/components/__generated__/stickers/laugh-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/laugh-animated.js +0 -7
- package/dist/components/__generated__/stickers/laugh.d.ts +0 -3
- package/dist/components/__generated__/stickers/laugh.js +0 -7
- package/dist/components/__generated__/stickers/love-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/love-animated.js +0 -7
- package/dist/components/__generated__/stickers/love.d.ts +0 -3
- package/dist/components/__generated__/stickers/love.js +0 -7
- package/dist/components/__generated__/stickers/nap-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/nap-animated.js +0 -7
- package/dist/components/__generated__/stickers/nap.d.ts +0 -3
- package/dist/components/__generated__/stickers/nap.js +0 -7
- package/dist/components/__generated__/stickers/party-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/party-animated.js +0 -7
- package/dist/components/__generated__/stickers/party.d.ts +0 -3
- package/dist/components/__generated__/stickers/party.js +0 -7
- package/dist/components/__generated__/stickers/passed-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/passed-animated.js +0 -7
- package/dist/components/__generated__/stickers/passed.d.ts +0 -3
- package/dist/components/__generated__/stickers/passed.js +0 -7
- package/dist/components/__generated__/stickers/peekaboo-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/peekaboo-animated.js +0 -7
- package/dist/components/__generated__/stickers/peekaboo.d.ts +0 -3
- package/dist/components/__generated__/stickers/peekaboo.js +0 -7
- package/dist/components/__generated__/stickers/pizza-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/pizza-animated.js +0 -7
- package/dist/components/__generated__/stickers/pizza.d.ts +0 -3
- package/dist/components/__generated__/stickers/pizza.js +0 -7
- package/dist/components/__generated__/stickers/puzzle-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/puzzle-animated.js +0 -7
- package/dist/components/__generated__/stickers/puzzle.d.ts +0 -3
- package/dist/components/__generated__/stickers/puzzle.js +0 -7
- package/dist/components/__generated__/stickers/sad-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/sad-animated.js +0 -7
- package/dist/components/__generated__/stickers/sad.d.ts +0 -3
- package/dist/components/__generated__/stickers/sad.js +0 -7
- package/dist/components/__generated__/stickers/scared-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/scared-animated.js +0 -7
- package/dist/components/__generated__/stickers/scared.d.ts +0 -3
- package/dist/components/__generated__/stickers/scared.js +0 -7
- package/dist/components/__generated__/stickers/scroll-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/scroll-animated.js +0 -7
- package/dist/components/__generated__/stickers/scroll.d.ts +0 -3
- package/dist/components/__generated__/stickers/scroll.js +0 -7
- package/dist/components/__generated__/stickers/search-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/search-animated.js +0 -7
- package/dist/components/__generated__/stickers/search.d.ts +0 -3
- package/dist/components/__generated__/stickers/search.js +0 -7
- package/dist/components/__generated__/stickers/shield-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/shield-animated.js +0 -7
- package/dist/components/__generated__/stickers/shield.d.ts +0 -3
- package/dist/components/__generated__/stickers/shield.js +0 -7
- package/dist/components/__generated__/stickers/shocked-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/shocked-animated.js +0 -7
- package/dist/components/__generated__/stickers/shocked.d.ts +0 -3
- package/dist/components/__generated__/stickers/shocked.js +0 -7
- package/dist/components/__generated__/stickers/sleep-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/sleep-animated.js +0 -7
- package/dist/components/__generated__/stickers/sleep.d.ts +0 -3
- package/dist/components/__generated__/stickers/sleep.js +0 -7
- package/dist/components/__generated__/stickers/stressed-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/stressed-animated.js +0 -7
- package/dist/components/__generated__/stickers/stressed.d.ts +0 -3
- package/dist/components/__generated__/stickers/stressed.js +0 -7
- package/dist/components/__generated__/stickers/suspicious-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/suspicious-animated.js +0 -7
- package/dist/components/__generated__/stickers/suspicious.d.ts +0 -3
- package/dist/components/__generated__/stickers/suspicious.js +0 -7
- package/dist/components/__generated__/stickers/thanks-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/thanks-animated.js +0 -7
- package/dist/components/__generated__/stickers/thanks.d.ts +0 -3
- package/dist/components/__generated__/stickers/thanks.js +0 -7
- package/dist/components/__generated__/stickers/think-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/think-animated.js +0 -7
- package/dist/components/__generated__/stickers/think-of-you-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/think-of-you-animated.js +0 -7
- package/dist/components/__generated__/stickers/think-of-you.d.ts +0 -3
- package/dist/components/__generated__/stickers/think-of-you.js +0 -7
- package/dist/components/__generated__/stickers/think.d.ts +0 -3
- package/dist/components/__generated__/stickers/think.js +0 -7
- package/dist/components/__generated__/stickers/thumbs-up-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/thumbs-up-animated.js +0 -7
- package/dist/components/__generated__/stickers/thumbs-up.d.ts +0 -3
- package/dist/components/__generated__/stickers/thumbs-up.js +0 -7
- package/dist/components/__generated__/stickers/vacation-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/vacation-animated.js +0 -7
- package/dist/components/__generated__/stickers/vacation.d.ts +0 -3
- package/dist/components/__generated__/stickers/vacation.js +0 -7
- package/dist/components/__generated__/stickers/wait-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/wait-animated.js +0 -7
- package/dist/components/__generated__/stickers/wait.d.ts +0 -3
- package/dist/components/__generated__/stickers/wait.js +0 -7
- package/dist/components/__generated__/stickers/wink-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/wink-animated.js +0 -7
- package/dist/components/__generated__/stickers/wink.d.ts +0 -3
- package/dist/components/__generated__/stickers/wink.js +0 -7
- package/dist/components/__generated__/stickers/work-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/work-animated.js +0 -7
- package/dist/components/__generated__/stickers/work.d.ts +0 -3
- package/dist/components/__generated__/stickers/work.js +0 -7
- package/dist/components/__generated__/stickers/zen-animated.d.ts +0 -3
- package/dist/components/__generated__/stickers/zen-animated.js +0 -7
- package/dist/components/__generated__/stickers/zen.d.ts +0 -3
- package/dist/components/__generated__/stickers/zen.js +0 -7
- package/dist/elements/a-menu-group.css +0 -21
- package/dist/elements/a-menu-group.d.ts +0 -13
- package/dist/elements/a-menu-group.js +0 -15
- package/dist/elements/a-menu-item.css +0 -162
- package/dist/elements/a-menu-item.d.ts +0 -27
- package/dist/elements/a-menu-item.js +0 -29
- package/dist/elements/a-menu-separator.css +0 -15
- package/dist/elements/a-menu-separator.d.ts +0 -12
- package/dist/elements/a-menu-separator.js +0 -15
- package/dist/elements/a-menu.css +0 -34
- package/dist/elements/a-menu.d.ts +0 -120
- package/dist/elements/a-menu.js +0 -649
- package/dist/elements/a-sticker-animated.css +0 -9
- package/dist/elements/a-sticker-animated.d.ts +0 -39
- package/dist/elements/a-sticker-animated.js +0 -81
- package/dist/elements/a-sticker.css +0 -9
- package/dist/elements/a-sticker.d.ts +0 -19
- package/dist/elements/a-sticker.js +0 -32
- package/dist/generate-stickers.mjs +0 -293
package/dist/elements/a-menu.js
DELETED
|
@@ -1,649 +0,0 @@
|
|
|
1
|
-
import { HTMLElementBase } from "../anta_helpers";
|
|
2
|
-
import { AMenuItemElement } from "./a-menu-item";
|
|
3
|
-
import "./a-menu.css";
|
|
4
|
-
const MARGIN = 4;
|
|
5
|
-
const MIN_HEIGHT = 96;
|
|
6
|
-
const SUBMENU_OPEN_DELAY = 130;
|
|
7
|
-
const SUBMENU_CLOSE_DELAY = 130;
|
|
8
|
-
const TYPEAHEAD_RESET = 500;
|
|
9
|
-
const openStack = [];
|
|
10
|
-
let docBound = false;
|
|
11
|
-
let boundDoc = null;
|
|
12
|
-
let boundView = null;
|
|
13
|
-
function bindDocListeners(doc, view) {
|
|
14
|
-
if (docBound) return;
|
|
15
|
-
doc.addEventListener("pointerdown", onDocPointerDown, true);
|
|
16
|
-
doc.addEventListener("keydown", onDocKeyDown, true);
|
|
17
|
-
doc.addEventListener("contextmenu", onDocContextMenu, true);
|
|
18
|
-
view.addEventListener("scroll", onScroll, { capture: true, passive: true });
|
|
19
|
-
view.addEventListener("resize", onResize);
|
|
20
|
-
boundDoc = doc;
|
|
21
|
-
boundView = view;
|
|
22
|
-
docBound = true;
|
|
23
|
-
}
|
|
24
|
-
function unbindDocListeners() {
|
|
25
|
-
if (!docBound) return;
|
|
26
|
-
boundDoc?.removeEventListener("pointerdown", onDocPointerDown, true);
|
|
27
|
-
boundDoc?.removeEventListener("keydown", onDocKeyDown, true);
|
|
28
|
-
boundDoc?.removeEventListener("contextmenu", onDocContextMenu, true);
|
|
29
|
-
boundView?.removeEventListener("scroll", onScroll, { capture: true });
|
|
30
|
-
boundView?.removeEventListener("resize", onResize);
|
|
31
|
-
boundDoc = null;
|
|
32
|
-
boundView = null;
|
|
33
|
-
docBound = false;
|
|
34
|
-
}
|
|
35
|
-
function pathHitsMenus(e) {
|
|
36
|
-
const path = e.composedPath();
|
|
37
|
-
for (const m of openStack) {
|
|
38
|
-
if (path.includes(m.surface)) return true;
|
|
39
|
-
const anchor = m.triggerAnchor;
|
|
40
|
-
if (anchor && path.includes(anchor)) return true;
|
|
41
|
-
}
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
function onDocPointerDown(e) {
|
|
45
|
-
if (!openStack.length) return;
|
|
46
|
-
if (!pathHitsMenus(e)) dismiss(e);
|
|
47
|
-
}
|
|
48
|
-
function onDocContextMenu(e) {
|
|
49
|
-
if (!openStack.length) return;
|
|
50
|
-
if (!pathHitsMenus(e)) dismiss(e);
|
|
51
|
-
}
|
|
52
|
-
function onScroll(e) {
|
|
53
|
-
if (!openStack.length) return;
|
|
54
|
-
const t = e.target;
|
|
55
|
-
for (const m of openStack) if (m.surface.contains(t)) return;
|
|
56
|
-
dismiss(e);
|
|
57
|
-
}
|
|
58
|
-
function onResize() {
|
|
59
|
-
if (!openStack.length) return;
|
|
60
|
-
dismiss();
|
|
61
|
-
}
|
|
62
|
-
function onDocKeyDown(e) {
|
|
63
|
-
const menu = openStack[openStack.length - 1];
|
|
64
|
-
if (!menu) return;
|
|
65
|
-
menu.handleKey(e);
|
|
66
|
-
}
|
|
67
|
-
function dismiss(originEvent) {
|
|
68
|
-
openStack[0]?.requestClose(originEvent);
|
|
69
|
-
}
|
|
70
|
-
function closeAll() {
|
|
71
|
-
for (let i = openStack.length - 1; i >= 0; i--) {
|
|
72
|
-
const m = openStack[i];
|
|
73
|
-
if (m.isOpen) m.emitChange(false);
|
|
74
|
-
m._doHide();
|
|
75
|
-
}
|
|
76
|
-
openStack.length = 0;
|
|
77
|
-
unbindDocListeners();
|
|
78
|
-
}
|
|
79
|
-
const anchorToMenu = /* @__PURE__ */ new WeakMap();
|
|
80
|
-
function handleIntersection(entries) {
|
|
81
|
-
for (const entry of entries) {
|
|
82
|
-
const menu = anchorToMenu.get(entry.target);
|
|
83
|
-
if (!menu) continue;
|
|
84
|
-
if (!menu.listening && entry.isIntersecting) {
|
|
85
|
-
requestAnimationFrame(() => menu.setupListeners());
|
|
86
|
-
} else if (menu.listening && !entry.isIntersecting) {
|
|
87
|
-
requestAnimationFrame(() => {
|
|
88
|
-
menu.teardownListeners();
|
|
89
|
-
if (menu.isOpen) menu.close();
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
const lazyObserver = typeof IntersectionObserver !== "undefined" ? new IntersectionObserver(handleIntersection, { root: null, rootMargin: "0px", threshold: 0 }) : null;
|
|
95
|
-
class AMenuElement extends HTMLElementBase {
|
|
96
|
-
static observedAttributes = ["placement", "context", "coord", "offset", "hover", "state"];
|
|
97
|
-
/** Shadow-internal popover surface — the only thing we ever mutate. */
|
|
98
|
-
surface;
|
|
99
|
-
listening = false;
|
|
100
|
-
_shown = false;
|
|
101
|
-
teardown;
|
|
102
|
-
// Submenu hover-intent timers.
|
|
103
|
-
openTimer;
|
|
104
|
-
closeTimer;
|
|
105
|
-
// Typeahead state (root navigation).
|
|
106
|
-
typeBuffer = "";
|
|
107
|
-
typeTimer;
|
|
108
|
-
constructor() {
|
|
109
|
-
super();
|
|
110
|
-
const shadow = this.attachShadow({ mode: "open" });
|
|
111
|
-
const style = document.createElement("style");
|
|
112
|
-
style.textContent = `
|
|
113
|
-
:host { display: contents; }
|
|
114
|
-
|
|
115
|
-
/* The shadow root holds exactly one element \u2014 this surface div (with a
|
|
116
|
-
<slot> inside) \u2014 so a bare tag selector is unambiguous; no class
|
|
117
|
-
needed. Slotted light-DOM content isn't matched by shadow selectors. */
|
|
118
|
-
div {
|
|
119
|
-
position: fixed;
|
|
120
|
-
left: 0;
|
|
121
|
-
top: 0;
|
|
122
|
-
margin: 0;
|
|
123
|
-
box-sizing: border-box;
|
|
124
|
-
/* Do NOT set display here. Author styles beat the UA popover rule
|
|
125
|
-
(\`[popover]:not(:popover-open){display:none}\`) regardless of
|
|
126
|
-
specificity, so an unconditional \`display:flex\` would keep a CLOSED
|
|
127
|
-
popover laid out in the top layer \u2014 invisible (opacity 0) but still
|
|
128
|
-
hoverable/clickable. Set display only on the open state and let the
|
|
129
|
-
UA hide it when closed. */
|
|
130
|
-
flex-direction: column;
|
|
131
|
-
gap: 1px;
|
|
132
|
-
min-width: var(--menu-min-width, 88px);
|
|
133
|
-
max-width: calc(100vw - ${2 * MARGIN}px);
|
|
134
|
-
max-height: calc(100dvh - ${2 * MARGIN}px);
|
|
135
|
-
overflow-y: auto;
|
|
136
|
-
overscroll-behavior: contain;
|
|
137
|
-
scrollbar-width: thin;
|
|
138
|
-
padding: var(--menu-padding, 4px);
|
|
139
|
-
background: var(--menu-bg, Canvas);
|
|
140
|
-
color: var(--text-2, CanvasText);
|
|
141
|
-
border: var(--menu-border, 1px solid);
|
|
142
|
-
border-radius: var(--menu-radius, 8px);
|
|
143
|
-
box-shadow: var(--menu-shadow, 0 8px 24px rgba(0,0,0,0.2));
|
|
144
|
-
-webkit-backdrop-filter: var(--menu-backdrop-filter, blur(20px));
|
|
145
|
-
backdrop-filter: var(--menu-backdrop-filter, blur(20px));
|
|
146
|
-
outline: none;
|
|
147
|
-
}
|
|
148
|
-
/* Open state. Closed \u2192 the UA's \`[popover]:not(:popover-open){display:none}\`
|
|
149
|
-
governs (so a closed menu is truly gone \u2014 not interactive). A keyframe
|
|
150
|
-
enter-fade is used instead of a transition + \`allow-discrete\`: the
|
|
151
|
-
latter proved fragile here (it could leave the surface stuck at
|
|
152
|
-
display:flex / opacity 0 after close). The fade starts at opacity 0, so
|
|
153
|
-
the first paint (before position() sets the transform) is invisible. */
|
|
154
|
-
div:popover-open {
|
|
155
|
-
display: flex;
|
|
156
|
-
animation: a-menu-enter 80ms ease-out;
|
|
157
|
-
}
|
|
158
|
-
@keyframes a-menu-enter { from { opacity: 0; } }
|
|
159
|
-
`;
|
|
160
|
-
this.surface = document.createElement("div");
|
|
161
|
-
this.surface.setAttribute("popover", "manual");
|
|
162
|
-
this.surface.append(document.createElement("slot"));
|
|
163
|
-
this.surface.addEventListener("mouseenter", () => {
|
|
164
|
-
if (this.isSubmenu) this.cancelCloseTimer();
|
|
165
|
-
});
|
|
166
|
-
this.surface.addEventListener("mouseleave", () => {
|
|
167
|
-
if (this.isSubmenu && this.isHover) this.scheduleClose();
|
|
168
|
-
});
|
|
169
|
-
this.surface.addEventListener("click", this.onSurfaceClick);
|
|
170
|
-
shadow.append(style, this.surface);
|
|
171
|
-
}
|
|
172
|
-
connectedCallback() {
|
|
173
|
-
const anchor = this.triggerAnchor;
|
|
174
|
-
if (anchor) {
|
|
175
|
-
anchorToMenu.set(anchor, this);
|
|
176
|
-
lazyObserver?.observe(anchor);
|
|
177
|
-
}
|
|
178
|
-
if (this.hasAttribute("state")) requestAnimationFrame(() => this.syncState());
|
|
179
|
-
}
|
|
180
|
-
disconnectedCallback() {
|
|
181
|
-
this.hide();
|
|
182
|
-
this.teardownListeners();
|
|
183
|
-
this.cancelOpenTimer();
|
|
184
|
-
this.cancelCloseTimer();
|
|
185
|
-
const anchor = this.triggerAnchor;
|
|
186
|
-
if (anchor && anchorToMenu.get(anchor) === this) {
|
|
187
|
-
anchorToMenu.delete(anchor);
|
|
188
|
-
lazyObserver?.unobserve(anchor);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
attributeChangedCallback(name) {
|
|
192
|
-
if (name === "state") {
|
|
193
|
-
this.syncState();
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
if (this.listening) {
|
|
197
|
-
this.teardownListeners();
|
|
198
|
-
this.setupListeners();
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
/** Apply the controlled `state` attribute to actual visibility, silently.
|
|
202
|
-
* Absent → uncontrolled (no-op here; triggers manage it). */
|
|
203
|
-
syncState() {
|
|
204
|
-
if (!this.isConnected) return;
|
|
205
|
-
const v = this.getAttribute("state");
|
|
206
|
-
if (v === "opened" && !this._shown) this.show();
|
|
207
|
-
else if (v === "closed" && this._shown) this.hide();
|
|
208
|
-
}
|
|
209
|
-
/** Controlled iff the consumer is managing the `state` attribute. */
|
|
210
|
-
get isControlled() {
|
|
211
|
-
return this.hasAttribute("state");
|
|
212
|
-
}
|
|
213
|
-
/* --- realm-correct window / document (iframe playground safety) --- */
|
|
214
|
-
get view() {
|
|
215
|
-
return this.ownerDocument?.defaultView ?? window;
|
|
216
|
-
}
|
|
217
|
-
get doc() {
|
|
218
|
-
return this.ownerDocument ?? document;
|
|
219
|
-
}
|
|
220
|
-
/* --- config getters --- */
|
|
221
|
-
get isSubmenu() {
|
|
222
|
-
return this.hasAttribute("submenu");
|
|
223
|
-
}
|
|
224
|
-
get isContext() {
|
|
225
|
-
return this.hasAttribute("context");
|
|
226
|
-
}
|
|
227
|
-
get isCoord() {
|
|
228
|
-
return this.hasAttribute("coord");
|
|
229
|
-
}
|
|
230
|
-
get isHover() {
|
|
231
|
-
return this.hasAttribute("hover");
|
|
232
|
-
}
|
|
233
|
-
get offset() {
|
|
234
|
-
const n = parseInt(this.getAttribute("offset") ?? "", 10);
|
|
235
|
-
return Number.isFinite(n) ? n : MARGIN;
|
|
236
|
-
}
|
|
237
|
-
get placement() {
|
|
238
|
-
const p = this.getAttribute("placement");
|
|
239
|
-
if (p === "bottom-end" || p === "top-start" || p === "top-end") return p;
|
|
240
|
-
return "bottom-start";
|
|
241
|
-
}
|
|
242
|
-
/** Root menu: the previous element sibling is the trigger. Submenu: the
|
|
243
|
-
* enclosing menu item. One deterministic rule per case — no ambiguity. */
|
|
244
|
-
get triggerAnchor() {
|
|
245
|
-
if (this.isSubmenu) return this.closest("a-menu-item");
|
|
246
|
-
return this.previousElementSibling;
|
|
247
|
-
}
|
|
248
|
-
/** For a submenu: the menu that contains its anchor item. */
|
|
249
|
-
get ownerMenu() {
|
|
250
|
-
if (!this.isSubmenu) return null;
|
|
251
|
-
return this.triggerAnchor?.closest("a-menu") ?? null;
|
|
252
|
-
}
|
|
253
|
-
get isOpen() {
|
|
254
|
-
return this._shown;
|
|
255
|
-
}
|
|
256
|
-
/* --- focusable items belonging to THIS menu (not nested submenus) --- */
|
|
257
|
-
/** Skip elements that can't actually take focus — `display:none` (incl. a
|
|
258
|
-
* closed submenu's contents), `visibility:hidden`, `content-visibility`
|
|
259
|
-
* skipped — so navigation never lands on a hidden node (programmatic
|
|
260
|
-
* `.focus()` on one silently fails). `getClientRects` is the fallback where
|
|
261
|
-
* `checkVisibility` isn't available. */
|
|
262
|
-
isVisible(el) {
|
|
263
|
-
const check = el.checkVisibility;
|
|
264
|
-
if (typeof check === "function") {
|
|
265
|
-
return check.call(el, { visibilityProperty: true, contentVisibilityAuto: true });
|
|
266
|
-
}
|
|
267
|
-
return el.getClientRects().length > 0;
|
|
268
|
-
}
|
|
269
|
-
focusableItems() {
|
|
270
|
-
return Array.from(this.querySelectorAll("a-menu-item")).filter(
|
|
271
|
-
(it) => it.closest("a-menu") === this && !it.hasAttribute("disabled") && this.isVisible(it)
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
/** Every tabbable element belonging to THIS menu (items + nested controls
|
|
275
|
-
* like inputs / sliders / buttons), in DOM order, visible and enabled —
|
|
276
|
-
* used to trap Tab within the open menu. Submenu contents are excluded
|
|
277
|
-
* (their nearest `a-menu` is the submenu). */
|
|
278
|
-
focusables() {
|
|
279
|
-
const sel = 'a-menu-item, a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
280
|
-
return Array.from(this.querySelectorAll(sel)).filter(
|
|
281
|
-
(el) => el.closest("a-menu") === this && !el.hasAttribute("disabled") && this.isVisible(el)
|
|
282
|
-
);
|
|
283
|
-
}
|
|
284
|
-
focusFirstItem() {
|
|
285
|
-
this.focusableItems()[0]?.focus();
|
|
286
|
-
}
|
|
287
|
-
/* ============================ open / close ============================ */
|
|
288
|
-
/** Public imperative API. Routes through the same intent path as the
|
|
289
|
-
* triggers, so it emits `openchange` and respects controlled mode. */
|
|
290
|
-
open(opts) {
|
|
291
|
-
this.requestOpen(opts);
|
|
292
|
-
}
|
|
293
|
-
close(originEvent) {
|
|
294
|
-
this.requestClose(originEvent);
|
|
295
|
-
}
|
|
296
|
-
toggle(opts) {
|
|
297
|
-
if (this._shown) this.requestClose(opts?.originEvent);
|
|
298
|
-
else this.requestOpen(opts);
|
|
299
|
-
}
|
|
300
|
-
/** Dispatch the single `openchange` event (new state + old state). */
|
|
301
|
-
emitChange(next, opts) {
|
|
302
|
-
this.dispatchEvent(
|
|
303
|
-
new CustomEvent("openchange", {
|
|
304
|
-
detail: {
|
|
305
|
-
open: next,
|
|
306
|
-
previousState: this._shown ? "opened" : "closed",
|
|
307
|
-
coord: opts?.coord,
|
|
308
|
-
originEvent: opts?.originEvent
|
|
309
|
-
}
|
|
310
|
-
})
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
/** Intent to open (trigger / method / keyboard). Emits `openchange`; applies
|
|
314
|
-
* the visibility itself ONLY when uncontrolled — a controlled menu waits for
|
|
315
|
-
* the consumer to flip `state` (strict). */
|
|
316
|
-
requestOpen(opts) {
|
|
317
|
-
if (this._shown) {
|
|
318
|
-
this.show(opts?.coord, opts?.viaKeyboard, opts?.originEvent);
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
this.emitChange(true, opts);
|
|
322
|
-
if (!this.isControlled) this.show(opts?.coord, opts?.viaKeyboard, opts?.originEvent);
|
|
323
|
-
}
|
|
324
|
-
/** Intent to close. Emits `openchange`; hides itself only when uncontrolled. */
|
|
325
|
-
requestClose(originEvent) {
|
|
326
|
-
if (!this._shown) return;
|
|
327
|
-
this.emitChange(false, { originEvent });
|
|
328
|
-
if (!this.isControlled) this.hide();
|
|
329
|
-
}
|
|
330
|
-
/** Apply OPEN to the DOM (no event) — used by uncontrolled intent and by the
|
|
331
|
-
* controlled `state` sync. */
|
|
332
|
-
show(coord, viaKeyboard = false, _originEvent) {
|
|
333
|
-
if (this.isSubmenu) {
|
|
334
|
-
const parent = this.ownerMenu;
|
|
335
|
-
if (parent) {
|
|
336
|
-
const pidx = openStack.indexOf(parent);
|
|
337
|
-
if (pidx !== -1) {
|
|
338
|
-
for (let i = openStack.length - 1; i > pidx; i--) openStack[i]._doHide();
|
|
339
|
-
openStack.length = pidx + 1;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
} else {
|
|
343
|
-
closeAll();
|
|
344
|
-
}
|
|
345
|
-
if (openStack.includes(this)) {
|
|
346
|
-
this.position(coord);
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
const wasEmpty = openStack.length === 0;
|
|
350
|
-
this._doShow(coord, !wasEmpty);
|
|
351
|
-
openStack.push(this);
|
|
352
|
-
if (wasEmpty) bindDocListeners(this.doc, this.view);
|
|
353
|
-
if (viaKeyboard) this.focusFirstItem();
|
|
354
|
-
}
|
|
355
|
-
/** Apply CLOSE to the DOM (no event). Closes this menu and everything stacked
|
|
356
|
-
* above it (its submenus). */
|
|
357
|
-
hide() {
|
|
358
|
-
const idx = openStack.indexOf(this);
|
|
359
|
-
if (idx === -1) {
|
|
360
|
-
if (this._shown) this._doHide();
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
for (let i = openStack.length - 1; i >= idx; i--) openStack[i]._doHide();
|
|
364
|
-
openStack.length = idx;
|
|
365
|
-
if (openStack.length === 0) unbindDocListeners();
|
|
366
|
-
}
|
|
367
|
-
/** Shadow-only show: open the popover and position it. `instant` skips the
|
|
368
|
-
* enter-fade and positions synchronously, so a menu opening over an
|
|
369
|
-
* already-visible one snaps in without a blink. */
|
|
370
|
-
_doShow(coord, instant = false) {
|
|
371
|
-
if (this.surface.isConnected && !this._shown) this.surface.showPopover();
|
|
372
|
-
this._shown = true;
|
|
373
|
-
this.surface.style.animation = instant ? "none" : "";
|
|
374
|
-
this.position(coord, instant);
|
|
375
|
-
}
|
|
376
|
-
/** Shadow-only hide. */
|
|
377
|
-
_doHide() {
|
|
378
|
-
if (this.surface.isConnected && this._shown) this.surface.hidePopover();
|
|
379
|
-
this._shown = false;
|
|
380
|
-
this.cancelOpenTimer();
|
|
381
|
-
this.cancelCloseTimer();
|
|
382
|
-
}
|
|
383
|
-
/* ============================ positioning ============================ */
|
|
384
|
-
position(coord, sync = false) {
|
|
385
|
-
const run = () => {
|
|
386
|
-
if (!this._shown) return;
|
|
387
|
-
const view = this.view;
|
|
388
|
-
const vw = view.innerWidth;
|
|
389
|
-
const vh = view.innerHeight;
|
|
390
|
-
const surface = this.surface;
|
|
391
|
-
let left = MARGIN;
|
|
392
|
-
let top = MARGIN;
|
|
393
|
-
if (coord) {
|
|
394
|
-
surface.style.maxHeight = `${Math.max(MIN_HEIGHT, vh - 2 * MARGIN)}px`;
|
|
395
|
-
const box = surface.getBoundingClientRect();
|
|
396
|
-
left = coord[0];
|
|
397
|
-
if (left + box.width > vw - MARGIN) left = vw - box.width - MARGIN;
|
|
398
|
-
left = Math.max(MARGIN, left);
|
|
399
|
-
top = coord[1];
|
|
400
|
-
if (top + box.height > vh - MARGIN) top = top - box.height;
|
|
401
|
-
top = Math.max(MARGIN, top);
|
|
402
|
-
} else if (this.isSubmenu) {
|
|
403
|
-
const it = this.triggerAnchor?.getBoundingClientRect();
|
|
404
|
-
if (!it) return;
|
|
405
|
-
surface.style.maxHeight = `${Math.max(MIN_HEIGHT, vh - 2 * MARGIN)}px`;
|
|
406
|
-
const box = surface.getBoundingClientRect();
|
|
407
|
-
left = it.right + this.offset;
|
|
408
|
-
if (left + box.width > vw - MARGIN) {
|
|
409
|
-
left = it.left - box.width - this.offset;
|
|
410
|
-
}
|
|
411
|
-
left = Math.max(MARGIN, left);
|
|
412
|
-
top = it.top - MARGIN;
|
|
413
|
-
if (top + box.height > vh - MARGIN) top = vh - box.height - MARGIN;
|
|
414
|
-
top = Math.max(MARGIN, top);
|
|
415
|
-
} else {
|
|
416
|
-
const a = this.triggerAnchor?.getBoundingClientRect();
|
|
417
|
-
if (!a) return;
|
|
418
|
-
const p = this.placement;
|
|
419
|
-
const spaceBelow = vh - a.bottom - 2 * MARGIN;
|
|
420
|
-
const spaceAbove = a.top - 2 * MARGIN;
|
|
421
|
-
let onTop = p.startsWith("top");
|
|
422
|
-
const natural = surface.scrollHeight;
|
|
423
|
-
if (onTop && spaceAbove < natural && spaceBelow > spaceAbove) onTop = false;
|
|
424
|
-
else if (!onTop && spaceBelow < natural && spaceAbove > spaceBelow) onTop = true;
|
|
425
|
-
const space = onTop ? spaceAbove : spaceBelow;
|
|
426
|
-
surface.style.maxHeight = `${Math.max(MIN_HEIGHT, Math.floor(space))}px`;
|
|
427
|
-
const box = surface.getBoundingClientRect();
|
|
428
|
-
left = p.endsWith("end") ? a.right - box.width : a.left;
|
|
429
|
-
if (left + box.width > vw - MARGIN) left = vw - box.width - MARGIN;
|
|
430
|
-
left = Math.max(MARGIN, left);
|
|
431
|
-
top = onTop ? a.top - box.height - this.offset : a.bottom + this.offset;
|
|
432
|
-
top = Math.max(MARGIN, top);
|
|
433
|
-
}
|
|
434
|
-
surface.style.transform = `translate(${Math.round(left)}px, ${Math.round(top)}px)`;
|
|
435
|
-
};
|
|
436
|
-
if (sync) run();
|
|
437
|
-
else requestAnimationFrame(run);
|
|
438
|
-
}
|
|
439
|
-
/* ====================== click / close contract ====================== */
|
|
440
|
-
/**
|
|
441
|
-
* Fully declarative close contract — decided synchronously from the DOM, so
|
|
442
|
-
* it never depends on the consumer's click handler (which in a worker-thread
|
|
443
|
-
* runtime can't `preventDefault` on the UI thread). The menu never
|
|
444
|
-
* stops/prevents the click, so the consumer's selection handler always runs.
|
|
445
|
-
*
|
|
446
|
-
* Walk the click's composedPath outward to the surface; the NEAREST marker
|
|
447
|
-
* wins:
|
|
448
|
-
* - `data-menu-open` → keep the menu open (a Done button can still close
|
|
449
|
-
* from inside such a region — it's hit first).
|
|
450
|
-
* - `a-menu-item` (a choice) or `data-menu-close` → close the menu.
|
|
451
|
-
* - nothing → keep open (plain custom content doesn't dismiss).
|
|
452
|
-
*/
|
|
453
|
-
onSurfaceClick = (e) => {
|
|
454
|
-
for (const node of e.composedPath()) {
|
|
455
|
-
if (node === this.surface) break;
|
|
456
|
-
if (!(node instanceof Element)) continue;
|
|
457
|
-
if (node.hasAttribute("data-menu-open")) return;
|
|
458
|
-
if (node instanceof AMenuItemElement) {
|
|
459
|
-
if (node.hasAttribute("disabled")) {
|
|
460
|
-
e.preventDefault();
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
if (node.hasAttribute("submenu")) return;
|
|
464
|
-
const role = node.getAttribute("role");
|
|
465
|
-
if (role === "menuitemcheckbox" || role === "menuitemradio") return;
|
|
466
|
-
return this.closeSystem(e);
|
|
467
|
-
}
|
|
468
|
-
if (node.hasAttribute("data-menu-close")) return this.closeSystem(e);
|
|
469
|
-
}
|
|
470
|
-
};
|
|
471
|
-
/** Close the whole open menu system from the root down. */
|
|
472
|
-
closeSystem(e) {
|
|
473
|
-
const root = openStack[0] ?? this;
|
|
474
|
-
root.requestClose(e);
|
|
475
|
-
}
|
|
476
|
-
/* ============================ keyboard ============================ */
|
|
477
|
-
/** Called by the coordinator on the topmost open menu. Handles navigation;
|
|
478
|
-
* Enter / Space activation is handled by a-menu-item's own global keydown
|
|
479
|
-
* (which synthesizes a click → routed through onSurfaceClick). */
|
|
480
|
-
handleKey(e) {
|
|
481
|
-
const active = this.doc.activeElement;
|
|
482
|
-
if (e.key === "Escape") {
|
|
483
|
-
e.preventDefault();
|
|
484
|
-
e.stopPropagation();
|
|
485
|
-
const anchor = this.triggerAnchor;
|
|
486
|
-
this.requestClose(e);
|
|
487
|
-
anchor?.focus();
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
if (e.key === "Tab") {
|
|
491
|
-
const f = this.focusables();
|
|
492
|
-
if (!f.length) return;
|
|
493
|
-
e.preventDefault();
|
|
494
|
-
const i = active ? f.indexOf(active) : -1;
|
|
495
|
-
const next = e.shiftKey ? i <= 0 ? f.length - 1 : i - 1 : i === -1 || i === f.length - 1 ? 0 : i + 1;
|
|
496
|
-
f[next]?.focus();
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
const within = active?.closest("a-menu") === this;
|
|
500
|
-
if (within && !(active instanceof AMenuItemElement)) return;
|
|
501
|
-
const items = this.focusableItems();
|
|
502
|
-
const idx = active ? items.indexOf(active) : -1;
|
|
503
|
-
switch (e.key) {
|
|
504
|
-
case "ArrowDown":
|
|
505
|
-
e.preventDefault();
|
|
506
|
-
items[idx < 0 ? 0 : (idx + 1) % items.length]?.focus();
|
|
507
|
-
break;
|
|
508
|
-
case "ArrowUp":
|
|
509
|
-
e.preventDefault();
|
|
510
|
-
items[idx <= 0 ? items.length - 1 : idx - 1]?.focus();
|
|
511
|
-
break;
|
|
512
|
-
case "Home":
|
|
513
|
-
e.preventDefault();
|
|
514
|
-
items[0]?.focus();
|
|
515
|
-
break;
|
|
516
|
-
case "End":
|
|
517
|
-
e.preventDefault();
|
|
518
|
-
items[items.length - 1]?.focus();
|
|
519
|
-
break;
|
|
520
|
-
case "ArrowRight": {
|
|
521
|
-
const sub = this.submenuOf(active);
|
|
522
|
-
if (sub) {
|
|
523
|
-
e.preventDefault();
|
|
524
|
-
sub.requestOpen({ viaKeyboard: true });
|
|
525
|
-
}
|
|
526
|
-
break;
|
|
527
|
-
}
|
|
528
|
-
case "ArrowLeft":
|
|
529
|
-
if (this.isSubmenu) {
|
|
530
|
-
e.preventDefault();
|
|
531
|
-
const anchorItem = this.triggerAnchor;
|
|
532
|
-
this.requestClose(e);
|
|
533
|
-
anchorItem?.focus();
|
|
534
|
-
}
|
|
535
|
-
break;
|
|
536
|
-
default:
|
|
537
|
-
if (e.key.length === 1 && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
|
538
|
-
this.typeahead(e.key, items);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
submenuOf(item) {
|
|
543
|
-
if (!item || !(item instanceof AMenuItemElement) || !item.hasAttribute("submenu")) return null;
|
|
544
|
-
return item.querySelector("a-menu");
|
|
545
|
-
}
|
|
546
|
-
typeahead(ch, items) {
|
|
547
|
-
this.typeBuffer += ch.toLowerCase();
|
|
548
|
-
clearTimeout(this.typeTimer);
|
|
549
|
-
this.typeTimer = setTimeout(() => this.typeBuffer = "", TYPEAHEAD_RESET);
|
|
550
|
-
const match = items.find((it) => (it.textContent ?? "").trim().toLowerCase().startsWith(this.typeBuffer));
|
|
551
|
-
match?.focus();
|
|
552
|
-
}
|
|
553
|
-
/* ====================== trigger listener wiring ====================== */
|
|
554
|
-
setupListeners() {
|
|
555
|
-
if (this.listening) return;
|
|
556
|
-
const anchor = this.triggerAnchor;
|
|
557
|
-
if (!anchor) {
|
|
558
|
-
this.listening = true;
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
if (this.isSubmenu) {
|
|
562
|
-
const onClick = (e) => this.toggle({ originEvent: e });
|
|
563
|
-
anchor.addEventListener("click", onClick);
|
|
564
|
-
let onEnter;
|
|
565
|
-
let onLeave;
|
|
566
|
-
if (this.isHover) {
|
|
567
|
-
onEnter = () => this.scheduleOpen();
|
|
568
|
-
onLeave = () => this.scheduleClose();
|
|
569
|
-
anchor.addEventListener("mouseenter", onEnter);
|
|
570
|
-
anchor.addEventListener("mouseleave", onLeave);
|
|
571
|
-
}
|
|
572
|
-
this.teardown = () => {
|
|
573
|
-
anchor.removeEventListener("click", onClick);
|
|
574
|
-
if (onEnter) anchor.removeEventListener("mouseenter", onEnter);
|
|
575
|
-
if (onLeave) anchor.removeEventListener("mouseleave", onLeave);
|
|
576
|
-
this.listening = false;
|
|
577
|
-
};
|
|
578
|
-
} else if (this.isContext) {
|
|
579
|
-
const onContext = (e) => {
|
|
580
|
-
e.preventDefault();
|
|
581
|
-
this.requestOpen({ coord: [e.clientX, e.clientY], originEvent: e });
|
|
582
|
-
};
|
|
583
|
-
anchor.addEventListener("contextmenu", onContext);
|
|
584
|
-
this.teardown = () => {
|
|
585
|
-
anchor.removeEventListener("contextmenu", onContext);
|
|
586
|
-
this.listening = false;
|
|
587
|
-
};
|
|
588
|
-
} else {
|
|
589
|
-
const onClick = (e) => {
|
|
590
|
-
const viaKeyboard = e.detail === 0;
|
|
591
|
-
const coord = this.isCoord ? [e.clientX, e.clientY] : void 0;
|
|
592
|
-
if (this._shown) this.requestClose(e);
|
|
593
|
-
else this.requestOpen({ coord, viaKeyboard, originEvent: e });
|
|
594
|
-
};
|
|
595
|
-
anchor.addEventListener("click", onClick);
|
|
596
|
-
this.teardown = () => {
|
|
597
|
-
anchor.removeEventListener("click", onClick);
|
|
598
|
-
this.listening = false;
|
|
599
|
-
};
|
|
600
|
-
}
|
|
601
|
-
this.listening = true;
|
|
602
|
-
}
|
|
603
|
-
teardownListeners() {
|
|
604
|
-
this.teardown?.();
|
|
605
|
-
this.teardown = void 0;
|
|
606
|
-
}
|
|
607
|
-
/* --- submenu hover-intent timers --- */
|
|
608
|
-
scheduleOpen() {
|
|
609
|
-
this.cancelCloseTimer();
|
|
610
|
-
if (this._shown) return;
|
|
611
|
-
this.cancelOpenTimer();
|
|
612
|
-
this.openTimer = setTimeout(() => {
|
|
613
|
-
this.openTimer = void 0;
|
|
614
|
-
this.requestOpen();
|
|
615
|
-
}, SUBMENU_OPEN_DELAY);
|
|
616
|
-
}
|
|
617
|
-
scheduleClose() {
|
|
618
|
-
this.cancelOpenTimer();
|
|
619
|
-
if (!this._shown) return;
|
|
620
|
-
this.cancelCloseTimer();
|
|
621
|
-
this.closeTimer = setTimeout(() => {
|
|
622
|
-
this.closeTimer = void 0;
|
|
623
|
-
this.requestClose();
|
|
624
|
-
}, SUBMENU_CLOSE_DELAY);
|
|
625
|
-
}
|
|
626
|
-
cancelOpenTimer() {
|
|
627
|
-
if (this.openTimer !== void 0) {
|
|
628
|
-
clearTimeout(this.openTimer);
|
|
629
|
-
this.openTimer = void 0;
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
cancelCloseTimer() {
|
|
633
|
-
if (this.closeTimer !== void 0) {
|
|
634
|
-
clearTimeout(this.closeTimer);
|
|
635
|
-
this.closeTimer = void 0;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
function register_a_menu() {
|
|
640
|
-
if (typeof customElements === "undefined") return;
|
|
641
|
-
if (!customElements.get("a-menu")) {
|
|
642
|
-
customElements.define("a-menu", AMenuElement);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
register_a_menu();
|
|
646
|
-
export {
|
|
647
|
-
AMenuElement,
|
|
648
|
-
register_a_menu
|
|
649
|
-
};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { type AnimationItem } from 'lottie-web';
|
|
2
|
-
import { HTMLElementBase } from '../anta_helpers';
|
|
3
|
-
import './a-sticker-animated.css';
|
|
4
|
-
/**
|
|
5
|
-
* `<a-sticker-animated>` — Lottie-driven sticker carrier.
|
|
6
|
-
*
|
|
7
|
-
* Receives the Lottie payload as the `animation` attribute (a JSON
|
|
8
|
-
* string). On change, parses the JSON once and instantiates a
|
|
9
|
-
* `lottie-web` player against a shadow-DOM container. The renderer is
|
|
10
|
-
* SVG — `lottie-web` creates real `<svg>` elements in the shadow root
|
|
11
|
-
* and updates path / transform attributes each frame. Rasterisation
|
|
12
|
-
* goes through the browser's native SVG renderer (Skia / Core
|
|
13
|
-
* Graphics), giving the same crispness as static `<svg>` content.
|
|
14
|
-
*
|
|
15
|
-
* Observed attributes:
|
|
16
|
-
* - `animation` — JSON string for `lottie-web`. Reset to null/missing
|
|
17
|
-
* tears the player down.
|
|
18
|
-
* - `paused` — present: freeze at current frame. Numeric value
|
|
19
|
-
* (seconds): seek to that time, then freeze. Absent: play.
|
|
20
|
-
*
|
|
21
|
-
* Sizing comes from external CSS reading `--sticker-size` (set by the
|
|
22
|
-
* JSX wrapper or the consumer).
|
|
23
|
-
*
|
|
24
|
-
* The static counterpart is `<a-sticker>`.
|
|
25
|
-
*/
|
|
26
|
-
export declare class AStickerAnimatedElement extends HTMLElementBase {
|
|
27
|
-
static observedAttributes: string[];
|
|
28
|
-
container: HTMLDivElement;
|
|
29
|
-
player: AnimationItem | null;
|
|
30
|
-
_animation: Record<string, unknown> | null;
|
|
31
|
-
constructor();
|
|
32
|
-
connectedCallback(): void;
|
|
33
|
-
disconnectedCallback(): void;
|
|
34
|
-
attributeChangedCallback(name: string): void;
|
|
35
|
-
rebuild(): void;
|
|
36
|
-
applyPaused(): void;
|
|
37
|
-
teardown(): void;
|
|
38
|
-
}
|
|
39
|
-
export declare function register_a_sticker_animated(): void;
|