@antadesign/anta 0.3.31 → 0.3.32
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/box-types.d.ts +12 -1
- package/dist/bundle.css +1 -1
- package/dist/bundle.js +125 -60
- package/dist/components/Box.d.ts +18 -6
- package/dist/components/Box.js +4 -0
- package/dist/components/Expander.d.ts +17 -9
- package/dist/components/Expander.js +14 -1
- package/dist/elements/a-box.css +1 -1
- package/dist/elements/a-box.d.ts +2 -0
- package/dist/elements/a-box.js +74 -32
- package/dist/elements/a-dialog.js +2 -0
- package/dist/elements/a-expander.css +1 -1
- package/dist/elements/a-expander.js +118 -39
- package/dist/elements/a-menu.js +40 -3
- package/dist/general_types.d.ts +18 -6
- package/dist/index.d.ts +1 -1
- package/docs/changelog.md +34 -0
- package/docs/components/box.md +81 -24
- package/docs/components/expander.md +88 -47
- package/docs/components/select-faceted.md +25 -11
- package/docs/packages/plot.md +234 -19
- package/package.json +1 -1
|
@@ -17,15 +17,25 @@ const SHADOW_STYLE = `
|
|
|
17
17
|
align-items: stretch;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
:host([indicator-placement="end"]) .header {
|
|
21
|
+
display: grid;
|
|
22
|
+
grid-template-columns: minmax(0, 1fr) auto var(--_expander-indicator-track);
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
slot[name="actions"] { display: none; }
|
|
21
26
|
.header.has-actions slot[name="actions"] {
|
|
22
27
|
display: flex;
|
|
23
28
|
align-items: center;
|
|
24
|
-
gap:
|
|
29
|
+
gap: var(--_expander-actions-gap);
|
|
25
30
|
flex-shrink: 0;
|
|
26
|
-
margin-inline-start:
|
|
31
|
+
margin-inline-start: var(--_expander-actions-start);
|
|
27
32
|
/* Inset from the right edge (the host has no padding of its own). */
|
|
28
|
-
margin-inline-end:
|
|
33
|
+
margin-inline-end: var(--_expander-actions-end);
|
|
34
|
+
}
|
|
35
|
+
:host([indicator-placement="end"]) .header.has-actions slot[name="actions"] {
|
|
36
|
+
grid-column: 2;
|
|
37
|
+
grid-row: 1;
|
|
38
|
+
z-index: 1;
|
|
29
39
|
}
|
|
30
40
|
|
|
31
41
|
button {
|
|
@@ -34,14 +44,11 @@ const SHADOW_STYLE = `
|
|
|
34
44
|
background: none;
|
|
35
45
|
border: none;
|
|
36
46
|
margin: 0;
|
|
37
|
-
/* The button
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
the title), so the title + the body share one inset value; 6px block
|
|
41
|
-
gives the header a touch more height. Restyle it edge-to-edge via
|
|
42
|
-
::part(summary). */
|
|
47
|
+
/* The default button fills the header beside its actions. The title and
|
|
48
|
+
body share --expander-gutter, and the indicator hangs inside that gutter.
|
|
49
|
+
End placement switches to the header's subgrid. */
|
|
43
50
|
position: relative;
|
|
44
|
-
padding:
|
|
51
|
+
padding: var(--_expander-header-padding-block) var(--_expander-header-padding-end) var(--_expander-header-padding-block) var(--expander-gutter);
|
|
45
52
|
flex: 1;
|
|
46
53
|
min-width: 0;
|
|
47
54
|
font: inherit;
|
|
@@ -58,49 +65,108 @@ const SHADOW_STYLE = `
|
|
|
58
65
|
outline: none;
|
|
59
66
|
}
|
|
60
67
|
|
|
68
|
+
:host([indicator-placement="end"]) button {
|
|
69
|
+
grid-column: 1 / -1;
|
|
70
|
+
grid-row: 1;
|
|
71
|
+
display: grid;
|
|
72
|
+
grid-template-columns: subgrid;
|
|
73
|
+
padding: var(--_expander-header-padding-block) 0;
|
|
74
|
+
}
|
|
75
|
+
:host([indicator-placement="end"]) slot[name="title"] {
|
|
76
|
+
grid-column: 1;
|
|
77
|
+
display: block;
|
|
78
|
+
min-width: 0;
|
|
79
|
+
margin-inline-start: var(--expander-gutter);
|
|
80
|
+
}
|
|
81
|
+
|
|
61
82
|
button:focus-visible {
|
|
62
83
|
outline: 1px solid var(--focus-ring);
|
|
63
84
|
outline-offset: 0px;
|
|
64
85
|
}
|
|
65
86
|
|
|
66
|
-
|
|
67
|
-
pushes the title. Its right edge lands 2px before the gutter (left = gutter
|
|
68
|
-
- 16px - 2px), leaving a 2px gap before the title; at the default 24px
|
|
69
|
-
gutter the chevron box is [6px, 22px], and on outdent (gutter 0) it
|
|
70
|
-
auto-hangs at -18px in the negative gutter. One var drives the title inset,
|
|
71
|
-
the body inset, and the chevron position. */
|
|
72
|
-
button::before {
|
|
73
|
-
content: '';
|
|
87
|
+
.indicator {
|
|
74
88
|
position: absolute;
|
|
75
|
-
|
|
89
|
+
inset-inline-start: var(--_expander-indicator-start);
|
|
76
90
|
top: 50%;
|
|
77
|
-
width:
|
|
78
|
-
height:
|
|
91
|
+
width: var(--_expander-indicator-size);
|
|
92
|
+
height: var(--_expander-indicator-size);
|
|
93
|
+
pointer-events: none;
|
|
94
|
+
opacity: 0.6;
|
|
95
|
+
transform: translateY(-50%);
|
|
96
|
+
transition: transform 150ms ease, opacity 150ms ease;
|
|
97
|
+
}
|
|
98
|
+
.indicator slot { display: grid; place-items: center; width: 100%; height: 100%; }
|
|
99
|
+
.indicator slot::slotted(*) { pointer-events: none; }
|
|
100
|
+
.indicator .glyph {
|
|
101
|
+
display: block;
|
|
102
|
+
width: var(--_expander-indicator-size);
|
|
103
|
+
height: var(--_expander-indicator-size);
|
|
79
104
|
background-color: currentColor;
|
|
80
|
-
-webkit-mask-image: var(--_expander-
|
|
81
|
-
mask-image: var(--_expander-
|
|
105
|
+
-webkit-mask-image: var(--_expander-indicator-mask);
|
|
106
|
+
mask-image: var(--_expander-indicator-mask);
|
|
82
107
|
-webkit-mask-size: contain;
|
|
83
108
|
mask-size: contain;
|
|
84
109
|
-webkit-mask-repeat: no-repeat;
|
|
85
110
|
mask-repeat: no-repeat;
|
|
86
111
|
-webkit-mask-position: center;
|
|
87
112
|
mask-position: center;
|
|
88
|
-
opacity: 0.6;
|
|
89
|
-
/* translateY centers it; the open state adds rotate (same transform so the
|
|
90
|
-
transition animates only the rotation). */
|
|
91
|
-
transform: translateY(-50%);
|
|
92
|
-
transition: transform 150ms ease, opacity 150ms ease, background-color 150ms ease;
|
|
93
113
|
}
|
|
94
|
-
|
|
95
|
-
|
|
114
|
+
:host([indicator="plus"]) .indicator .glyph { position: relative; background: none; mask: none; -webkit-mask: none; }
|
|
115
|
+
:host([indicator="plus"]) .indicator .glyph::before,
|
|
116
|
+
:host([indicator="plus"]) .indicator .glyph::after {
|
|
117
|
+
content: '';
|
|
118
|
+
position: absolute;
|
|
119
|
+
background: currentColor;
|
|
120
|
+
border-radius: calc(var(--_expander-indicator-stroke) / 2);
|
|
121
|
+
}
|
|
122
|
+
:host([indicator="plus"]) .indicator .glyph::before {
|
|
123
|
+
width: calc(var(--_expander-indicator-size) - 2 * var(--_expander-indicator-stroke));
|
|
124
|
+
height: var(--_expander-indicator-stroke);
|
|
125
|
+
left: var(--_expander-indicator-stroke);
|
|
126
|
+
top: calc((var(--_expander-indicator-size) - var(--_expander-indicator-stroke)) / 2);
|
|
127
|
+
}
|
|
128
|
+
:host([indicator="plus"]) .indicator .glyph::after {
|
|
129
|
+
width: var(--_expander-indicator-stroke);
|
|
130
|
+
height: calc(var(--_expander-indicator-size) - 2 * var(--_expander-indicator-stroke));
|
|
131
|
+
left: calc((var(--_expander-indicator-size) - var(--_expander-indicator-stroke)) / 2);
|
|
132
|
+
top: var(--_expander-indicator-stroke);
|
|
133
|
+
transition: transform 150ms ease;
|
|
134
|
+
}
|
|
135
|
+
button:enabled:hover .indicator { opacity: 1; }
|
|
136
|
+
button[aria-expanded="true"] .indicator { transform: translateY(-50%) rotate(90deg); opacity: 1; }
|
|
137
|
+
:host([indicator="plus"]) button[aria-expanded="true"] .indicator,
|
|
138
|
+
button[aria-expanded="true"] .indicator.has-pair { transform: translateY(-50%); }
|
|
139
|
+
:host([indicator="plus"]) button[aria-expanded="true"] .glyph::after { transform: scaleY(0); }
|
|
140
|
+
button[aria-expanded="false"] slot[name="indicator"]::slotted([data-when="open"]),
|
|
141
|
+
button[aria-expanded="true"] slot[name="indicator"]::slotted([data-when="closed"]) { display: none; }
|
|
142
|
+
|
|
143
|
+
:host([indicator-placement="end"]) .indicator {
|
|
144
|
+
position: static;
|
|
145
|
+
grid-column: 3;
|
|
146
|
+
grid-row: 1;
|
|
147
|
+
justify-self: end;
|
|
148
|
+
align-self: center;
|
|
149
|
+
margin-inline-end: var(--_expander-indicator-edge);
|
|
150
|
+
transform: rotate(90deg);
|
|
151
|
+
}
|
|
152
|
+
:host([indicator-placement="end"]) button[aria-expanded="true"] .indicator { transform: rotate(270deg); }
|
|
153
|
+
:host([indicator-placement="end"]) .indicator.has-custom,
|
|
154
|
+
:host([indicator-placement="end"]) .indicator.has-pair { transform: none; }
|
|
155
|
+
:host([indicator-placement="end"][indicator="plus"]) .indicator { transform: none; }
|
|
156
|
+
:host([indicator-placement="end"]) button[aria-expanded="true"] .indicator.has-custom { transform: rotate(180deg); }
|
|
157
|
+
:host([indicator-placement="end"]) button[aria-expanded="true"] .indicator.has-pair,
|
|
158
|
+
:host([indicator-placement="end"][indicator="plus"]) button[aria-expanded="true"] .indicator { transform: none; }
|
|
96
159
|
|
|
97
160
|
button:enabled:hover { color: var(--expander-text-hover); }
|
|
98
161
|
:host([priority="tertiary"]) button:enabled:hover { --_summary-underline: underline; }
|
|
99
162
|
button:enabled:active { color: var(--expander-text); }
|
|
100
163
|
button:disabled { cursor: default; }
|
|
101
|
-
button:enabled:not([aria-expanded="true"]):active
|
|
164
|
+
button:enabled:not([aria-expanded="true"]):active .indicator {
|
|
102
165
|
opacity: 0.6;
|
|
103
166
|
}
|
|
167
|
+
@media (prefers-reduced-motion: reduce) {
|
|
168
|
+
.indicator, :host([indicator="plus"]) .indicator .glyph::after { transition: none; }
|
|
169
|
+
}
|
|
104
170
|
|
|
105
171
|
.region {
|
|
106
172
|
display: grid;
|
|
@@ -109,11 +175,8 @@ const SHADOW_STYLE = `
|
|
|
109
175
|
}
|
|
110
176
|
.header:has(button[aria-expanded="true"]) + .region { grid-template-rows: 1fr; }
|
|
111
177
|
|
|
112
|
-
/*
|
|
113
|
-
|
|
114
|
-
header + region back by that 1px so the title and body land exactly on the
|
|
115
|
-
surrounding content (the chevron, absolutely positioned inside the header,
|
|
116
|
-
rides along). Logical start so it follows RTL. */
|
|
178
|
+
/* The transparent tertiary border still insets the content by 1px. Pull the
|
|
179
|
+
header and region back so outdent lands flush with surrounding content. */
|
|
117
180
|
:host([priority="tertiary"][outdent]) .header,
|
|
118
181
|
:host([priority="tertiary"][outdent]) .region {
|
|
119
182
|
margin-inline-start: -1px;
|
|
@@ -145,8 +208,7 @@ class AExpanderElement extends HTMLElementBase {
|
|
|
145
208
|
// including custom header content. Guarded for engines without ResizeObserver.
|
|
146
209
|
roundObserver;
|
|
147
210
|
// ElementInternals exposes the open/closed state as a custom state
|
|
148
|
-
// (`:state(open)`) for consumer styling
|
|
149
|
-
// in `actions`, or matching an open header to a design. It's NOT a host
|
|
211
|
+
// (`:state(open)`) for consumer styling, including the indicator. It's NOT a host
|
|
150
212
|
// attribute (declarative-DOM safe: no host mutation, no reconciliation
|
|
151
213
|
// churn), just element-internal state the browser exposes for CSS matching.
|
|
152
214
|
// Guarded for engines without attachInternals / CustomStateSet (no-op there).
|
|
@@ -164,7 +226,24 @@ class AExpanderElement extends HTMLElementBase {
|
|
|
164
226
|
const titleSlot = document.createElement("slot");
|
|
165
227
|
titleSlot.name = "title";
|
|
166
228
|
this.titleSlot = titleSlot;
|
|
167
|
-
|
|
229
|
+
const indicator = document.createElement("span");
|
|
230
|
+
indicator.className = "indicator";
|
|
231
|
+
indicator.setAttribute("part", "indicator");
|
|
232
|
+
indicator.setAttribute("aria-hidden", "true");
|
|
233
|
+
indicator.inert = true;
|
|
234
|
+
const indicatorSlot = document.createElement("slot");
|
|
235
|
+
indicatorSlot.name = "indicator";
|
|
236
|
+
const glyph = document.createElement("span");
|
|
237
|
+
glyph.className = "glyph";
|
|
238
|
+
indicatorSlot.append(glyph);
|
|
239
|
+
indicatorSlot.addEventListener("slotchange", () => {
|
|
240
|
+
const assigned = indicatorSlot.assignedElements();
|
|
241
|
+
const hasPair = assigned.some((el) => el.hasAttribute("data-when"));
|
|
242
|
+
indicator.classList.toggle("has-custom", assigned.length > 0 && !hasPair);
|
|
243
|
+
indicator.classList.toggle("has-pair", hasPair);
|
|
244
|
+
});
|
|
245
|
+
indicator.append(indicatorSlot);
|
|
246
|
+
this.summary.append(titleSlot, indicator);
|
|
168
247
|
this.summary.addEventListener("click", this.onSummaryClick);
|
|
169
248
|
const header = document.createElement("div");
|
|
170
249
|
header.className = "header";
|
package/dist/elements/a-menu.js
CHANGED
|
@@ -22,9 +22,20 @@ const openStack = [];
|
|
|
22
22
|
let docBound = false;
|
|
23
23
|
let boundDoc = null;
|
|
24
24
|
let boundView = null;
|
|
25
|
+
let mouseX = null;
|
|
26
|
+
let mouseY = 0;
|
|
27
|
+
function trackMouse(e) {
|
|
28
|
+
mouseX = e.pointerType === "mouse" ? e.clientX : null;
|
|
29
|
+
if (mouseX !== null) mouseY = e.clientY;
|
|
30
|
+
}
|
|
31
|
+
function mouseInside(rect) {
|
|
32
|
+
return mouseX !== null && mouseX >= rect.left && mouseX < rect.right && mouseY >= rect.top && mouseY < rect.bottom;
|
|
33
|
+
}
|
|
25
34
|
function bindDocListeners(doc, view) {
|
|
26
35
|
if (docBound) return;
|
|
27
36
|
doc.addEventListener("pointerdown", onDocPointerDown, true);
|
|
37
|
+
doc.addEventListener("pointermove", trackMouse, { capture: true, passive: true });
|
|
38
|
+
doc.addEventListener("pointerleave", clearMouse);
|
|
28
39
|
doc.addEventListener("keydown", onDocKeyDown, true);
|
|
29
40
|
doc.addEventListener("keyup", onDocKeyUp, true);
|
|
30
41
|
doc.addEventListener("contextmenu", onDocContextMenu, true);
|
|
@@ -36,6 +47,8 @@ function bindDocListeners(doc, view) {
|
|
|
36
47
|
function unbindDocListeners() {
|
|
37
48
|
if (!docBound) return;
|
|
38
49
|
boundDoc?.removeEventListener("pointerdown", onDocPointerDown, true);
|
|
50
|
+
boundDoc?.removeEventListener("pointermove", trackMouse, true);
|
|
51
|
+
boundDoc?.removeEventListener("pointerleave", clearMouse);
|
|
39
52
|
boundDoc?.removeEventListener("keydown", onDocKeyDown, true);
|
|
40
53
|
boundDoc?.removeEventListener("keyup", onDocKeyUp, true);
|
|
41
54
|
boundDoc?.removeEventListener("contextmenu", onDocContextMenu, true);
|
|
@@ -43,6 +56,10 @@ function unbindDocListeners() {
|
|
|
43
56
|
boundDoc = null;
|
|
44
57
|
boundView = null;
|
|
45
58
|
docBound = false;
|
|
59
|
+
mouseX = null;
|
|
60
|
+
}
|
|
61
|
+
function clearMouse() {
|
|
62
|
+
mouseX = null;
|
|
46
63
|
}
|
|
47
64
|
function menuIndexForEvent(e, primaryClick = false) {
|
|
48
65
|
const path = e.composedPath();
|
|
@@ -75,6 +92,7 @@ setMenuPresence({
|
|
|
75
92
|
contains: nodeHitsMenus
|
|
76
93
|
});
|
|
77
94
|
function onDocPointerDown(e) {
|
|
95
|
+
trackMouse(e);
|
|
78
96
|
if (!openStack.length) return;
|
|
79
97
|
const index = menuIndexForEvent(e, e.button === 0);
|
|
80
98
|
openStack[index + 1]?.requestClose(e);
|
|
@@ -145,6 +163,7 @@ class AMenuElement extends HTMLElementBase {
|
|
|
145
163
|
// Submenu hover-intent timers.
|
|
146
164
|
openTimer;
|
|
147
165
|
closeTimer;
|
|
166
|
+
#holdHoverClose = false;
|
|
148
167
|
// Typeahead state (root navigation).
|
|
149
168
|
typeBuffer = "";
|
|
150
169
|
typeTimer;
|
|
@@ -307,7 +326,10 @@ class AMenuElement extends HTMLElementBase {
|
|
|
307
326
|
this.surface.append(header, scroll, footer);
|
|
308
327
|
this.surface.addEventListener("pointerenter", (e) => {
|
|
309
328
|
if (e.pointerType !== "mouse") return;
|
|
310
|
-
if (this.isSubmenu)
|
|
329
|
+
if (this.isSubmenu) {
|
|
330
|
+
this.#holdHoverClose = false;
|
|
331
|
+
this.cancelCloseTimer();
|
|
332
|
+
}
|
|
311
333
|
});
|
|
312
334
|
this.surface.addEventListener("pointerleave", (e) => {
|
|
313
335
|
if (e.pointerType !== "mouse") return;
|
|
@@ -850,6 +872,7 @@ class AMenuElement extends HTMLElementBase {
|
|
|
850
872
|
_doShow(coord, instant = false) {
|
|
851
873
|
if (this.surface.isConnected && !this._shown) this.surface.showPopover();
|
|
852
874
|
this._shown = true;
|
|
875
|
+
this.#holdHoverClose = false;
|
|
853
876
|
this._dismissNotified = false;
|
|
854
877
|
this.reflectOpen(true);
|
|
855
878
|
this.hideAnchorTooltip();
|
|
@@ -866,9 +889,18 @@ class AMenuElement extends HTMLElementBase {
|
|
|
866
889
|
}
|
|
867
890
|
/** Shadow-only hide. */
|
|
868
891
|
_doHide() {
|
|
892
|
+
const parent = this.parentElement?.closest("a-menu");
|
|
893
|
+
if (this._shown && parent && mouseX !== null && mouseInside(this.surface.getBoundingClientRect())) {
|
|
894
|
+
for (let ancestor = parent; ancestor; ancestor = ancestor.parentElement?.closest("a-menu")) {
|
|
895
|
+
if (!ancestor.isSubmenu || !ancestor.#isHover || !ancestor._shown || ancestor.surface.matches(":hover")) continue;
|
|
896
|
+
ancestor.#holdHoverClose = true;
|
|
897
|
+
ancestor.cancelCloseTimer();
|
|
898
|
+
}
|
|
899
|
+
}
|
|
869
900
|
this.#stopAnchorTracking();
|
|
870
901
|
if (this.surface.isConnected && this._shown) this.surface.hidePopover();
|
|
871
902
|
this._shown = false;
|
|
903
|
+
this.#holdHoverClose = false;
|
|
872
904
|
this.reflectOpen(false);
|
|
873
905
|
this.cancelOpenTimer();
|
|
874
906
|
this.cancelCloseTimer();
|
|
@@ -1242,7 +1274,9 @@ class AMenuElement extends HTMLElementBase {
|
|
|
1242
1274
|
let onLeave;
|
|
1243
1275
|
if (this.#isHover) {
|
|
1244
1276
|
onEnter = (e) => {
|
|
1245
|
-
if (e.pointerType
|
|
1277
|
+
if (e.pointerType !== "mouse") return;
|
|
1278
|
+
this.#holdHoverClose = false;
|
|
1279
|
+
this.scheduleOpen();
|
|
1246
1280
|
};
|
|
1247
1281
|
onLeave = (e) => {
|
|
1248
1282
|
if (e.pointerType === "mouse") this.scheduleClose();
|
|
@@ -1320,9 +1354,12 @@ class AMenuElement extends HTMLElementBase {
|
|
|
1320
1354
|
scheduleClose() {
|
|
1321
1355
|
this.cancelOpenTimer();
|
|
1322
1356
|
if (!this._shown) return;
|
|
1357
|
+
if (this.#holdHoverClose) return;
|
|
1323
1358
|
if (this.#hasKeyboardFocusInside) return;
|
|
1324
|
-
if (openStack.some((m) => m !== this && (this.contains(m) || m.triggerAnchor != null && this.contains(m.triggerAnchor))))
|
|
1359
|
+
if (openStack.some((m) => m !== this && (this.contains(m) || m.triggerAnchor != null && this.contains(m.triggerAnchor)))) {
|
|
1360
|
+
this.cancelCloseTimer();
|
|
1325
1361
|
return;
|
|
1362
|
+
}
|
|
1326
1363
|
this.cancelCloseTimer();
|
|
1327
1364
|
this.closeTimer = setTimeout(() => {
|
|
1328
1365
|
this.closeTimer = void 0;
|
package/dist/general_types.d.ts
CHANGED
|
@@ -334,6 +334,10 @@ export interface ABoxAttributes extends BaseAttributes {
|
|
|
334
334
|
* typed `attr()` read it from `--box-gap` in the host's inline style
|
|
335
335
|
* instead, which is what the JSX wrapper always sets. */
|
|
336
336
|
gap?: boolean | '' | number | string;
|
|
337
|
+
/** Adds matching descendant rects to each measurement snapshot. With
|
|
338
|
+
* `observe="scroll"`, use `throttle` when many descendants match: rects are
|
|
339
|
+
* read for each emitted event, and CSS state updates follow the interval. */
|
|
340
|
+
'include-rects-for'?: string;
|
|
337
341
|
/** CSS padding shorthand (`padding="8px 16px"`). Without typed `attr()`
|
|
338
342
|
* support, set `--box-padding` as well. The JSX wrapper supplies it. */
|
|
339
343
|
padding?: boolean | '' | number | string;
|
|
@@ -348,8 +352,12 @@ export interface ABoxAttributes extends BaseAttributes {
|
|
|
348
352
|
* attribute means `all`. Omission runs no observers unless `fade` is set;
|
|
349
353
|
* a native event listener alone does not enable observation. */
|
|
350
354
|
observe?: string;
|
|
351
|
-
/**
|
|
352
|
-
*
|
|
355
|
+
/** Keeps measurement observation active outside the viewport when `observe`
|
|
356
|
+
* or `fade` selects measurement. */
|
|
357
|
+
'observe-offscreen'?: boolean | '';
|
|
358
|
+
/** Minimum interval between measurement reads, CSS state updates, and
|
|
359
|
+
* events in milliseconds. The initial read is immediate. Omit or pass `0`
|
|
360
|
+
* for frame-based updates. Invalid or negative values use `0`. */
|
|
353
361
|
throttle?: number | string;
|
|
354
362
|
/** Depth of that mask, as a length value (`fade-size="2rem"`). Engines
|
|
355
363
|
* without typed `attr()` read it from `--box-fade-size` in the host's
|
|
@@ -423,6 +431,11 @@ export interface ATagAttributes extends BaseAttributes {
|
|
|
423
431
|
* use `Expander` from `@antadesign/anta`.
|
|
424
432
|
*/
|
|
425
433
|
export interface AExpanderAttributes extends BaseAttributes {
|
|
434
|
+
/** Built-in disclosure mark. Custom visuals use `slot="indicator"`.
|
|
435
|
+
* Defaults to `chevron`. */
|
|
436
|
+
indicator?: 'chevron' | 'triangle' | 'plus';
|
|
437
|
+
/** Logical side for the disclosure mark. Defaults to `start`. */
|
|
438
|
+
'indicator-placement'?: 'start' | 'end';
|
|
426
439
|
/** Controlled open state (`'open'` / `'closed'`). Present → controlled: the
|
|
427
440
|
* attribute is the source of truth, clicks only dispatch the cancelable
|
|
428
441
|
* `statechange` event, and the consumer answers by updating it. Absent →
|
|
@@ -434,10 +447,9 @@ export interface AExpanderAttributes extends BaseAttributes {
|
|
|
434
447
|
/** Surface emphasis. `secondary` (default) is a subtle fill; `primary`
|
|
435
448
|
* is a stronger raised fill; `tertiary` is transparent. */
|
|
436
449
|
priority?: 'primary' | 'secondary' | 'tertiary';
|
|
437
|
-
/**
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
* has to bound the chevron. Presence-based. */
|
|
450
|
+
/** Align the title and body with surrounding content on a tertiary
|
|
451
|
+
* expander. The start indicator hangs in the gutter; an end indicator
|
|
452
|
+
* stays inside its edge. Presence-based. */
|
|
441
453
|
outdent?: boolean | '';
|
|
442
454
|
/** Disables the header: not clickable or focusable, hover affordance
|
|
443
455
|
* off, text dimmed. The open state freezes as-is. Presence-based. */
|
package/dist/index.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export { Panel } from './components/Panel';
|
|
|
34
34
|
export type { PanelProps } from './components/Panel';
|
|
35
35
|
export type { PanelState } from './general_types';
|
|
36
36
|
export type { CaptureInputCancelReason, CaptureInputDirection, CaptureInputDirections, CaptureInputGeometry, CaptureInputModifier, CapturePan, CapturePanInertia, CapturePanInput, CapturePointerActivationReason, CapturePointerCapture, CapturePointerInput, CapturePointerStart, CapturePointerType, CaptureWheelActivation, CaptureWheelActivationReason, CaptureWheelInput, CaptureWheelSettle, SerializedMouseEvent, SerializedPointerEvent, SerializedWheelEvent, } from './capture-types';
|
|
37
|
-
export type { BoxChange, BoxContext, BoxContextChange, BoxDisplay, BoxFont, BoxInset, BoxMeasurement, BoxMeasurementChange, BoxObservation, BoxMode, BoxOS, BoxBrowser, BoxPointer, } from './box-types';
|
|
37
|
+
export type { BoxChange, BoxContext, BoxContextChange, BoxDisplay, BoxFont, BoxInset, BoxMeasurement, BoxMeasurementChange, BoxObservation, BoxRect, BoxMode, BoxOS, BoxBrowser, BoxPointer, } from './box-types';
|
|
38
38
|
export { Title } from './components/Title';
|
|
39
39
|
export type { TitleProps } from './components/Title';
|
|
40
40
|
export { Tag } from './components/Tag';
|
package/docs/changelog.md
CHANGED
|
@@ -3,6 +3,40 @@
|
|
|
3
3
|
This page tracks changes that ship in `@antadesign/anta`. Documentation-only
|
|
4
4
|
changes are not listed.
|
|
5
5
|
|
|
6
|
+
## 0.3.32 — September 25, 2026
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- [Expander indicators](/expander/#indicator) can sit after header actions and
|
|
11
|
+
use built-in chevron, triangle, or plus visuals. Custom indicators can rotate
|
|
12
|
+
as one node or switch between closed and open nodes.
|
|
13
|
+
- [Box measurements](/box/#measurements) can include
|
|
14
|
+
descendant rects with `includeRectsFor`, including positions relative to the
|
|
15
|
+
Box, width, and height. Changed rects appear in `detail.changed.rects` when
|
|
16
|
+
another observed field triggers a report.
|
|
17
|
+
- [Box measurements](/box/#measurements) can stay active outside the viewport
|
|
18
|
+
with `observeOffscreen` when a virtualized layout needs updates there.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- [Box layout](/box/#display) now uses `position: relative` by default, so
|
|
23
|
+
absolutely positioned descendants use the Box as their containing block. Set
|
|
24
|
+
`position: static` on the Box if they should use another positioned ancestor.
|
|
25
|
+
- [Box measurements](/box/#measurements) now apply `throttle` to measurement
|
|
26
|
+
reads and CSS states as well as events. The edge mask eases between states;
|
|
27
|
+
larger intervals delay the fade response during scrolling.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- [Expander indicators](/expander/#indicator) leave the mark empty for
|
|
32
|
+
unrecognized strings and numbers instead of displaying them as text.
|
|
33
|
+
- [Menu submenus](/menu/#submenus) stay open when a nested
|
|
34
|
+
date picker closes under the pointer outside the submenu. Hover dismissal
|
|
35
|
+
resumes after the pointer returns. Closing a nested popup away from the
|
|
36
|
+
pointer leaves hover dismissal available.
|
|
37
|
+
- [Dialog headers](/dialog/#zones) wrap long unbroken text
|
|
38
|
+
and clip content that still overflows their bounds.
|
|
39
|
+
|
|
6
40
|
## 0.3.31 — September 18, 2026
|
|
7
41
|
|
|
8
42
|
### Added
|