@antadesign/anta 0.1.1-dev.7 → 0.1.1-dev.8
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/Tooltip.d.ts +55 -0
- package/dist/components/Tooltip.js +26 -0
- 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-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-text.d.ts +1 -0
- package/dist/elements/a-text.js +2 -0
- package/dist/elements/a-tooltip.css +42 -0
- package/dist/elements/a-tooltip.d.ts +61 -0
- package/dist/elements/a-tooltip.js +411 -0
- package/dist/elements/index.d.ts +18 -8
- package/dist/elements/index.js +15 -33
- package/dist/general_types.d.ts +25 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/jsx-runtime.d.ts +2 -1
- package/dist/reset.css +10 -5
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -36,6 +36,8 @@ Anta exposes four independent imports. Tokens + elements + the JSX layer are the
|
|
|
36
36
|
|
|
37
37
|
The chain matters: the per-element CSS that ships with `/elements` references variables like `var(--text-1)` and `var(--bg-2)`. Those variables are *only defined* by `tokens.css`. Skip the tokens import and the components render with whatever the surrounding cascade provides — usually nothing styled at all.
|
|
38
38
|
|
|
39
|
+
`@antadesign/anta/elements` registers **all** elements — convenient, but it includes every element's code (and deps). To keep your bundle lean, import only the elements you use from their per-element entry points instead: `import '@antadesign/anta/elements/a-tooltip'` registers just `<a-tooltip>` **and loads just its CSS**. Unused elements — and their dependencies, e.g. `lottie-web` (needed only by `<a-sticker-animated>`) — then never enter your bundle. See [Registering elements](#registering-elements).
|
|
40
|
+
|
|
39
41
|
### Cascade layers
|
|
40
42
|
|
|
41
43
|
Anta's reset and element CSS live in `@layer anta`. `tokens.css` pre-declares an order of `@layer base, anta, components, utilities;`, which keeps Anta's defaults above any preflight resets (Tailwind's `@layer base`, Normalize, etc.) while letting your own `@layer components` rules and utility-class frameworks like Tailwind (`@layer utilities`) override Anta when you ask them to.
|
|
@@ -70,6 +72,15 @@ The JSX wrappers (React components) as `Progress` render custom DOM elements as
|
|
|
70
72
|
import '@antadesign/anta/elements' // auto-registers all elements
|
|
71
73
|
```
|
|
72
74
|
|
|
75
|
+
**Register only what you use.** `/elements` is the all-in-one convenience import. To trim your bundle, import the specific element entry points instead — each registers just that element and loads just its CSS:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import '@antadesign/anta/elements/a-tooltip' // only <a-tooltip> + its CSS
|
|
79
|
+
import '@antadesign/anta/elements/a-button' // only <a-button> + its CSS
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Both styles are side-effect imports (the act of importing registers the element), and both are idempotent and SSR-safe. The granular form keeps unused elements — and their dependencies, e.g. `lottie-web`, which only `<a-sticker-animated>` pulls in — out of your bundle.
|
|
83
|
+
|
|
73
84
|
The cleanest pattern is a **static, synchronous import at your app's entry file** — outside any component, outside any hook:
|
|
74
85
|
|
|
75
86
|
```ts
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { BaseProps } from "../general_types";
|
|
2
|
+
export interface TooltipProps extends BaseProps {
|
|
3
|
+
/** Tooltip content. Renders anything — text, markup, an icon + text.
|
|
4
|
+
* Lives in the light DOM, so it's styleable with your own plain CSS. */
|
|
5
|
+
children?: React.ReactNode;
|
|
6
|
+
/** Show delay in milliseconds after hover / focus. Never use `0` — use
|
|
7
|
+
* ~`50` for a near-instant tooltip (0 has caused issues in practice).
|
|
8
|
+
* @defaultValue 250 */
|
|
9
|
+
delay?: number;
|
|
10
|
+
/** Which side of the anchor the bubble prefers. Auto-flips to the other
|
|
11
|
+
* side when there isn't room.
|
|
12
|
+
* @defaultValue bottom */
|
|
13
|
+
placement?: 'top' | 'bottom';
|
|
14
|
+
/** Pin the bubble under the anchor instead of following the cursor. */
|
|
15
|
+
static?: boolean;
|
|
16
|
+
/** Make the bubble hoverable and clickable — enables pointer events and
|
|
17
|
+
* keeps it open while the cursor is over it, so its content (links,
|
|
18
|
+
* buttons) can be interacted with. Implies `static` (an interactive
|
|
19
|
+
* bubble can't follow the cursor). */
|
|
20
|
+
interactive?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Tooltip — a small floating bubble that describes the element it's placed
|
|
24
|
+
* inside. Render `<Tooltip>` as a child of the element it annotates; it
|
|
25
|
+
* doesn't affect that element's layout.
|
|
26
|
+
*
|
|
27
|
+
* Shows on hover (after `delay`) and on keyboard focus; dismisses on mouse
|
|
28
|
+
* leave, blur, Escape, or when the anchor scrolls away. Follows the cursor
|
|
29
|
+
* by default — pass `static` to pin it under the anchor instead.
|
|
30
|
+
*
|
|
31
|
+
* Requires `@antadesign/anta/elements` to be imported (client-side only)
|
|
32
|
+
* to register the underlying custom element.
|
|
33
|
+
*
|
|
34
|
+
* @example Basic usage
|
|
35
|
+
* ```tsx
|
|
36
|
+
* import { Tooltip } from '@antadesign/anta'
|
|
37
|
+
* import '@antadesign/anta/elements'
|
|
38
|
+
*
|
|
39
|
+
* <button>
|
|
40
|
+
* Save
|
|
41
|
+
* <Tooltip>Saves your work</Tooltip>
|
|
42
|
+
* </button>
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @example Pinned above, rich content
|
|
46
|
+
* ```tsx
|
|
47
|
+
* <span style={{ cursor: 'help' }}>
|
|
48
|
+
* Status
|
|
49
|
+
* <Tooltip placement="top" static>
|
|
50
|
+
* <strong>Healthy</strong> — last checked 2m ago
|
|
51
|
+
* </Tooltip>
|
|
52
|
+
* </span>
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare const Tooltip: ({ delay, placement, static: isStatic, interactive, className, children, ...rest }: TooltipProps) => any;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx } from "@antadesign/anta/jsx-runtime";
|
|
2
|
+
const Tooltip = ({
|
|
3
|
+
delay,
|
|
4
|
+
placement,
|
|
5
|
+
static: isStatic,
|
|
6
|
+
interactive,
|
|
7
|
+
className,
|
|
8
|
+
children,
|
|
9
|
+
...rest
|
|
10
|
+
}) => {
|
|
11
|
+
return /* @__PURE__ */ jsx(
|
|
12
|
+
"a-tooltip",
|
|
13
|
+
{
|
|
14
|
+
delay: delay != null ? String(delay) : void 0,
|
|
15
|
+
placement: placement === "top" ? "top" : void 0,
|
|
16
|
+
static: isStatic ? "" : void 0,
|
|
17
|
+
interactive: interactive ? "" : void 0,
|
|
18
|
+
class: className,
|
|
19
|
+
...rest,
|
|
20
|
+
children
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
export {
|
|
25
|
+
Tooltip
|
|
26
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HTMLElementBase } from "../anta_helpers";
|
|
2
|
+
import "./a-button.css";
|
|
2
3
|
class AButtonElement extends HTMLElementBase {
|
|
3
4
|
connectedCallback() {
|
|
4
5
|
if (!document.hasKeyListenerForAButton) {
|
|
@@ -70,6 +71,7 @@ function register_a_button() {
|
|
|
70
71
|
customElements.define("a-button", AButtonElement);
|
|
71
72
|
}
|
|
72
73
|
}
|
|
74
|
+
register_a_button();
|
|
73
75
|
export {
|
|
74
76
|
AButtonElement,
|
|
75
77
|
register_a_button
|
package/dist/elements/a-icon.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { HTMLElementBase } from "../anta_helpers";
|
|
2
|
+
import "./a-icon.css";
|
|
3
|
+
import "./a-icon.shapes.css";
|
|
2
4
|
class AIconElement extends HTMLElementBase {
|
|
3
5
|
}
|
|
4
6
|
function register_a_icon() {
|
|
@@ -7,6 +9,7 @@ function register_a_icon() {
|
|
|
7
9
|
customElements.define("a-icon", AIconElement);
|
|
8
10
|
}
|
|
9
11
|
}
|
|
12
|
+
register_a_icon();
|
|
10
13
|
export {
|
|
11
14
|
AIconElement,
|
|
12
15
|
register_a_icon
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HTMLElementBase } from "../anta_helpers";
|
|
2
|
+
import "./a-progress.css";
|
|
2
3
|
class AProgressElement extends HTMLElementBase {
|
|
3
4
|
static observedAttributes = ["value", "max", "tone"];
|
|
4
5
|
indicator;
|
|
@@ -60,6 +61,7 @@ function register_a_progress() {
|
|
|
60
61
|
customElements.define("a-progress", AProgressElement);
|
|
61
62
|
}
|
|
62
63
|
}
|
|
64
|
+
register_a_progress();
|
|
63
65
|
export {
|
|
64
66
|
AProgressElement,
|
|
65
67
|
register_a_progress
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import lottie from "lottie-web";
|
|
2
2
|
import { HTMLElementBase } from "../anta_helpers";
|
|
3
|
+
import "./a-sticker-animated.css";
|
|
3
4
|
class AStickerAnimatedElement extends HTMLElementBase {
|
|
4
5
|
static observedAttributes = ["animation", "paused"];
|
|
5
6
|
container;
|
|
@@ -73,6 +74,7 @@ function register_a_sticker_animated() {
|
|
|
73
74
|
customElements.define("a-sticker-animated", AStickerAnimatedElement);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
77
|
+
register_a_sticker_animated();
|
|
76
78
|
export {
|
|
77
79
|
AStickerAnimatedElement,
|
|
78
80
|
register_a_sticker_animated
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HTMLElementBase } from "../anta_helpers";
|
|
2
|
+
import "./a-sticker.css";
|
|
2
3
|
class AStickerElement extends HTMLElementBase {
|
|
3
4
|
static observedAttributes = ["svg"];
|
|
4
5
|
container;
|
|
@@ -24,6 +25,7 @@ function register_a_sticker() {
|
|
|
24
25
|
customElements.define("a-sticker", AStickerElement);
|
|
25
26
|
}
|
|
26
27
|
}
|
|
28
|
+
register_a_sticker();
|
|
27
29
|
export {
|
|
28
30
|
AStickerElement,
|
|
29
31
|
register_a_sticker
|
package/dist/elements/a-text.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HTMLElementBase } from "../anta_helpers";
|
|
2
|
+
import "./a-text.css";
|
|
2
3
|
const SHADOW_STYLE = `
|
|
3
4
|
:host {
|
|
4
5
|
display: block;
|
|
@@ -137,6 +138,7 @@ function register_a_text() {
|
|
|
137
138
|
customElements.define("a-text", ATextElement);
|
|
138
139
|
}
|
|
139
140
|
}
|
|
141
|
+
register_a_text();
|
|
140
142
|
export {
|
|
141
143
|
ATextElement,
|
|
142
144
|
register_a_text
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
@layer anta {
|
|
2
|
+
/* Before the custom element upgrades on the client, <a-tooltip> is an
|
|
3
|
+
unknown inline element and its content would flash *inside the anchor*.
|
|
4
|
+
Hide it until defined; once defined this stops matching and the shadow
|
|
5
|
+
`:host { display: contents }` governs (content renders only in the
|
|
6
|
+
popover via the slot). */
|
|
7
|
+
a-tooltip:not(:defined) {
|
|
8
|
+
display: none;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* Tooltip exposes only the box "chrome" that lives inside the shadow
|
|
12
|
+
popover and is therefore impossible to reach with plain consumer CSS.
|
|
13
|
+
The bubble's content is slotted light DOM, so its font / colour / size
|
|
14
|
+
are already styleable from the page — those are intentionally NOT
|
|
15
|
+
tokens. These custom properties inherit across the shadow boundary
|
|
16
|
+
into the popover container (see a-tooltip.ts). The host itself draws
|
|
17
|
+
nothing and stays out of layout (`:host { display: contents }` in the
|
|
18
|
+
shadow style). */
|
|
19
|
+
a-tooltip {
|
|
20
|
+
/* Frosted translucent surface (matches the legacy look): a mostly-
|
|
21
|
+
opaque white that, paired with the container's `backdrop-filter:
|
|
22
|
+
blur(8px)`, reads as a frosted bubble over the page. --bg-1 is
|
|
23
|
+
#ffffff in light / #000000 in dark, so this flips to a dark frost
|
|
24
|
+
automatically (alpha is dialed down in the .dark override). */
|
|
25
|
+
--tooltip-bg: color-mix(in oklch, var(--bg-1) 80%, transparent);
|
|
26
|
+
--tooltip-shadow:
|
|
27
|
+
0 1px 8px color-mix(in oklch, var(--text-1) 15%, transparent),
|
|
28
|
+
0 0 1px color-mix(in oklch, var(--text-1) 50%, transparent);
|
|
29
|
+
--tooltip-radius: 3px;
|
|
30
|
+
--tooltip-max-width: min(calc(100vw - 20px), 80ch);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Dark: a slightly more transparent black frost. A solid black cast shadow
|
|
34
|
+
for lift, plus an inset 1px white ring so the bubble's edge stays crisp
|
|
35
|
+
against dark page content. */
|
|
36
|
+
.dark a-tooltip {
|
|
37
|
+
--tooltip-bg: color-mix(in oklch, var(--bg-1) 70%, transparent);
|
|
38
|
+
--tooltip-shadow:
|
|
39
|
+
0 2px 16px color-mix(in oklch, black 70%, transparent),
|
|
40
|
+
inset 0 0 0 1px color-mix(in oklch, white 25%, transparent);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { HTMLElementBase } from '../anta_helpers';
|
|
2
|
+
import './a-tooltip.css';
|
|
3
|
+
export declare class ATooltipElement extends HTMLElementBase {
|
|
4
|
+
static observedAttributes: string[];
|
|
5
|
+
/** Shadow-internal popover surface — the only thing we ever mutate. */
|
|
6
|
+
private container;
|
|
7
|
+
private anchor;
|
|
8
|
+
listening: boolean;
|
|
9
|
+
private shown;
|
|
10
|
+
private lastMouse?;
|
|
11
|
+
private debouncedShow?;
|
|
12
|
+
private teardown?;
|
|
13
|
+
private closeTimer?;
|
|
14
|
+
private fading;
|
|
15
|
+
private fadeTimer?;
|
|
16
|
+
private docMoveBound;
|
|
17
|
+
constructor();
|
|
18
|
+
connectedCallback(): void;
|
|
19
|
+
disconnectedCallback(): void;
|
|
20
|
+
attributeChangedCallback(name: string): void;
|
|
21
|
+
/** (Re)build the show debounce with the CURRENT `delay` (rebuilt when the
|
|
22
|
+
* `delay` attribute changes). Re-armed on each hover move (trailing), and
|
|
23
|
+
* fed the latest cursor event, so it shows at the cursor and so moving back
|
|
24
|
+
* onto an anchor after the tooltip was dismissed re-arms it. */
|
|
25
|
+
private makeDebouncedShow;
|
|
26
|
+
/** The element's OWN window / document. The class may be defined in a
|
|
27
|
+
* different realm than the element lives in (e.g. the docs playground
|
|
28
|
+
* renders into an iframe but reuses the parent page's element class), so
|
|
29
|
+
* the module-global `window`/`document` can point at the wrong frame.
|
|
30
|
+
* Everything viewport- or document-scoped (clamping, scroll/key/move
|
|
31
|
+
* listeners) must go through these so it's correct in any frame. */
|
|
32
|
+
private get view();
|
|
33
|
+
private get doc();
|
|
34
|
+
private get isInteractive();
|
|
35
|
+
/** Pinned under the anchor (no cursor-following). Interactive implies this —
|
|
36
|
+
* you can't move into a bubble that's chasing the cursor. */
|
|
37
|
+
private get isStatic();
|
|
38
|
+
private get prefersTop();
|
|
39
|
+
private get delay();
|
|
40
|
+
private positionToTarget;
|
|
41
|
+
private positionToMouse;
|
|
42
|
+
private position;
|
|
43
|
+
show: (e?: MouseEvent) => void;
|
|
44
|
+
hide: () => void;
|
|
45
|
+
/** While shown, track the cursor even after it has left the anchor (during
|
|
46
|
+
* the close delay). Cursor-following only — static/interactive bubbles
|
|
47
|
+
* stay pinned. */
|
|
48
|
+
private onDocMove;
|
|
49
|
+
/** Hide after CLOSE_DELAY unless something cancels it first (re-enter, or
|
|
50
|
+
* another tooltip claiming the slot). Lets the bubble bridge the gap to a
|
|
51
|
+
* neighbouring anchor — and survive the trip into an interactive bubble. */
|
|
52
|
+
private scheduleHide;
|
|
53
|
+
private cancelHide;
|
|
54
|
+
private onKeyDown;
|
|
55
|
+
/** Open now if another tooltip is hot (skip delay), else (re)arm the delayed
|
|
56
|
+
* show with the latest cursor event. */
|
|
57
|
+
private trigger;
|
|
58
|
+
setupListeners(): void;
|
|
59
|
+
teardownListeners(): void;
|
|
60
|
+
}
|
|
61
|
+
export declare function register_a_tooltip(): void;
|
|
@@ -0,0 +1,411 @@
|
|
|
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
|
+
let currentOpen = null;
|
|
12
|
+
let graceTimer;
|
|
13
|
+
function graceActive() {
|
|
14
|
+
return graceTimer !== void 0;
|
|
15
|
+
}
|
|
16
|
+
function isHot() {
|
|
17
|
+
return currentOpen !== null || graceActive();
|
|
18
|
+
}
|
|
19
|
+
function clearGrace() {
|
|
20
|
+
if (graceTimer !== void 0) {
|
|
21
|
+
clearTimeout(graceTimer);
|
|
22
|
+
graceTimer = void 0;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function claimOpen(el) {
|
|
26
|
+
if (currentOpen && currentOpen !== el) currentOpen.hide();
|
|
27
|
+
currentOpen = el;
|
|
28
|
+
clearGrace();
|
|
29
|
+
}
|
|
30
|
+
function releaseOpen(el) {
|
|
31
|
+
if (currentOpen !== el) return;
|
|
32
|
+
currentOpen = null;
|
|
33
|
+
clearGrace();
|
|
34
|
+
graceTimer = setTimeout(() => {
|
|
35
|
+
graceTimer = void 0;
|
|
36
|
+
}, GRACE_MS);
|
|
37
|
+
}
|
|
38
|
+
const anchorToTooltip = /* @__PURE__ */ new WeakMap();
|
|
39
|
+
function handleIntersection(entries) {
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
const tooltip = anchorToTooltip.get(entry.target);
|
|
42
|
+
if (!tooltip) continue;
|
|
43
|
+
if (!tooltip.listening && entry.isIntersecting) {
|
|
44
|
+
requestAnimationFrame(() => tooltip.setupListeners());
|
|
45
|
+
} else if (tooltip.listening && !entry.isIntersecting) {
|
|
46
|
+
requestAnimationFrame(() => tooltip.teardownListeners());
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const lazyObserver = typeof IntersectionObserver !== "undefined" ? new IntersectionObserver(handleIntersection, { root: null, rootMargin: "0px", threshold: 0 }) : null;
|
|
51
|
+
class ATooltipElement extends HTMLElementBase {
|
|
52
|
+
// Observe `delay` so changing it at runtime — e.g. the docs playground
|
|
53
|
+
// patches the attribute on the live element — rebuilds the show debounce
|
|
54
|
+
// with the new value instead of keeping the one captured at setup.
|
|
55
|
+
static observedAttributes = ["delay"];
|
|
56
|
+
/** Shadow-internal popover surface — the only thing we ever mutate. */
|
|
57
|
+
container;
|
|
58
|
+
anchor = null;
|
|
59
|
+
listening = false;
|
|
60
|
+
shown = false;
|
|
61
|
+
lastMouse;
|
|
62
|
+
debouncedShow;
|
|
63
|
+
teardown;
|
|
64
|
+
closeTimer;
|
|
65
|
+
fading = false;
|
|
66
|
+
fadeTimer;
|
|
67
|
+
docMoveBound = false;
|
|
68
|
+
constructor() {
|
|
69
|
+
super();
|
|
70
|
+
const shadow = this.attachShadow({ mode: "open" });
|
|
71
|
+
const style = document.createElement("style");
|
|
72
|
+
style.textContent = `
|
|
73
|
+
:host { display: contents; }
|
|
74
|
+
|
|
75
|
+
.container {
|
|
76
|
+
--_dur: ${FADE_MS}ms;
|
|
77
|
+
|
|
78
|
+
position: fixed;
|
|
79
|
+
left: 0;
|
|
80
|
+
top: 0;
|
|
81
|
+
margin: 0;
|
|
82
|
+
box-sizing: border-box;
|
|
83
|
+
width: fit-content;
|
|
84
|
+
max-width: var(--tooltip-max-width, min(calc(100vw - 20px), 80ch));
|
|
85
|
+
max-height: calc(100vh - 20px);
|
|
86
|
+
overflow: clip;
|
|
87
|
+
pointer-events: none;
|
|
88
|
+
text-align: left;
|
|
89
|
+
|
|
90
|
+
background: var(--tooltip-bg, Canvas);
|
|
91
|
+
color: var(--text-1, CanvasText);
|
|
92
|
+
box-shadow: var(--tooltip-shadow, 0 1px 8px rgba(0, 0, 0, 0.2));
|
|
93
|
+
backdrop-filter: blur(8px);
|
|
94
|
+
padding: 5px 8px;
|
|
95
|
+
border: none;
|
|
96
|
+
border-radius: var(--tooltip-radius, 3px);
|
|
97
|
+
outline: none;
|
|
98
|
+
|
|
99
|
+
font-size: 14px;
|
|
100
|
+
line-height: 130%;
|
|
101
|
+
font-weight: 400;
|
|
102
|
+
white-space: break-spaces;
|
|
103
|
+
word-break: break-word;
|
|
104
|
+
overflow-wrap: break-word;
|
|
105
|
+
|
|
106
|
+
/* Clean enter/exit fade. allow-discrete keeps the bubble rendered
|
|
107
|
+
through its fade-out after hidePopover(), and @starting-style
|
|
108
|
+
gives every open a from-opacity:0 \u2014 so the first paint at a
|
|
109
|
+
not-yet-computed transform is invisible (no flash at a stale
|
|
110
|
+
spot), and re-appearing is always clean. */
|
|
111
|
+
opacity: 0;
|
|
112
|
+
transition:
|
|
113
|
+
opacity var(--_dur) ease,
|
|
114
|
+
overlay var(--_dur) ease allow-discrete,
|
|
115
|
+
display var(--_dur) ease allow-discrete;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.container:popover-open { opacity: 1; }
|
|
119
|
+
|
|
120
|
+
@starting-style {
|
|
121
|
+
.container:popover-open { opacity: 0; }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Interactive tooltips accept pointer events so their content (links,
|
|
125
|
+
buttons) is clickable; the default click-through bubble does not. */
|
|
126
|
+
:host([interactive]) .container { pointer-events: auto; }
|
|
127
|
+
`;
|
|
128
|
+
this.container = document.createElement("div");
|
|
129
|
+
this.container.className = "container";
|
|
130
|
+
this.container.setAttribute("popover", "manual");
|
|
131
|
+
this.container.setAttribute("role", "tooltip");
|
|
132
|
+
this.container.append(document.createElement("slot"));
|
|
133
|
+
this.container.addEventListener("mouseenter", () => {
|
|
134
|
+
if (this.isInteractive) this.cancelHide();
|
|
135
|
+
});
|
|
136
|
+
this.container.addEventListener("mouseleave", () => {
|
|
137
|
+
if (this.isInteractive && this.shown) this.scheduleHide();
|
|
138
|
+
});
|
|
139
|
+
shadow.append(style, this.container);
|
|
140
|
+
}
|
|
141
|
+
connectedCallback() {
|
|
142
|
+
const parent = this.parentElement;
|
|
143
|
+
if (!parent) return;
|
|
144
|
+
this.anchor = parent;
|
|
145
|
+
anchorToTooltip.set(parent, this);
|
|
146
|
+
lazyObserver?.observe(parent);
|
|
147
|
+
}
|
|
148
|
+
disconnectedCallback() {
|
|
149
|
+
this.hide();
|
|
150
|
+
if (this.fadeTimer !== void 0) {
|
|
151
|
+
clearTimeout(this.fadeTimer);
|
|
152
|
+
this.fadeTimer = void 0;
|
|
153
|
+
}
|
|
154
|
+
this.fading = false;
|
|
155
|
+
if (this.docMoveBound) {
|
|
156
|
+
this.doc.removeEventListener("mousemove", this.onDocMove);
|
|
157
|
+
this.docMoveBound = false;
|
|
158
|
+
}
|
|
159
|
+
this.teardownListeners();
|
|
160
|
+
if (this.anchor) {
|
|
161
|
+
if (anchorToTooltip.get(this.anchor) === this) {
|
|
162
|
+
anchorToTooltip.delete(this.anchor);
|
|
163
|
+
lazyObserver?.unobserve(this.anchor);
|
|
164
|
+
}
|
|
165
|
+
this.anchor = null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
attributeChangedCallback(name) {
|
|
169
|
+
if (name === "delay" && this.listening) this.makeDebouncedShow();
|
|
170
|
+
}
|
|
171
|
+
/** (Re)build the show debounce with the CURRENT `delay` (rebuilt when the
|
|
172
|
+
* `delay` attribute changes). Re-armed on each hover move (trailing), and
|
|
173
|
+
* fed the latest cursor event, so it shows at the cursor and so moving back
|
|
174
|
+
* onto an anchor after the tooltip was dismissed re-arms it. */
|
|
175
|
+
makeDebouncedShow() {
|
|
176
|
+
this.debouncedShow?.cancel();
|
|
177
|
+
this.debouncedShow = debounce((e) => this.show(e), this.delay);
|
|
178
|
+
}
|
|
179
|
+
/** The element's OWN window / document. The class may be defined in a
|
|
180
|
+
* different realm than the element lives in (e.g. the docs playground
|
|
181
|
+
* renders into an iframe but reuses the parent page's element class), so
|
|
182
|
+
* the module-global `window`/`document` can point at the wrong frame.
|
|
183
|
+
* Everything viewport- or document-scoped (clamping, scroll/key/move
|
|
184
|
+
* listeners) must go through these so it's correct in any frame. */
|
|
185
|
+
get view() {
|
|
186
|
+
return this.ownerDocument?.defaultView ?? window;
|
|
187
|
+
}
|
|
188
|
+
get doc() {
|
|
189
|
+
return this.ownerDocument ?? document;
|
|
190
|
+
}
|
|
191
|
+
get isInteractive() {
|
|
192
|
+
return this.hasAttribute("interactive");
|
|
193
|
+
}
|
|
194
|
+
/** Pinned under the anchor (no cursor-following). Interactive implies this —
|
|
195
|
+
* you can't move into a bubble that's chasing the cursor. */
|
|
196
|
+
get isStatic() {
|
|
197
|
+
return this.hasAttribute("static") || this.isInteractive;
|
|
198
|
+
}
|
|
199
|
+
get prefersTop() {
|
|
200
|
+
return this.getAttribute("placement") === "top";
|
|
201
|
+
}
|
|
202
|
+
get delay() {
|
|
203
|
+
const attr = this.getAttribute("delay");
|
|
204
|
+
if (attr == null) return DEFAULT_DELAY;
|
|
205
|
+
const n = parseInt(attr, 10);
|
|
206
|
+
return Number.isFinite(n) ? n : DEFAULT_DELAY;
|
|
207
|
+
}
|
|
208
|
+
// --- positioning (sets only the shadow container's own transform) ---
|
|
209
|
+
positionToTarget = () => {
|
|
210
|
+
requestAnimationFrame(() => {
|
|
211
|
+
if (!this.anchor || !this.shown) return;
|
|
212
|
+
const a = this.anchor.getBoundingClientRect();
|
|
213
|
+
const box = this.container.getBoundingClientRect();
|
|
214
|
+
const view = this.view;
|
|
215
|
+
const vw = view.innerWidth;
|
|
216
|
+
const vh = view.innerHeight;
|
|
217
|
+
let left = a.left;
|
|
218
|
+
if (left + box.width > vw) left = vw - box.width - MARGIN;
|
|
219
|
+
left = Math.max(MARGIN, left);
|
|
220
|
+
let top;
|
|
221
|
+
if (this.prefersTop) {
|
|
222
|
+
top = a.top - box.height - MARGIN;
|
|
223
|
+
if (top < MARGIN) top = a.bottom + MARGIN;
|
|
224
|
+
} else {
|
|
225
|
+
top = a.bottom + MARGIN;
|
|
226
|
+
if (top + box.height > vh) top = a.top - box.height - MARGIN;
|
|
227
|
+
}
|
|
228
|
+
top = Math.max(MARGIN, top);
|
|
229
|
+
this.container.style.transform = `translate(${Math.round(left)}px, ${Math.round(top)}px)`;
|
|
230
|
+
});
|
|
231
|
+
};
|
|
232
|
+
positionToMouse = (e) => {
|
|
233
|
+
requestAnimationFrame(() => {
|
|
234
|
+
if (!this.shown && !this.fading) return;
|
|
235
|
+
const box = this.container.getBoundingClientRect();
|
|
236
|
+
const view = this.view;
|
|
237
|
+
const vw = view.innerWidth;
|
|
238
|
+
const vh = view.innerHeight;
|
|
239
|
+
let left = e.clientX - PADDING_X;
|
|
240
|
+
if (left + box.width > vw) left = vw - box.width - MARGIN;
|
|
241
|
+
left = Math.max(MARGIN, left);
|
|
242
|
+
let top;
|
|
243
|
+
if (this.prefersTop) {
|
|
244
|
+
top = e.clientY - box.height - MARGIN * 2;
|
|
245
|
+
if (top < MARGIN) top = e.clientY + CURSOR_SIZE;
|
|
246
|
+
} else {
|
|
247
|
+
top = e.clientY + CURSOR_SIZE;
|
|
248
|
+
if (top + box.height > vh) top = e.clientY - box.height - MARGIN * 2;
|
|
249
|
+
}
|
|
250
|
+
top = Math.max(MARGIN, top);
|
|
251
|
+
this.container.style.transform = `translate(${Math.round(left)}px, ${Math.round(top)}px)`;
|
|
252
|
+
});
|
|
253
|
+
};
|
|
254
|
+
position(e) {
|
|
255
|
+
if (!this.isStatic && e) this.positionToMouse(e);
|
|
256
|
+
else this.positionToTarget();
|
|
257
|
+
}
|
|
258
|
+
// --- show / hide ---
|
|
259
|
+
show = (e) => {
|
|
260
|
+
if (!this.anchor) return;
|
|
261
|
+
this.cancelHide();
|
|
262
|
+
if (currentOpen && currentOpen !== this && this.anchor.contains(currentOpen.anchor)) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
claimOpen(this);
|
|
266
|
+
if (!this.shown) {
|
|
267
|
+
this.shown = true;
|
|
268
|
+
this.fading = false;
|
|
269
|
+
if (this.fadeTimer !== void 0) {
|
|
270
|
+
clearTimeout(this.fadeTimer);
|
|
271
|
+
this.fadeTimer = void 0;
|
|
272
|
+
}
|
|
273
|
+
this.container.showPopover();
|
|
274
|
+
this.view.addEventListener("scroll", this.hide, { capture: true, passive: true });
|
|
275
|
+
this.doc.addEventListener("keydown", this.onKeyDown, true);
|
|
276
|
+
if (!this.docMoveBound) {
|
|
277
|
+
this.doc.addEventListener("mousemove", this.onDocMove);
|
|
278
|
+
this.docMoveBound = true;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
this.position(e);
|
|
282
|
+
};
|
|
283
|
+
hide = () => {
|
|
284
|
+
this.cancelHide();
|
|
285
|
+
if (!this.shown) return;
|
|
286
|
+
this.shown = false;
|
|
287
|
+
this.container.hidePopover();
|
|
288
|
+
this.view.removeEventListener("scroll", this.hide, { capture: true });
|
|
289
|
+
this.doc.removeEventListener("keydown", this.onKeyDown, true);
|
|
290
|
+
this.fading = true;
|
|
291
|
+
if (this.fadeTimer !== void 0) clearTimeout(this.fadeTimer);
|
|
292
|
+
this.fadeTimer = setTimeout(() => {
|
|
293
|
+
this.fading = false;
|
|
294
|
+
this.fadeTimer = void 0;
|
|
295
|
+
if (this.docMoveBound) {
|
|
296
|
+
this.doc.removeEventListener("mousemove", this.onDocMove);
|
|
297
|
+
this.docMoveBound = false;
|
|
298
|
+
}
|
|
299
|
+
}, FADE_MS);
|
|
300
|
+
releaseOpen(this);
|
|
301
|
+
};
|
|
302
|
+
/** While shown, track the cursor even after it has left the anchor (during
|
|
303
|
+
* the close delay). Cursor-following only — static/interactive bubbles
|
|
304
|
+
* stay pinned. */
|
|
305
|
+
onDocMove = (e) => {
|
|
306
|
+
if ((this.shown || this.fading) && !this.isStatic) {
|
|
307
|
+
this.lastMouse = e;
|
|
308
|
+
this.positionToMouse(e);
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
/** Hide after CLOSE_DELAY unless something cancels it first (re-enter, or
|
|
312
|
+
* another tooltip claiming the slot). Lets the bubble bridge the gap to a
|
|
313
|
+
* neighbouring anchor — and survive the trip into an interactive bubble. */
|
|
314
|
+
scheduleHide = () => {
|
|
315
|
+
this.cancelHide();
|
|
316
|
+
this.closeTimer = setTimeout(() => {
|
|
317
|
+
this.closeTimer = void 0;
|
|
318
|
+
this.hide();
|
|
319
|
+
}, CLOSE_DELAY);
|
|
320
|
+
};
|
|
321
|
+
cancelHide() {
|
|
322
|
+
if (this.closeTimer !== void 0) {
|
|
323
|
+
clearTimeout(this.closeTimer);
|
|
324
|
+
this.closeTimer = void 0;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
onKeyDown = (e) => {
|
|
328
|
+
if (e.key === "Escape") this.hide();
|
|
329
|
+
};
|
|
330
|
+
/** Open now if another tooltip is hot (skip delay), else (re)arm the delayed
|
|
331
|
+
* show with the latest cursor event. */
|
|
332
|
+
trigger(e) {
|
|
333
|
+
if (isHot()) {
|
|
334
|
+
this.debouncedShow?.cancel();
|
|
335
|
+
this.show(e);
|
|
336
|
+
} else {
|
|
337
|
+
this.debouncedShow?.(e);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// --- lazy listener wiring (called by the intersection observer) ---
|
|
341
|
+
setupListeners() {
|
|
342
|
+
if (this.listening || !this.anchor) {
|
|
343
|
+
this.listening = true;
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const anchor = this.anchor;
|
|
347
|
+
const view = this.view;
|
|
348
|
+
const doc = this.doc;
|
|
349
|
+
this.makeDebouncedShow();
|
|
350
|
+
const onMouseMove = (e) => {
|
|
351
|
+
this.lastMouse = e;
|
|
352
|
+
if (this.shown) {
|
|
353
|
+
if (!this.isStatic) this.positionToMouse(e);
|
|
354
|
+
} else {
|
|
355
|
+
this.trigger(e);
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
const onLeave = () => {
|
|
359
|
+
this.debouncedShow?.cancel();
|
|
360
|
+
anchor.removeEventListener("mousemove", onMouseMove);
|
|
361
|
+
anchor.removeEventListener("mouseleave", onLeave);
|
|
362
|
+
anchor.removeEventListener("blur", onLeave);
|
|
363
|
+
view.removeEventListener("pagehide", onLeave);
|
|
364
|
+
doc.removeEventListener("visibilitychange", onLeave);
|
|
365
|
+
this.scheduleHide();
|
|
366
|
+
};
|
|
367
|
+
const onEnter = (e) => {
|
|
368
|
+
this.lastMouse = e;
|
|
369
|
+
anchor.addEventListener("mousemove", onMouseMove);
|
|
370
|
+
anchor.addEventListener("mouseleave", onLeave);
|
|
371
|
+
view.addEventListener("pagehide", onLeave);
|
|
372
|
+
doc.addEventListener("visibilitychange", onLeave);
|
|
373
|
+
this.trigger(e);
|
|
374
|
+
};
|
|
375
|
+
const onFocus = () => {
|
|
376
|
+
anchor.addEventListener("blur", onLeave);
|
|
377
|
+
view.addEventListener("pagehide", onLeave);
|
|
378
|
+
doc.addEventListener("visibilitychange", onLeave);
|
|
379
|
+
this.trigger();
|
|
380
|
+
};
|
|
381
|
+
anchor.addEventListener("mouseenter", onEnter);
|
|
382
|
+
anchor.addEventListener("focus", onFocus);
|
|
383
|
+
this.teardown = () => {
|
|
384
|
+
this.debouncedShow?.cancel();
|
|
385
|
+
anchor.removeEventListener("mousemove", onMouseMove);
|
|
386
|
+
anchor.removeEventListener("mouseenter", onEnter);
|
|
387
|
+
anchor.removeEventListener("mouseleave", onLeave);
|
|
388
|
+
anchor.removeEventListener("focus", onFocus);
|
|
389
|
+
anchor.removeEventListener("blur", onLeave);
|
|
390
|
+
view.removeEventListener("pagehide", onLeave);
|
|
391
|
+
doc.removeEventListener("visibilitychange", onLeave);
|
|
392
|
+
this.listening = false;
|
|
393
|
+
};
|
|
394
|
+
this.listening = true;
|
|
395
|
+
}
|
|
396
|
+
teardownListeners() {
|
|
397
|
+
this.teardown?.();
|
|
398
|
+
this.teardown = void 0;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
function register_a_tooltip() {
|
|
402
|
+
if (typeof customElements === "undefined") return;
|
|
403
|
+
if (!customElements.get("a-tooltip")) {
|
|
404
|
+
customElements.define("a-tooltip", ATooltipElement);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
register_a_tooltip();
|
|
408
|
+
export {
|
|
409
|
+
ATooltipElement,
|
|
410
|
+
register_a_tooltip
|
|
411
|
+
};
|
package/dist/elements/index.d.ts
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
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 (e.g. it won't drag in
|
|
12
|
+
* `lottie-web`, which only `a-sticker-animated` needs).
|
|
13
|
+
*
|
|
14
|
+
* Must only be imported client-side — registration is guarded against missing
|
|
15
|
+
* `customElements` (SSR), but there's no reason to load it server-side.
|
|
16
|
+
*/
|
|
9
17
|
export { AProgressElement, register_a_progress } from './a-progress';
|
|
10
18
|
export { ATextElement, register_a_text } from './a-text';
|
|
11
19
|
export { AIconElement, register_a_icon } from './a-icon';
|
|
12
20
|
export { AButtonElement, register_a_button } from './a-button';
|
|
13
21
|
export { AStickerElement, register_a_sticker } from './a-sticker';
|
|
14
22
|
export { AStickerAnimatedElement, register_a_sticker_animated } from './a-sticker-animated';
|
|
23
|
+
export { ATooltipElement, register_a_tooltip } from './a-tooltip';
|
|
24
|
+
import './a-title.css';
|
package/dist/elements/index.js
CHANGED
|
@@ -1,31 +1,11 @@
|
|
|
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 { register_a_sticker } from "./a-sticker";
|
|
6
|
-
import { register_a_sticker_animated } from "./a-sticker-animated";
|
|
7
|
-
import "./a-
|
|
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 { AStickerElement, register_a_sticker } from "./a-sticker";
|
|
6
|
+
import { AStickerAnimatedElement, register_a_sticker_animated } from "./a-sticker-animated";
|
|
7
|
+
import { ATooltipElement, register_a_tooltip } from "./a-tooltip";
|
|
9
8
|
import "./a-title.css";
|
|
10
|
-
import "./a-icon.css";
|
|
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
|
-
}
|
|
29
9
|
export {
|
|
30
10
|
AButtonElement,
|
|
31
11
|
AIconElement,
|
|
@@ -33,10 +13,12 @@ export {
|
|
|
33
13
|
AStickerAnimatedElement,
|
|
34
14
|
AStickerElement,
|
|
35
15
|
ATextElement,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
16
|
+
ATooltipElement,
|
|
17
|
+
register_a_button,
|
|
18
|
+
register_a_icon,
|
|
19
|
+
register_a_progress,
|
|
20
|
+
register_a_sticker,
|
|
21
|
+
register_a_sticker_animated,
|
|
22
|
+
register_a_text,
|
|
23
|
+
register_a_tooltip
|
|
42
24
|
};
|
package/dist/general_types.d.ts
CHANGED
|
@@ -76,7 +76,7 @@ export interface ATextAttributes extends BaseAttributes {
|
|
|
76
76
|
/** Type scale. `small` = 13/16, `medium` (default) = 15/20, `large` = 17/24. */
|
|
77
77
|
size?: 'small' | 'medium' | 'large';
|
|
78
78
|
/** Render as inline-block instead of the default block. */
|
|
79
|
-
inline?: boolean |
|
|
79
|
+
inline?: boolean | '';
|
|
80
80
|
/** Truncate to N lines with a trailing ellipsis. The attribute value
|
|
81
81
|
* carries the line count (e.g. `"1"`, `"3"`); the count is also
|
|
82
82
|
* available via the `--line-clamp` CSS custom property set inline. */
|
|
@@ -84,7 +84,7 @@ export interface ATextAttributes extends BaseAttributes {
|
|
|
84
84
|
/** Marks the host as expandable when paired with `truncate`. Adds
|
|
85
85
|
* the fade-out mask; the JSX wrapper renders the chevron and owns
|
|
86
86
|
* the click/keyboard expansion logic. */
|
|
87
|
-
expandable?: boolean |
|
|
87
|
+
expandable?: boolean | '';
|
|
88
88
|
/** ARIA disclosure state, mirrors the JSX wrapper's `expanded` flag. */
|
|
89
89
|
'aria-expanded'?: boolean | 'true' | 'false';
|
|
90
90
|
}
|
|
@@ -173,6 +173,25 @@ export interface AIconAttributes extends BaseAttributes {
|
|
|
173
173
|
/** Hides decorative icons from screen readers. */
|
|
174
174
|
'aria-hidden'?: 'true' | 'false' | boolean;
|
|
175
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Attributes for the `<a-tooltip>` custom element. Placed as a child of the
|
|
178
|
+
* element it annotates (content as children). For the typed JSX wrapper use
|
|
179
|
+
* `Tooltip` from `@antadesign/anta`.
|
|
180
|
+
*/
|
|
181
|
+
export interface ATooltipAttributes extends BaseAttributes {
|
|
182
|
+
/** Show delay in milliseconds. Never use `0` — use ~`50`. Defaults to 250. */
|
|
183
|
+
delay?: number | string;
|
|
184
|
+
/** Preferred side; auto-flips when there's no room. Defaults to `'bottom'`. */
|
|
185
|
+
placement?: 'top' | 'bottom';
|
|
186
|
+
/** Pin under the anchor instead of following the cursor. Presence-based
|
|
187
|
+
* (`''` on, omit off). */
|
|
188
|
+
static?: boolean | '';
|
|
189
|
+
/** Make the bubble hoverable/clickable (pointer events on, stays open while
|
|
190
|
+
* hovered). Implies `static`. Presence-based (`''` on, omit off). */
|
|
191
|
+
interactive?: boolean | '';
|
|
192
|
+
/** HTML `id`. */
|
|
193
|
+
id?: string;
|
|
194
|
+
}
|
|
176
195
|
/**
|
|
177
196
|
* Attributes for the `<a-button>` custom element. For the typed JSX
|
|
178
197
|
* wrapper use `Button` from `@antadesign/anta`.
|
|
@@ -188,13 +207,13 @@ export interface AButtonAttributes extends BaseAttributes {
|
|
|
188
207
|
size?: 'small' | 'medium' | 'large';
|
|
189
208
|
/** Drop outer padding to zero. Only takes effect on `priority="quaternary"`.
|
|
190
209
|
* Presence-based: `''` (or any value) turns it on; omit to turn off. */
|
|
191
|
-
paddingless?:
|
|
210
|
+
paddingless?: boolean | '';
|
|
192
211
|
/** Loading state. Presence-based (`''` on, omit off). */
|
|
193
|
-
loading?:
|
|
212
|
+
loading?: boolean | '';
|
|
194
213
|
/** Disabled state. Presence-based (`''` on, omit off). */
|
|
195
|
-
disabled?:
|
|
214
|
+
disabled?: boolean | '';
|
|
196
215
|
/** Toggled-on / pressed state. Presence-based (`''` on, omit off). */
|
|
197
|
-
selected?:
|
|
216
|
+
selected?: boolean | '';
|
|
198
217
|
/** Submit/reset semantics. */
|
|
199
218
|
type?: 'button' | 'submit' | 'reset';
|
|
200
219
|
/** Associate with a form by id when not nested inside it. */
|
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,8 @@ export { Sticker } from './components/Sticker';
|
|
|
31
31
|
export type { StickerProps } from './components/Sticker';
|
|
32
32
|
export { StickerAnimated } from './components/StickerAnimated';
|
|
33
33
|
export type { StickerAnimatedProps } from './components/StickerAnimated';
|
|
34
|
+
export { Tooltip } from './components/Tooltip';
|
|
35
|
+
export type { TooltipProps } from './components/Tooltip';
|
|
34
36
|
export type { BaseProps, BaseAttributes } from './general_types';
|
|
35
37
|
export { configure } from './jsx-runtime';
|
|
36
38
|
/**
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { Button } from "./components/Button";
|
|
|
6
6
|
import { ICON_SHAPES, ICON_SYNONYMS } from "./elements/a-icon.shapes";
|
|
7
7
|
import { Sticker } from "./components/Sticker";
|
|
8
8
|
import { StickerAnimated } from "./components/StickerAnimated";
|
|
9
|
+
import { Tooltip } from "./components/Tooltip";
|
|
9
10
|
import { configure } from "./jsx-runtime";
|
|
10
11
|
export {
|
|
11
12
|
Button,
|
|
@@ -17,5 +18,6 @@ export {
|
|
|
17
18
|
StickerAnimated,
|
|
18
19
|
Text,
|
|
19
20
|
Title,
|
|
21
|
+
Tooltip,
|
|
20
22
|
configure
|
|
21
23
|
};
|
package/dist/jsx-runtime.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare function configure(jsx: JsxFunction, Fragment?: ComponentType): v
|
|
|
22
22
|
export declare function jsx(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
|
|
23
23
|
export declare function jsxs(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
|
|
24
24
|
export { _Fragment as Fragment };
|
|
25
|
-
import type { AProgressAttributes, ATextAttributes, ATitleAttributes, AIconAttributes, AButtonAttributes, AStickerAttributes, AStickerAnimatedAttributes, BaseAttributes } from './general_types';
|
|
25
|
+
import type { AProgressAttributes, ATextAttributes, ATitleAttributes, AIconAttributes, AButtonAttributes, AStickerAttributes, AStickerAnimatedAttributes, ATooltipAttributes, BaseAttributes } from './general_types';
|
|
26
26
|
export declare namespace JSX {
|
|
27
27
|
type IntrinsicElements = React.JSX.IntrinsicElements & {
|
|
28
28
|
'a-progress': AProgressAttributes;
|
|
@@ -37,5 +37,6 @@ export declare namespace JSX {
|
|
|
37
37
|
'a-button-label': BaseAttributes;
|
|
38
38
|
'a-sticker': AStickerAttributes;
|
|
39
39
|
'a-sticker-animated': AStickerAnimatedAttributes;
|
|
40
|
+
'a-tooltip': ATooltipAttributes;
|
|
40
41
|
};
|
|
41
42
|
}
|
package/dist/reset.css
CHANGED
|
@@ -108,9 +108,14 @@
|
|
|
108
108
|
/* Global link defaults. Hairline underline at 75% alpha;
|
|
109
109
|
underline goes to currentColor (100%) and 1px on hover. Color
|
|
110
110
|
comes from --link-color tokens, which auto-flip in dark mode.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
`:not([role="button"])` excludes anchor-buttons (`<a role="button">`,
|
|
112
|
+
e.g. `<Button href>`): `a:link`/`a:visited` are pseudo-classes with the
|
|
113
|
+
same (0,1,1) specificity as `a[role="button"]`, so without the exclusion
|
|
114
|
+
they'd tie and win on source order, giving buttons link colour +
|
|
115
|
+
underline. Other contexts (nav, headings) still override as needed. */
|
|
116
|
+
a:not([role="button"]),
|
|
117
|
+
a:not([role="button"]):link,
|
|
118
|
+
a:not([role="button"]):visited {
|
|
114
119
|
color: var(--link-color);
|
|
115
120
|
text-decoration: underline;
|
|
116
121
|
text-decoration-style: solid;
|
|
@@ -121,14 +126,14 @@
|
|
|
121
126
|
/* Hover only on real-pointer devices — gating avoids the sticky hover
|
|
122
127
|
color that lingers after a tap on touch screens. */
|
|
123
128
|
@media (hover: hover) and (pointer: fine) {
|
|
124
|
-
a:hover {
|
|
129
|
+
a:not([role="button"]):hover {
|
|
125
130
|
color: var(--link-color-hover);
|
|
126
131
|
/* Underline color is left as the resting hairline (the base rule's
|
|
127
132
|
`currentColor` mix) — only the thickness grows on hover. */
|
|
128
133
|
text-decoration-thickness: 1px;
|
|
129
134
|
}
|
|
130
135
|
}
|
|
131
|
-
a:active {
|
|
136
|
+
a:not([role="button"]):active {
|
|
132
137
|
text-decoration-color: color-mix(in srgb, currentColor 75%, transparent);
|
|
133
138
|
}
|
|
134
139
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antadesign/anta",
|
|
3
|
-
"version": "0.1.1-dev.
|
|
3
|
+
"version": "0.1.1-dev.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"clsx": "^2.1.0",
|
|
67
|
+
"es-toolkit": "^1.47.0",
|
|
67
68
|
"lottie-web": "^5.13.0"
|
|
68
69
|
},
|
|
69
70
|
"peerDependencies": {
|