@antadesign/anta 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/anta_helpers.d.ts +111 -0
- package/dist/anta_helpers.js +90 -1
- package/dist/calendar-core.d.ts +126 -0
- package/dist/calendar-core.js +289 -0
- package/dist/components/Button.d.ts +9 -1
- package/dist/components/Button.js +12 -18
- package/dist/components/Calendar.d.ts +80 -0
- package/dist/components/Calendar.js +220 -0
- package/dist/components/Checkbox.d.ts +21 -15
- package/dist/components/Checkbox.js +17 -7
- package/dist/components/Expander.d.ts +7 -1
- package/dist/components/Expander.js +4 -2
- package/dist/components/Input.d.ts +16 -8
- package/dist/components/Input.js +19 -11
- package/dist/components/InputDate.d.ts +87 -0
- package/dist/components/InputDate.js +278 -0
- package/dist/components/InputDate.module.css +1 -0
- package/dist/components/Menu.d.ts +5 -1
- package/dist/components/Menu.js +6 -2
- package/dist/components/MenuItem.d.ts +48 -7
- package/dist/components/MenuItem.js +71 -7
- package/dist/components/MenuSeparator.d.ts +13 -2
- package/dist/components/MenuSeparator.js +12 -2
- package/dist/components/Progress.d.ts +4 -1
- package/dist/components/Progress.js +4 -3
- package/dist/components/RadioGroup.d.ts +17 -15
- package/dist/components/RadioGroup.js +8 -8
- package/dist/components/Select.d.ts +255 -0
- package/dist/components/Select.js +290 -0
- package/dist/components/Select.module.css +1 -0
- package/dist/components/Tab.d.ts +37 -0
- package/dist/components/Tab.js +5 -0
- package/dist/components/TabPanel.d.ts +22 -0
- package/dist/components/TabPanel.js +5 -0
- package/dist/components/Tabs.d.ts +129 -0
- package/dist/components/Tabs.js +176 -0
- package/dist/components/Tabs.module.css +1 -0
- package/dist/components/Tag.d.ts +10 -9
- package/dist/components/Tag.js +2 -2
- package/dist/components/Text.d.ts +6 -5
- package/dist/components/Title.d.ts +4 -2
- package/dist/components/Tooltip.d.ts +13 -1
- package/dist/components/Tooltip.js +9 -0
- package/dist/elements/a-button.css +1 -1
- package/dist/elements/a-calendar.css +1 -0
- package/dist/elements/a-calendar.d.ts +76 -0
- package/dist/elements/a-calendar.js +190 -0
- package/dist/elements/a-checkbox.css +1 -1
- package/dist/elements/a-checkbox.d.ts +1 -2
- package/dist/elements/a-checkbox.js +5 -5
- package/dist/elements/a-expander.css +1 -1
- package/dist/elements/a-expander.d.ts +16 -5
- package/dist/elements/a-expander.js +65 -9
- package/dist/elements/a-icon.shapes.css +1 -1
- package/dist/elements/a-icon.shapes.d.ts +6 -1
- package/dist/elements/a-icon.shapes.js +9 -0
- package/dist/elements/a-input.css +1 -1
- package/dist/elements/a-input.d.ts +6 -0
- package/dist/elements/a-input.js +28 -9
- package/dist/elements/a-menu-group.css +1 -1
- package/dist/elements/a-menu-item.css +1 -1
- package/dist/elements/a-menu-item.d.ts +14 -4
- package/dist/elements/a-menu-item.js +17 -0
- package/dist/elements/a-menu-separator.css +1 -1
- package/dist/elements/a-menu.css +1 -1
- package/dist/elements/a-menu.d.ts +51 -8
- package/dist/elements/a-menu.js +285 -42
- package/dist/elements/a-progress.css +1 -1
- package/dist/elements/a-radio-group.d.ts +1 -3
- package/dist/elements/a-radio-group.js +13 -13
- package/dist/elements/a-radio.css +1 -1
- package/dist/elements/a-radio.d.ts +3 -11
- package/dist/elements/a-radio.js +3 -34
- package/dist/elements/a-tab.css +1 -0
- package/dist/elements/a-tab.d.ts +6 -0
- package/dist/elements/a-tab.js +15 -0
- package/dist/elements/a-tabpanel.css +1 -0
- package/dist/elements/a-tabs.css +1 -0
- package/dist/elements/a-tabs.d.ts +28 -0
- package/dist/elements/a-tabs.js +157 -0
- package/dist/elements/a-tag.css +1 -1
- package/dist/elements/a-text.css +1 -1
- package/dist/elements/a-text.d.ts +14 -13
- package/dist/elements/a-text.js +53 -23
- package/dist/elements/a-title.css +1 -1
- package/dist/elements/a-tooltip.css +1 -1
- package/dist/elements/a-tooltip.d.ts +16 -8
- package/dist/elements/a-tooltip.js +62 -16
- package/dist/elements/index.d.ts +4 -0
- package/dist/elements/index.js +10 -0
- package/dist/general_types.d.ts +252 -30
- package/dist/index.d.ts +15 -1
- package/dist/index.js +43 -1
- package/dist/jsx-runtime.d.ts +20 -7
- package/dist/jsx-runtime.js +6 -0
- package/dist/reset.css +1 -1
- package/dist/tokens.css +1 -1
- package/package.json +4 -2
|
@@ -28,6 +28,7 @@ import './a-tooltip.css';
|
|
|
28
28
|
* below) instead of selecting text or popping the system menu.
|
|
29
29
|
*/
|
|
30
30
|
export declare class ATooltipElement extends HTMLElementBase {
|
|
31
|
+
#private;
|
|
31
32
|
static observedAttributes: string[];
|
|
32
33
|
/** Shadow-internal popover surface — the only thing we ever mutate. */
|
|
33
34
|
private container;
|
|
@@ -60,14 +61,21 @@ export declare class ATooltipElement extends HTMLElementBase {
|
|
|
60
61
|
* fed the latest cursor event, so it shows at the cursor and so moving back
|
|
61
62
|
* onto an anchor after the tooltip was dismissed re-arms it. */
|
|
62
63
|
private makeDebouncedShow;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
/** The element whose overflow decides whether the tooltip shows: a
|
|
65
|
+
* `truncated-selector` resolved within the anchor wins; else the first of
|
|
66
|
+
* Anta's ellipsizing label parts inside the anchor; else the anchor itself
|
|
67
|
+
* (which may be the clipping box for a hand-authored target). */
|
|
68
|
+
private resolveTruncationTarget;
|
|
69
|
+
/** True when the resolved target overflows its box (horizontal ellipsis or
|
|
70
|
+
* vertical clamp). A 1px threshold absorbs sub-pixel rounding; a zero-size
|
|
71
|
+
* (hidden / detached) target counts as not truncated. Measured fresh on each
|
|
72
|
+
* show attempt, so late fonts / resizes self-correct with no observer. */
|
|
73
|
+
private isTargetTruncated;
|
|
74
|
+
/** True when there's nothing worth showing: no element children (so an
|
|
75
|
+
* icon/image-only bubble still counts as content) and no non-whitespace text
|
|
76
|
+
* (so formatting whitespace / an empty conditional doesn't open a blank bubble).
|
|
77
|
+
* Re-checked on every show(), so a tooltip populated later self-corrects. */
|
|
78
|
+
private isEmpty;
|
|
71
79
|
private positionFrame?;
|
|
72
80
|
private pendingPosition?;
|
|
73
81
|
private schedulePosition;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HTMLElementBase } from "../anta_helpers";
|
|
1
|
+
import { HTMLElementBase, anchorRect, isMenuOpen, isInsideOpenMenu } from "../anta_helpers";
|
|
2
2
|
import { debounce } from "es-toolkit";
|
|
3
3
|
import "./a-tooltip.css";
|
|
4
4
|
const MARGIN = 4;
|
|
@@ -12,6 +12,7 @@ const PROX_NEAR = 10;
|
|
|
12
12
|
const PROX_FAR = 100;
|
|
13
13
|
const PROX_FADE_MS = 60;
|
|
14
14
|
const ENTER_TOUCH_DELAY = 500;
|
|
15
|
+
const TRUNCATING_PARTS = "a-tab-label, a-button-label";
|
|
15
16
|
const LEAVE_TOUCH_DELAY = 1500;
|
|
16
17
|
const TOUCH_SLOP = 10;
|
|
17
18
|
let currentOpen = null;
|
|
@@ -163,10 +164,10 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
163
164
|
this.bubble.setAttribute("part", "bubble");
|
|
164
165
|
this.container.append(this.bubble);
|
|
165
166
|
this.container.addEventListener("mouseenter", () => {
|
|
166
|
-
if (this
|
|
167
|
+
if (this.#isInteractive) this.cancelHide();
|
|
167
168
|
});
|
|
168
169
|
this.container.addEventListener("mouseleave", () => {
|
|
169
|
-
if (this
|
|
170
|
+
if (this.#isInteractive && this.shown) this.scheduleHide();
|
|
170
171
|
});
|
|
171
172
|
shadow.append(style, this.container);
|
|
172
173
|
}
|
|
@@ -196,28 +197,68 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
196
197
|
* onto an anchor after the tooltip was dismissed re-arms it. */
|
|
197
198
|
makeDebouncedShow() {
|
|
198
199
|
this.debouncedShow?.cancel();
|
|
199
|
-
this.debouncedShow = debounce((e) => this.show(e), this
|
|
200
|
+
this.debouncedShow = debounce((e) => this.show(e), this.#delay);
|
|
200
201
|
}
|
|
201
|
-
get isInteractive() {
|
|
202
|
+
get #isInteractive() {
|
|
202
203
|
return this.hasAttribute("interactive");
|
|
203
204
|
}
|
|
204
205
|
/** Pinned under the anchor (no cursor-following) — the DEFAULT. Following the
|
|
205
206
|
* cursor is opt-in via the `follow` attribute. `interactive` (you can't move
|
|
206
207
|
* into a bubble that chases the cursor) and a touch long-press (a finger
|
|
207
208
|
* can't track one) force pinned regardless of `follow`. */
|
|
208
|
-
get isPinned() {
|
|
209
|
-
if (this
|
|
209
|
+
get #isPinned() {
|
|
210
|
+
if (this.#isInteractive || this.touchOpen) return true;
|
|
210
211
|
return !this.hasAttribute("follow");
|
|
211
212
|
}
|
|
212
|
-
get prefersTop() {
|
|
213
|
+
get #prefersTop() {
|
|
213
214
|
return this.getAttribute("placement") === "top";
|
|
214
215
|
}
|
|
215
|
-
get delay() {
|
|
216
|
+
get #delay() {
|
|
216
217
|
const attr = this.getAttribute("delay");
|
|
217
218
|
if (attr == null) return DEFAULT_DELAY;
|
|
218
219
|
const n = parseInt(attr, 10);
|
|
219
220
|
return Number.isFinite(n) ? n : DEFAULT_DELAY;
|
|
220
221
|
}
|
|
222
|
+
// --- truncated-only gating (UI-thread layout READS — no mutation) ---
|
|
223
|
+
/** When set, the tooltip only shows if its resolved target is actually
|
|
224
|
+
* truncated/clipped; a fitting label gets no tooltip. */
|
|
225
|
+
get #truncatedOnly() {
|
|
226
|
+
return this.hasAttribute("truncated-only");
|
|
227
|
+
}
|
|
228
|
+
/** The element whose overflow decides whether the tooltip shows: a
|
|
229
|
+
* `truncated-selector` resolved within the anchor wins; else the first of
|
|
230
|
+
* Anta's ellipsizing label parts inside the anchor; else the anchor itself
|
|
231
|
+
* (which may be the clipping box for a hand-authored target). */
|
|
232
|
+
resolveTruncationTarget() {
|
|
233
|
+
const anchor = this.anchor;
|
|
234
|
+
if (!anchor) return null;
|
|
235
|
+
const sel = this.getAttribute("truncated-selector");
|
|
236
|
+
if (sel) {
|
|
237
|
+
try {
|
|
238
|
+
const found = anchor.querySelector(sel);
|
|
239
|
+
if (found) return found;
|
|
240
|
+
} catch {
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return anchor.querySelector(TRUNCATING_PARTS) ?? anchor;
|
|
244
|
+
}
|
|
245
|
+
/** True when the resolved target overflows its box (horizontal ellipsis or
|
|
246
|
+
* vertical clamp). A 1px threshold absorbs sub-pixel rounding; a zero-size
|
|
247
|
+
* (hidden / detached) target counts as not truncated. Measured fresh on each
|
|
248
|
+
* show attempt, so late fonts / resizes self-correct with no observer. */
|
|
249
|
+
isTargetTruncated() {
|
|
250
|
+
const t = this.resolveTruncationTarget();
|
|
251
|
+
if (!t) return false;
|
|
252
|
+
if (t.clientWidth === 0 && t.clientHeight === 0) return false;
|
|
253
|
+
return t.scrollWidth - t.clientWidth > 1 || t.scrollHeight - t.clientHeight > 1;
|
|
254
|
+
}
|
|
255
|
+
/** True when there's nothing worth showing: no element children (so an
|
|
256
|
+
* icon/image-only bubble still counts as content) and no non-whitespace text
|
|
257
|
+
* (so formatting whitespace / an empty conditional doesn't open a blank bubble).
|
|
258
|
+
* Re-checked on every show(), so a tooltip populated later self-corrects. */
|
|
259
|
+
isEmpty() {
|
|
260
|
+
return this.children.length === 0 && (this.textContent ?? "").trim() === "";
|
|
261
|
+
}
|
|
221
262
|
// --- positioning (sets only the shadow container's own transform) ---
|
|
222
263
|
// Single pending position frame: a burst of mousemoves within one frame
|
|
223
264
|
// coalesces to ONE layout read + transform write, using the LATEST geometry
|
|
@@ -253,10 +294,10 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
253
294
|
positionToTarget = () => {
|
|
254
295
|
this.schedulePosition(() => {
|
|
255
296
|
if (!this.anchor || !this.shown) return;
|
|
256
|
-
const a = this.anchor
|
|
297
|
+
const a = anchorRect(this.anchor);
|
|
257
298
|
const box = this.container.getBoundingClientRect();
|
|
258
299
|
const { innerWidth: vw, innerHeight: vh } = this.view;
|
|
259
|
-
const top = this.flipVertical(a.top - box.height - MARGIN, a.bottom + MARGIN, box.height, vh, this
|
|
300
|
+
const top = this.flipVertical(a.top - box.height - MARGIN, a.bottom + MARGIN, box.height, vh, this.#prefersTop || this.touchOpen);
|
|
260
301
|
this.place(a.left, top, box.width, vw);
|
|
261
302
|
});
|
|
262
303
|
};
|
|
@@ -265,12 +306,12 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
265
306
|
if (!this.shown && !this.fading) return;
|
|
266
307
|
const box = this.container.getBoundingClientRect();
|
|
267
308
|
const { innerWidth: vw, innerHeight: vh } = this.view;
|
|
268
|
-
const top = this.flipVertical(e.clientY - box.height - MARGIN * 2, e.clientY + CURSOR_SIZE, box.height, vh, this
|
|
309
|
+
const top = this.flipVertical(e.clientY - box.height - MARGIN * 2, e.clientY + CURSOR_SIZE, box.height, vh, this.#prefersTop);
|
|
269
310
|
this.place(e.clientX - PADDING_X, top, box.width, vw);
|
|
270
311
|
});
|
|
271
312
|
};
|
|
272
313
|
position(e) {
|
|
273
|
-
if (!this
|
|
314
|
+
if (!this.#isPinned && e) this.positionToMouse(e);
|
|
274
315
|
else this.positionToTarget();
|
|
275
316
|
}
|
|
276
317
|
/** Opacity for the inner bubble from the cursor's distance to the anchor rect
|
|
@@ -278,7 +319,7 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
278
319
|
* Cursor-follow only — drives the "fade as you move away" behaviour. */
|
|
279
320
|
proximityOpacity(e) {
|
|
280
321
|
if (!this.anchor) return 1;
|
|
281
|
-
const r = this.anchor
|
|
322
|
+
const r = anchorRect(this.anchor);
|
|
282
323
|
const dx = Math.max(r.left - e.clientX, 0, e.clientX - r.right);
|
|
283
324
|
const dy = Math.max(r.top - e.clientY, 0, e.clientY - r.bottom);
|
|
284
325
|
const dist = Math.hypot(dx, dy);
|
|
@@ -289,6 +330,9 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
289
330
|
// --- show / hide ---
|
|
290
331
|
show = (e) => {
|
|
291
332
|
if (!this.anchor) return;
|
|
333
|
+
if (isMenuOpen() && !isInsideOpenMenu(this.anchor)) return;
|
|
334
|
+
if (this.isEmpty()) return;
|
|
335
|
+
if (this.#truncatedOnly && !this.isTargetTruncated()) return;
|
|
292
336
|
this.cancelHide();
|
|
293
337
|
if (currentOpen && currentOpen !== this && this.anchor.contains(currentOpen.anchor)) {
|
|
294
338
|
return;
|
|
@@ -365,7 +409,7 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
365
409
|
this.cleanup();
|
|
366
410
|
return;
|
|
367
411
|
}
|
|
368
|
-
if (!(this.shown || this.fading) || this
|
|
412
|
+
if (!(this.shown || this.fading) || this.#isPinned) return;
|
|
369
413
|
this.lastMouse = e;
|
|
370
414
|
const o = this.proximityOpacity(e);
|
|
371
415
|
if (o === 0) {
|
|
@@ -400,6 +444,8 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
400
444
|
/** Open now if another tooltip is hot (skip delay), else (re)arm the delayed
|
|
401
445
|
* show with the latest cursor event. */
|
|
402
446
|
trigger(e) {
|
|
447
|
+
if (this.isEmpty()) return;
|
|
448
|
+
if (this.#truncatedOnly && !this.isTargetTruncated()) return;
|
|
403
449
|
if (isHot()) {
|
|
404
450
|
this.debouncedShow?.cancel();
|
|
405
451
|
this.show(e);
|
|
@@ -421,7 +467,7 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
421
467
|
if (e.pointerType !== "mouse") return;
|
|
422
468
|
this.lastMouse = e;
|
|
423
469
|
if (this.shown) {
|
|
424
|
-
if (!this
|
|
470
|
+
if (!this.#isPinned) this.positionToMouse(e);
|
|
425
471
|
} else {
|
|
426
472
|
this.trigger(e);
|
|
427
473
|
}
|
package/dist/elements/index.d.ts
CHANGED
|
@@ -21,11 +21,15 @@ export { ACheckboxElement, register_a_checkbox } from './a-checkbox';
|
|
|
21
21
|
export { AExpanderElement, register_a_expander } from './a-expander';
|
|
22
22
|
export { ATooltipElement, register_a_tooltip } from './a-tooltip';
|
|
23
23
|
export { AInputElement, register_a_input } from './a-input';
|
|
24
|
+
export { ACalendarElement, register_a_calendar } from './a-calendar';
|
|
24
25
|
export { ARadioElement, register_a_radio } from './a-radio';
|
|
25
26
|
export { ARadioGroupElement, register_a_radio_group } from './a-radio-group';
|
|
26
27
|
export { AMenuElement, register_a_menu } from './a-menu';
|
|
27
28
|
export { AMenuItemElement, register_a_menu_item } from './a-menu-item';
|
|
28
29
|
export { AMenuSeparatorElement, register_a_menu_separator } from './a-menu-separator';
|
|
29
30
|
export { AMenuGroupElement, register_a_menu_group } from './a-menu-group';
|
|
31
|
+
export { ATabElement, register_a_tab } from './a-tab';
|
|
32
|
+
export { ATabsElement, register_a_tabs } from './a-tabs';
|
|
30
33
|
import './a-title.css';
|
|
31
34
|
import './a-tag.css';
|
|
35
|
+
import './a-tabpanel.css';
|
package/dist/elements/index.js
CHANGED
|
@@ -6,16 +6,21 @@ import { ACheckboxElement, register_a_checkbox } from "./a-checkbox";
|
|
|
6
6
|
import { AExpanderElement, register_a_expander } from "./a-expander";
|
|
7
7
|
import { ATooltipElement, register_a_tooltip } from "./a-tooltip";
|
|
8
8
|
import { AInputElement, register_a_input } from "./a-input";
|
|
9
|
+
import { ACalendarElement, register_a_calendar } from "./a-calendar";
|
|
9
10
|
import { ARadioElement, register_a_radio } from "./a-radio";
|
|
10
11
|
import { ARadioGroupElement, register_a_radio_group } from "./a-radio-group";
|
|
11
12
|
import { AMenuElement, register_a_menu } from "./a-menu";
|
|
12
13
|
import { AMenuItemElement, register_a_menu_item } from "./a-menu-item";
|
|
13
14
|
import { AMenuSeparatorElement, register_a_menu_separator } from "./a-menu-separator";
|
|
14
15
|
import { AMenuGroupElement, register_a_menu_group } from "./a-menu-group";
|
|
16
|
+
import { ATabElement, register_a_tab } from "./a-tab";
|
|
17
|
+
import { ATabsElement, register_a_tabs } from "./a-tabs";
|
|
15
18
|
import "./a-title.css";
|
|
16
19
|
import "./a-tag.css";
|
|
20
|
+
import "./a-tabpanel.css";
|
|
17
21
|
export {
|
|
18
22
|
AButtonElement,
|
|
23
|
+
ACalendarElement,
|
|
19
24
|
ACheckboxElement,
|
|
20
25
|
AExpanderElement,
|
|
21
26
|
AIconElement,
|
|
@@ -27,9 +32,12 @@ export {
|
|
|
27
32
|
AProgressElement,
|
|
28
33
|
ARadioElement,
|
|
29
34
|
ARadioGroupElement,
|
|
35
|
+
ATabElement,
|
|
36
|
+
ATabsElement,
|
|
30
37
|
ATextElement,
|
|
31
38
|
ATooltipElement,
|
|
32
39
|
register_a_button,
|
|
40
|
+
register_a_calendar,
|
|
33
41
|
register_a_checkbox,
|
|
34
42
|
register_a_expander,
|
|
35
43
|
register_a_icon,
|
|
@@ -41,6 +49,8 @@ export {
|
|
|
41
49
|
register_a_progress,
|
|
42
50
|
register_a_radio,
|
|
43
51
|
register_a_radio_group,
|
|
52
|
+
register_a_tab,
|
|
53
|
+
register_a_tabs,
|
|
44
54
|
register_a_text,
|
|
45
55
|
register_a_tooltip
|
|
46
56
|
};
|