@antadesign/anta 0.1.1-dev.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/components/Button.js +4 -3
- package/dist/components/Menu.d.ts +61 -0
- package/dist/components/Menu.js +34 -0
- package/dist/components/MenuGroup.d.ts +24 -0
- package/dist/components/MenuGroup.js +19 -0
- package/dist/components/MenuItem.d.ts +49 -0
- package/dist/components/MenuItem.js +40 -0
- package/dist/components/MenuSeparator.d.ts +14 -0
- package/dist/components/MenuSeparator.js +7 -0
- package/dist/components/Tag.d.ts +55 -0
- package/dist/components/Tag.js +40 -0
- package/dist/components/Text.d.ts +4 -2
- package/dist/components/Tooltip.d.ts +57 -0
- package/dist/components/Tooltip.js +26 -0
- package/dist/elements/a-button.css +31 -8
- package/dist/elements/a-button.d.ts +1 -0
- package/dist/elements/a-button.js +2 -0
- package/dist/elements/a-icon.d.ts +2 -0
- package/dist/elements/a-icon.js +3 -0
- package/dist/elements/a-icon.shapes.css +4 -0
- package/dist/elements/a-icon.shapes.d.ts +2 -1
- package/dist/elements/a-icon.shapes.js +3 -1
- package/dist/elements/a-menu-group.css +21 -0
- package/dist/elements/a-menu-group.d.ts +13 -0
- package/dist/elements/a-menu-group.js +15 -0
- package/dist/elements/a-menu-item.css +162 -0
- package/dist/elements/a-menu-item.d.ts +27 -0
- package/dist/elements/a-menu-item.js +29 -0
- package/dist/elements/a-menu-separator.css +15 -0
- package/dist/elements/a-menu-separator.d.ts +12 -0
- package/dist/elements/a-menu-separator.js +15 -0
- package/dist/elements/a-menu.css +34 -0
- package/dist/elements/a-menu.d.ts +120 -0
- package/dist/elements/a-menu.js +649 -0
- package/dist/elements/a-progress.d.ts +1 -0
- package/dist/elements/a-progress.js +2 -0
- package/dist/elements/a-sticker-animated.d.ts +1 -0
- package/dist/elements/a-sticker-animated.js +2 -0
- package/dist/elements/a-sticker.d.ts +1 -0
- package/dist/elements/a-sticker.js +2 -0
- package/dist/elements/a-tag.css +196 -0
- package/dist/elements/a-text.css +17 -13
- package/dist/elements/a-text.d.ts +1 -0
- package/dist/elements/a-text.js +2 -0
- package/dist/elements/a-tooltip.css +62 -0
- package/dist/elements/a-tooltip.d.ts +68 -0
- package/dist/elements/a-tooltip.js +488 -0
- package/dist/elements/index.d.ts +18 -10
- package/dist/elements/index.js +12 -35
- package/dist/general_types.d.ts +40 -41
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/jsx-runtime.d.ts +7 -5
- package/dist/reset.css +14 -5
- package/package.json +13 -14
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { HTMLElementBase } from "../anta_helpers";
|
|
2
|
+
import { debounce } from "es-toolkit";
|
|
3
|
+
import "./a-tooltip.css";
|
|
4
|
+
const MARGIN = 4;
|
|
5
|
+
const CURSOR_SIZE = 16;
|
|
6
|
+
const PADDING_X = 8;
|
|
7
|
+
const DEFAULT_DELAY = 250;
|
|
8
|
+
const FADE_MS = 150;
|
|
9
|
+
const GRACE_MS = 300;
|
|
10
|
+
const CLOSE_DELAY = 120;
|
|
11
|
+
const ENTER_TOUCH_DELAY = 500;
|
|
12
|
+
const LEAVE_TOUCH_DELAY = 1500;
|
|
13
|
+
const TOUCH_SLOP = 10;
|
|
14
|
+
let currentOpen = null;
|
|
15
|
+
let graceTimer;
|
|
16
|
+
function graceActive() {
|
|
17
|
+
return graceTimer !== void 0;
|
|
18
|
+
}
|
|
19
|
+
function isHot() {
|
|
20
|
+
return currentOpen !== null || graceActive();
|
|
21
|
+
}
|
|
22
|
+
function clearGrace() {
|
|
23
|
+
if (graceTimer !== void 0) {
|
|
24
|
+
clearTimeout(graceTimer);
|
|
25
|
+
graceTimer = void 0;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function claimOpen(el) {
|
|
29
|
+
if (currentOpen && currentOpen !== el) currentOpen.hide();
|
|
30
|
+
currentOpen = el;
|
|
31
|
+
clearGrace();
|
|
32
|
+
}
|
|
33
|
+
function releaseOpen(el) {
|
|
34
|
+
if (currentOpen !== el) return;
|
|
35
|
+
currentOpen = null;
|
|
36
|
+
clearGrace();
|
|
37
|
+
graceTimer = setTimeout(() => {
|
|
38
|
+
graceTimer = void 0;
|
|
39
|
+
}, GRACE_MS);
|
|
40
|
+
}
|
|
41
|
+
const anchorToTooltip = /* @__PURE__ */ new WeakMap();
|
|
42
|
+
function handleIntersection(entries) {
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
const tooltip = anchorToTooltip.get(entry.target);
|
|
45
|
+
if (!tooltip) continue;
|
|
46
|
+
if (!tooltip.listening && entry.isIntersecting) {
|
|
47
|
+
requestAnimationFrame(() => tooltip.setupListeners());
|
|
48
|
+
} else if (tooltip.listening && !entry.isIntersecting) {
|
|
49
|
+
requestAnimationFrame(() => tooltip.teardownListeners());
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const lazyObserver = typeof IntersectionObserver !== "undefined" ? new IntersectionObserver(handleIntersection, { root: null, rootMargin: "0px", threshold: 0 }) : null;
|
|
54
|
+
class ATooltipElement extends HTMLElementBase {
|
|
55
|
+
// Observe `delay` so changing it at runtime — e.g. the docs playground
|
|
56
|
+
// patches the attribute on the live element — rebuilds the show debounce
|
|
57
|
+
// with the new value instead of keeping the one captured at setup.
|
|
58
|
+
static observedAttributes = ["delay"];
|
|
59
|
+
/** Shadow-internal popover surface — the only thing we ever mutate. */
|
|
60
|
+
container;
|
|
61
|
+
anchor = null;
|
|
62
|
+
listening = false;
|
|
63
|
+
shown = false;
|
|
64
|
+
/** True while the current open was triggered by a touch long-press. Such a
|
|
65
|
+
* bubble is pinned (never cursor-follows) and biases above the anchor so the
|
|
66
|
+
* fingertip doesn't cover it. */
|
|
67
|
+
touchOpen = false;
|
|
68
|
+
lastMouse;
|
|
69
|
+
debouncedShow;
|
|
70
|
+
teardown;
|
|
71
|
+
closeTimer;
|
|
72
|
+
fading = false;
|
|
73
|
+
fadeTimer;
|
|
74
|
+
docMoveBound = false;
|
|
75
|
+
constructor() {
|
|
76
|
+
super();
|
|
77
|
+
const shadow = this.attachShadow({ mode: "open" });
|
|
78
|
+
const style = document.createElement("style");
|
|
79
|
+
style.textContent = `
|
|
80
|
+
:host { display: contents; }
|
|
81
|
+
|
|
82
|
+
.container {
|
|
83
|
+
--_dur: ${FADE_MS}ms;
|
|
84
|
+
|
|
85
|
+
position: fixed;
|
|
86
|
+
left: 0;
|
|
87
|
+
top: 0;
|
|
88
|
+
margin: 0;
|
|
89
|
+
box-sizing: border-box;
|
|
90
|
+
width: fit-content;
|
|
91
|
+
max-width: var(--tooltip-max-width, min(calc(100vw - 20px), 80ch));
|
|
92
|
+
max-height: calc(100vh - 20px);
|
|
93
|
+
overflow: clip;
|
|
94
|
+
pointer-events: none;
|
|
95
|
+
text-align: left;
|
|
96
|
+
|
|
97
|
+
background: var(--tooltip-bg, Canvas);
|
|
98
|
+
color: var(--text-3, CanvasText);
|
|
99
|
+
box-shadow: var(--tooltip-shadow, 0 1px 8px rgba(0, 0, 0, 0.2));
|
|
100
|
+
-webkit-backdrop-filter: var(--tooltip-backdrop-filter, blur(8px));
|
|
101
|
+
backdrop-filter: var(--tooltip-backdrop-filter, blur(8px));
|
|
102
|
+
padding: 5px 8px;
|
|
103
|
+
border: var(--tooltip-border, none);
|
|
104
|
+
border-radius: var(--tooltip-radius, 3px);
|
|
105
|
+
outline: none;
|
|
106
|
+
|
|
107
|
+
/* The bubble establishes its own text baseline so inheritable text
|
|
108
|
+
properties from the anchor (e.g. a Button's condensed "wdth" 88
|
|
109
|
+
axis, its 0.05ch letter-spacing, an uppercase transform, a custom
|
|
110
|
+
font) don't bleed into the slotted content. The content is slotted
|
|
111
|
+
light DOM, so it inherits these *from this container* \u2014 making this
|
|
112
|
+
the single choke point. Values mirror Anta's body text. Consumers
|
|
113
|
+
still customise a single tooltip by styling their own content
|
|
114
|
+
element directly (a class on the content overrides what it inherits
|
|
115
|
+
\u2014 see the Tooltip docs). */
|
|
116
|
+
font-family: var(--sans-serif, system-ui, sans-serif);
|
|
117
|
+
font-size: 14px;
|
|
118
|
+
font-weight: 400;
|
|
119
|
+
font-style: normal;
|
|
120
|
+
font-stretch: normal;
|
|
121
|
+
font-variation-settings: "wdth" 100, "slnt" 0, "ital" 0;
|
|
122
|
+
line-height: 1.5;
|
|
123
|
+
letter-spacing: 0.02ch;
|
|
124
|
+
word-spacing: normal;
|
|
125
|
+
text-transform: none;
|
|
126
|
+
white-space: break-spaces;
|
|
127
|
+
word-break: break-word;
|
|
128
|
+
overflow-wrap: break-word;
|
|
129
|
+
|
|
130
|
+
/* Clean enter/exit fade. allow-discrete keeps the bubble rendered
|
|
131
|
+
through its fade-out after hidePopover(), and @starting-style
|
|
132
|
+
gives every open a from-opacity:0 \u2014 so the first paint at a
|
|
133
|
+
not-yet-computed transform is invisible (no flash at a stale
|
|
134
|
+
spot), and re-appearing is always clean. */
|
|
135
|
+
opacity: 0;
|
|
136
|
+
transition:
|
|
137
|
+
opacity var(--_dur) ease,
|
|
138
|
+
overlay var(--_dur) ease allow-discrete,
|
|
139
|
+
display var(--_dur) ease allow-discrete;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.container:popover-open { opacity: 1; }
|
|
143
|
+
|
|
144
|
+
@starting-style {
|
|
145
|
+
.container:popover-open { opacity: 0; }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* Interactive tooltips accept pointer events so their content (links,
|
|
149
|
+
buttons) is clickable; the default click-through bubble does not. */
|
|
150
|
+
:host([interactive]) .container { pointer-events: auto; }
|
|
151
|
+
`;
|
|
152
|
+
this.container = document.createElement("div");
|
|
153
|
+
this.container.className = "container";
|
|
154
|
+
this.container.setAttribute("popover", "manual");
|
|
155
|
+
this.container.setAttribute("role", "tooltip");
|
|
156
|
+
this.container.append(document.createElement("slot"));
|
|
157
|
+
this.container.addEventListener("mouseenter", () => {
|
|
158
|
+
if (this.isInteractive) this.cancelHide();
|
|
159
|
+
});
|
|
160
|
+
this.container.addEventListener("mouseleave", () => {
|
|
161
|
+
if (this.isInteractive && this.shown) this.scheduleHide();
|
|
162
|
+
});
|
|
163
|
+
shadow.append(style, this.container);
|
|
164
|
+
}
|
|
165
|
+
connectedCallback() {
|
|
166
|
+
const parent = this.parentElement;
|
|
167
|
+
if (!parent) return;
|
|
168
|
+
this.anchor = parent;
|
|
169
|
+
anchorToTooltip.set(parent, this);
|
|
170
|
+
lazyObserver?.observe(parent);
|
|
171
|
+
}
|
|
172
|
+
disconnectedCallback() {
|
|
173
|
+
this.hide();
|
|
174
|
+
if (this.fadeTimer !== void 0) {
|
|
175
|
+
clearTimeout(this.fadeTimer);
|
|
176
|
+
this.fadeTimer = void 0;
|
|
177
|
+
}
|
|
178
|
+
this.fading = false;
|
|
179
|
+
if (this.docMoveBound) {
|
|
180
|
+
this.doc.removeEventListener("mousemove", this.onDocMove);
|
|
181
|
+
this.docMoveBound = false;
|
|
182
|
+
}
|
|
183
|
+
this.teardownListeners();
|
|
184
|
+
if (this.anchor) {
|
|
185
|
+
if (anchorToTooltip.get(this.anchor) === this) {
|
|
186
|
+
anchorToTooltip.delete(this.anchor);
|
|
187
|
+
lazyObserver?.unobserve(this.anchor);
|
|
188
|
+
}
|
|
189
|
+
this.anchor = null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
attributeChangedCallback(name) {
|
|
193
|
+
if (name === "delay" && this.listening) this.makeDebouncedShow();
|
|
194
|
+
}
|
|
195
|
+
/** (Re)build the show debounce with the CURRENT `delay` (rebuilt when the
|
|
196
|
+
* `delay` attribute changes). Re-armed on each hover move (trailing), and
|
|
197
|
+
* fed the latest cursor event, so it shows at the cursor and so moving back
|
|
198
|
+
* onto an anchor after the tooltip was dismissed re-arms it. */
|
|
199
|
+
makeDebouncedShow() {
|
|
200
|
+
this.debouncedShow?.cancel();
|
|
201
|
+
this.debouncedShow = debounce((e) => this.show(e), this.delay);
|
|
202
|
+
}
|
|
203
|
+
/** The element's OWN window / document. The class may be defined in a
|
|
204
|
+
* different realm than the element lives in (e.g. the docs playground
|
|
205
|
+
* renders into an iframe but reuses the parent page's element class), so
|
|
206
|
+
* the module-global `window`/`document` can point at the wrong frame.
|
|
207
|
+
* Everything viewport- or document-scoped (clamping, scroll/key/move
|
|
208
|
+
* listeners) must go through these so it's correct in any frame. */
|
|
209
|
+
get view() {
|
|
210
|
+
return this.ownerDocument?.defaultView ?? window;
|
|
211
|
+
}
|
|
212
|
+
get doc() {
|
|
213
|
+
return this.ownerDocument ?? document;
|
|
214
|
+
}
|
|
215
|
+
get isInteractive() {
|
|
216
|
+
return this.hasAttribute("interactive");
|
|
217
|
+
}
|
|
218
|
+
/** Pinned under the anchor (no cursor-following). Interactive implies this —
|
|
219
|
+
* you can't move into a bubble that's chasing the cursor. */
|
|
220
|
+
get isStatic() {
|
|
221
|
+
return this.hasAttribute("static") || this.isInteractive;
|
|
222
|
+
}
|
|
223
|
+
/** Pinned to the anchor for any reason: the `static`/`interactive` attrs, or
|
|
224
|
+
* a touch long-press (a finger can't track a following bubble). */
|
|
225
|
+
get isPinned() {
|
|
226
|
+
return this.isStatic || this.touchOpen;
|
|
227
|
+
}
|
|
228
|
+
get prefersTop() {
|
|
229
|
+
return this.getAttribute("placement") === "top";
|
|
230
|
+
}
|
|
231
|
+
get delay() {
|
|
232
|
+
const attr = this.getAttribute("delay");
|
|
233
|
+
if (attr == null) return DEFAULT_DELAY;
|
|
234
|
+
const n = parseInt(attr, 10);
|
|
235
|
+
return Number.isFinite(n) ? n : DEFAULT_DELAY;
|
|
236
|
+
}
|
|
237
|
+
// --- positioning (sets only the shadow container's own transform) ---
|
|
238
|
+
positionToTarget = () => {
|
|
239
|
+
requestAnimationFrame(() => {
|
|
240
|
+
if (!this.anchor || !this.shown) return;
|
|
241
|
+
const a = this.anchor.getBoundingClientRect();
|
|
242
|
+
const box = this.container.getBoundingClientRect();
|
|
243
|
+
const view = this.view;
|
|
244
|
+
const vw = view.innerWidth;
|
|
245
|
+
const vh = view.innerHeight;
|
|
246
|
+
let left = a.left;
|
|
247
|
+
if (left + box.width > vw) left = vw - box.width - MARGIN;
|
|
248
|
+
left = Math.max(MARGIN, left);
|
|
249
|
+
let top;
|
|
250
|
+
if (this.prefersTop || this.touchOpen) {
|
|
251
|
+
top = a.top - box.height - MARGIN;
|
|
252
|
+
if (top < MARGIN) top = a.bottom + MARGIN;
|
|
253
|
+
} else {
|
|
254
|
+
top = a.bottom + MARGIN;
|
|
255
|
+
if (top + box.height > vh) top = a.top - box.height - MARGIN;
|
|
256
|
+
}
|
|
257
|
+
top = Math.max(MARGIN, top);
|
|
258
|
+
this.container.style.transform = `translate(${Math.round(left)}px, ${Math.round(top)}px)`;
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
positionToMouse = (e) => {
|
|
262
|
+
requestAnimationFrame(() => {
|
|
263
|
+
if (!this.shown && !this.fading) return;
|
|
264
|
+
const box = this.container.getBoundingClientRect();
|
|
265
|
+
const view = this.view;
|
|
266
|
+
const vw = view.innerWidth;
|
|
267
|
+
const vh = view.innerHeight;
|
|
268
|
+
let left = e.clientX - PADDING_X;
|
|
269
|
+
if (left + box.width > vw) left = vw - box.width - MARGIN;
|
|
270
|
+
left = Math.max(MARGIN, left);
|
|
271
|
+
let top;
|
|
272
|
+
if (this.prefersTop) {
|
|
273
|
+
top = e.clientY - box.height - MARGIN * 2;
|
|
274
|
+
if (top < MARGIN) top = e.clientY + CURSOR_SIZE;
|
|
275
|
+
} else {
|
|
276
|
+
top = e.clientY + CURSOR_SIZE;
|
|
277
|
+
if (top + box.height > vh) top = e.clientY - box.height - MARGIN * 2;
|
|
278
|
+
}
|
|
279
|
+
top = Math.max(MARGIN, top);
|
|
280
|
+
this.container.style.transform = `translate(${Math.round(left)}px, ${Math.round(top)}px)`;
|
|
281
|
+
});
|
|
282
|
+
};
|
|
283
|
+
position(e) {
|
|
284
|
+
if (!this.isPinned && e) this.positionToMouse(e);
|
|
285
|
+
else this.positionToTarget();
|
|
286
|
+
}
|
|
287
|
+
// --- show / hide ---
|
|
288
|
+
show = (e) => {
|
|
289
|
+
if (!this.anchor) return;
|
|
290
|
+
this.cancelHide();
|
|
291
|
+
if (currentOpen && currentOpen !== this && this.anchor.contains(currentOpen.anchor)) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
claimOpen(this);
|
|
295
|
+
if (!this.shown) {
|
|
296
|
+
this.shown = true;
|
|
297
|
+
this.fading = false;
|
|
298
|
+
if (this.fadeTimer !== void 0) {
|
|
299
|
+
clearTimeout(this.fadeTimer);
|
|
300
|
+
this.fadeTimer = void 0;
|
|
301
|
+
}
|
|
302
|
+
this.container.showPopover();
|
|
303
|
+
this.view.addEventListener("scroll", this.hide, { capture: true, passive: true });
|
|
304
|
+
this.doc.addEventListener("keydown", this.onKeyDown, true);
|
|
305
|
+
if (!this.docMoveBound) {
|
|
306
|
+
this.doc.addEventListener("mousemove", this.onDocMove);
|
|
307
|
+
this.docMoveBound = true;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
this.position(e);
|
|
311
|
+
};
|
|
312
|
+
hide = () => {
|
|
313
|
+
this.cancelHide();
|
|
314
|
+
if (!this.shown) return;
|
|
315
|
+
this.shown = false;
|
|
316
|
+
this.touchOpen = false;
|
|
317
|
+
this.container.hidePopover();
|
|
318
|
+
this.view.removeEventListener("scroll", this.hide, { capture: true });
|
|
319
|
+
this.doc.removeEventListener("keydown", this.onKeyDown, true);
|
|
320
|
+
this.fading = true;
|
|
321
|
+
if (this.fadeTimer !== void 0) clearTimeout(this.fadeTimer);
|
|
322
|
+
this.fadeTimer = setTimeout(() => {
|
|
323
|
+
this.fading = false;
|
|
324
|
+
this.fadeTimer = void 0;
|
|
325
|
+
if (this.docMoveBound) {
|
|
326
|
+
this.doc.removeEventListener("mousemove", this.onDocMove);
|
|
327
|
+
this.docMoveBound = false;
|
|
328
|
+
}
|
|
329
|
+
}, FADE_MS);
|
|
330
|
+
releaseOpen(this);
|
|
331
|
+
};
|
|
332
|
+
/** While shown, track the cursor even after it has left the anchor (during
|
|
333
|
+
* the close delay). Cursor-following only — static/interactive bubbles
|
|
334
|
+
* stay pinned. */
|
|
335
|
+
onDocMove = (e) => {
|
|
336
|
+
if ((this.shown || this.fading) && !this.isPinned) {
|
|
337
|
+
this.lastMouse = e;
|
|
338
|
+
this.positionToMouse(e);
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
/** Hide after CLOSE_DELAY unless something cancels it first (re-enter, or
|
|
342
|
+
* another tooltip claiming the slot). Lets the bubble bridge the gap to a
|
|
343
|
+
* neighbouring anchor — and survive the trip into an interactive bubble. */
|
|
344
|
+
scheduleHide = (delay = CLOSE_DELAY) => {
|
|
345
|
+
this.cancelHide();
|
|
346
|
+
this.closeTimer = setTimeout(() => {
|
|
347
|
+
this.closeTimer = void 0;
|
|
348
|
+
this.hide();
|
|
349
|
+
}, delay);
|
|
350
|
+
};
|
|
351
|
+
cancelHide() {
|
|
352
|
+
if (this.closeTimer !== void 0) {
|
|
353
|
+
clearTimeout(this.closeTimer);
|
|
354
|
+
this.closeTimer = void 0;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
onKeyDown = (e) => {
|
|
358
|
+
if (e.key === "Escape") this.hide();
|
|
359
|
+
};
|
|
360
|
+
/** Open now if another tooltip is hot (skip delay), else (re)arm the delayed
|
|
361
|
+
* show with the latest cursor event. */
|
|
362
|
+
trigger(e) {
|
|
363
|
+
if (isHot()) {
|
|
364
|
+
this.debouncedShow?.cancel();
|
|
365
|
+
this.show(e);
|
|
366
|
+
} else {
|
|
367
|
+
this.debouncedShow?.(e);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// --- lazy listener wiring (called by the intersection observer) ---
|
|
371
|
+
setupListeners() {
|
|
372
|
+
if (this.listening || !this.anchor) {
|
|
373
|
+
this.listening = true;
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const anchor = this.anchor;
|
|
377
|
+
const view = this.view;
|
|
378
|
+
const doc = this.doc;
|
|
379
|
+
this.makeDebouncedShow();
|
|
380
|
+
const onPointerMove = (e) => {
|
|
381
|
+
if (e.pointerType !== "mouse") return;
|
|
382
|
+
this.lastMouse = e;
|
|
383
|
+
if (this.shown) {
|
|
384
|
+
if (!this.isPinned) this.positionToMouse(e);
|
|
385
|
+
} else {
|
|
386
|
+
this.trigger(e);
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
const onLeave = () => {
|
|
390
|
+
this.debouncedShow?.cancel();
|
|
391
|
+
anchor.removeEventListener("pointermove", onPointerMove);
|
|
392
|
+
anchor.removeEventListener("pointerleave", onLeave);
|
|
393
|
+
anchor.removeEventListener("blur", onLeave);
|
|
394
|
+
view.removeEventListener("pagehide", onLeave);
|
|
395
|
+
doc.removeEventListener("visibilitychange", onLeave);
|
|
396
|
+
this.scheduleHide();
|
|
397
|
+
};
|
|
398
|
+
const onEnter = (e) => {
|
|
399
|
+
if (e.pointerType !== "mouse") return;
|
|
400
|
+
this.lastMouse = e;
|
|
401
|
+
anchor.addEventListener("pointermove", onPointerMove);
|
|
402
|
+
anchor.addEventListener("pointerleave", onLeave);
|
|
403
|
+
view.addEventListener("pagehide", onLeave);
|
|
404
|
+
doc.addEventListener("visibilitychange", onLeave);
|
|
405
|
+
this.trigger(e);
|
|
406
|
+
};
|
|
407
|
+
const onFocus = () => {
|
|
408
|
+
if (!anchor.matches(":focus-visible")) return;
|
|
409
|
+
anchor.addEventListener("blur", onLeave);
|
|
410
|
+
view.addEventListener("pagehide", onLeave);
|
|
411
|
+
doc.addEventListener("visibilitychange", onLeave);
|
|
412
|
+
this.trigger();
|
|
413
|
+
};
|
|
414
|
+
let pressTimer;
|
|
415
|
+
let pressStart;
|
|
416
|
+
const preventContext = (e) => e.preventDefault();
|
|
417
|
+
const clearPressTimer = () => {
|
|
418
|
+
if (pressTimer !== void 0) {
|
|
419
|
+
clearTimeout(pressTimer);
|
|
420
|
+
pressTimer = void 0;
|
|
421
|
+
}
|
|
422
|
+
pressStart = void 0;
|
|
423
|
+
};
|
|
424
|
+
const onPressMove = (e) => {
|
|
425
|
+
if (pressStart && Math.hypot(e.clientX - pressStart.x, e.clientY - pressStart.y) > TOUCH_SLOP) {
|
|
426
|
+
clearPressTimer();
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
const onPressEnd = () => {
|
|
430
|
+
clearPressTimer();
|
|
431
|
+
detachPress();
|
|
432
|
+
if (this.shown && this.touchOpen) this.scheduleHide(LEAVE_TOUCH_DELAY);
|
|
433
|
+
};
|
|
434
|
+
const detachPress = () => {
|
|
435
|
+
anchor.removeEventListener("pointermove", onPressMove);
|
|
436
|
+
anchor.removeEventListener("pointerup", onPressEnd);
|
|
437
|
+
anchor.removeEventListener("pointercancel", onPressEnd);
|
|
438
|
+
anchor.removeEventListener("contextmenu", preventContext);
|
|
439
|
+
};
|
|
440
|
+
const onPointerDown = (e) => {
|
|
441
|
+
if (e.pointerType === "mouse") return;
|
|
442
|
+
clearPressTimer();
|
|
443
|
+
pressStart = { x: e.clientX, y: e.clientY };
|
|
444
|
+
anchor.addEventListener("pointermove", onPressMove);
|
|
445
|
+
anchor.addEventListener("pointerup", onPressEnd);
|
|
446
|
+
anchor.addEventListener("pointercancel", onPressEnd);
|
|
447
|
+
anchor.addEventListener("contextmenu", preventContext);
|
|
448
|
+
pressTimer = setTimeout(() => {
|
|
449
|
+
pressTimer = void 0;
|
|
450
|
+
this.touchOpen = true;
|
|
451
|
+
this.show();
|
|
452
|
+
}, ENTER_TOUCH_DELAY);
|
|
453
|
+
};
|
|
454
|
+
anchor.addEventListener("pointerenter", onEnter);
|
|
455
|
+
anchor.addEventListener("focus", onFocus);
|
|
456
|
+
anchor.addEventListener("pointerdown", onPointerDown);
|
|
457
|
+
this.teardown = () => {
|
|
458
|
+
this.debouncedShow?.cancel();
|
|
459
|
+
clearPressTimer();
|
|
460
|
+
detachPress();
|
|
461
|
+
anchor.removeEventListener("pointermove", onPointerMove);
|
|
462
|
+
anchor.removeEventListener("pointerenter", onEnter);
|
|
463
|
+
anchor.removeEventListener("pointerleave", onLeave);
|
|
464
|
+
anchor.removeEventListener("focus", onFocus);
|
|
465
|
+
anchor.removeEventListener("blur", onLeave);
|
|
466
|
+
anchor.removeEventListener("pointerdown", onPointerDown);
|
|
467
|
+
view.removeEventListener("pagehide", onLeave);
|
|
468
|
+
doc.removeEventListener("visibilitychange", onLeave);
|
|
469
|
+
this.listening = false;
|
|
470
|
+
};
|
|
471
|
+
this.listening = true;
|
|
472
|
+
}
|
|
473
|
+
teardownListeners() {
|
|
474
|
+
this.teardown?.();
|
|
475
|
+
this.teardown = void 0;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
function register_a_tooltip() {
|
|
479
|
+
if (typeof customElements === "undefined") return;
|
|
480
|
+
if (!customElements.get("a-tooltip")) {
|
|
481
|
+
customElements.define("a-tooltip", ATooltipElement);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
register_a_tooltip();
|
|
485
|
+
export {
|
|
486
|
+
ATooltipElement,
|
|
487
|
+
register_a_tooltip
|
|
488
|
+
};
|
package/dist/elements/index.d.ts
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import '
|
|
8
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Barrel: registers ALL Anta custom elements (the convenience path).
|
|
3
|
+
*
|
|
4
|
+
* Each `a-{name}` module self-registers and imports its own CSS when loaded,
|
|
5
|
+
* so re-exporting them here (which evaluates each module) registers the whole
|
|
6
|
+
* set + injects every element's CSS. Importing this barrel for side effects —
|
|
7
|
+
* `import '@antadesign/anta/elements'` — gives you everything.
|
|
8
|
+
*
|
|
9
|
+
* For a SMALLER footprint, import just the element(s) you use instead:
|
|
10
|
+
* import '@antadesign/anta/elements/a-tooltip' // registers a-tooltip + its CSS, nothing else
|
|
11
|
+
* That granular path pulls in only that element's code and CSS, nothing else.
|
|
12
|
+
*
|
|
13
|
+
* Must only be imported client-side — registration is guarded against missing
|
|
14
|
+
* `customElements` (SSR), but there's no reason to load it server-side.
|
|
15
|
+
*/
|
|
9
16
|
export { AProgressElement, register_a_progress } from './a-progress';
|
|
10
17
|
export { ATextElement, register_a_text } from './a-text';
|
|
11
18
|
export { AIconElement, register_a_icon } from './a-icon';
|
|
12
19
|
export { AButtonElement, register_a_button } from './a-button';
|
|
13
|
-
export {
|
|
14
|
-
|
|
20
|
+
export { ATooltipElement, register_a_tooltip } from './a-tooltip';
|
|
21
|
+
import './a-title.css';
|
|
22
|
+
import './a-tag.css';
|
package/dist/elements/index.js
CHANGED
|
@@ -1,42 +1,19 @@
|
|
|
1
|
-
import { register_a_progress } from "./a-progress";
|
|
2
|
-
import { register_a_text } from "./a-text";
|
|
3
|
-
import { register_a_icon } from "./a-icon";
|
|
4
|
-
import { register_a_button } from "./a-button";
|
|
5
|
-
import {
|
|
6
|
-
import { register_a_sticker_animated } from "./a-sticker-animated";
|
|
7
|
-
import "./a-progress.css";
|
|
8
|
-
import "./a-text.css";
|
|
1
|
+
import { AProgressElement, register_a_progress } from "./a-progress";
|
|
2
|
+
import { ATextElement, register_a_text } from "./a-text";
|
|
3
|
+
import { AIconElement, register_a_icon } from "./a-icon";
|
|
4
|
+
import { AButtonElement, register_a_button } from "./a-button";
|
|
5
|
+
import { ATooltipElement, register_a_tooltip } from "./a-tooltip";
|
|
9
6
|
import "./a-title.css";
|
|
10
|
-
import "./a-
|
|
11
|
-
import "./a-icon.shapes.css";
|
|
12
|
-
import "./a-button.css";
|
|
13
|
-
import "./a-sticker.css";
|
|
14
|
-
import "./a-sticker-animated.css";
|
|
15
|
-
import { AProgressElement, register_a_progress as register_a_progress2 } from "./a-progress";
|
|
16
|
-
import { ATextElement, register_a_text as register_a_text2 } from "./a-text";
|
|
17
|
-
import { AIconElement, register_a_icon as register_a_icon2 } from "./a-icon";
|
|
18
|
-
import { AButtonElement, register_a_button as register_a_button2 } from "./a-button";
|
|
19
|
-
import { AStickerElement, register_a_sticker as register_a_sticker2 } from "./a-sticker";
|
|
20
|
-
import { AStickerAnimatedElement, register_a_sticker_animated as register_a_sticker_animated2 } from "./a-sticker-animated";
|
|
21
|
-
if (typeof customElements !== "undefined") {
|
|
22
|
-
register_a_progress();
|
|
23
|
-
register_a_text();
|
|
24
|
-
register_a_icon();
|
|
25
|
-
register_a_button();
|
|
26
|
-
register_a_sticker();
|
|
27
|
-
register_a_sticker_animated();
|
|
28
|
-
}
|
|
7
|
+
import "./a-tag.css";
|
|
29
8
|
export {
|
|
30
9
|
AButtonElement,
|
|
31
10
|
AIconElement,
|
|
32
11
|
AProgressElement,
|
|
33
|
-
AStickerAnimatedElement,
|
|
34
|
-
AStickerElement,
|
|
35
12
|
ATextElement,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
13
|
+
ATooltipElement,
|
|
14
|
+
register_a_button,
|
|
15
|
+
register_a_icon,
|
|
16
|
+
register_a_progress,
|
|
17
|
+
register_a_text,
|
|
18
|
+
register_a_tooltip
|
|
42
19
|
};
|