@antadesign/anta 0.3.27 → 0.3.29
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/NOTICES.md +32 -1
- package/dist/anta_helpers.d.ts +25 -0
- package/dist/anta_helpers.js +28 -0
- package/dist/box-observation.d.ts +8 -0
- package/dist/box-observation.js +41 -0
- package/dist/box-types.d.ts +2 -0
- package/dist/bundle.css +1 -1
- package/dist/bundle.js +77 -46
- package/dist/components/Banner.js +2 -2
- package/dist/components/Box.d.ts +28 -12
- package/dist/components/Box.js +18 -11
- package/dist/components/Breadcrumbs.css +1 -1
- package/dist/components/Button.js +2 -2
- package/dist/components/Calendar.js +3 -5
- package/dist/components/Card.js +2 -2
- package/dist/components/Checkbox.d.ts +12 -13
- package/dist/components/Checkbox.js +5 -13
- package/dist/components/Expander.js +2 -2
- package/dist/components/Input.d.ts +8 -2
- package/dist/components/Input.js +6 -2
- package/dist/components/InputAutocomplete.js +3 -12
- package/dist/components/InputDate.css +1 -1
- package/dist/components/InputDate.js +2 -0
- package/dist/components/InputTime.js +2 -2
- package/dist/components/Loader.js +2 -1
- package/dist/components/Menu.d.ts +4 -4
- package/dist/components/Menu.js +1 -1
- package/dist/components/MenuItem.d.ts +7 -8
- package/dist/components/MenuItem.js +4 -4
- package/dist/components/Panel.d.ts +17 -0
- package/dist/components/Panel.js +22 -0
- package/dist/components/Progress.js +2 -2
- package/dist/components/RadioGroup.d.ts +14 -14
- package/dist/components/RadioGroup.js +7 -23
- package/dist/components/Select.d.ts +26 -21
- package/dist/components/Select.js +51 -38
- package/dist/components/SelectFaceted.d.ts +24 -11
- package/dist/components/SelectFaceted.js +65 -44
- package/dist/components/Slider.js +3 -3
- package/dist/components/Steps.css +1 -1
- package/dist/components/Switch.d.ts +10 -11
- package/dist/components/Switch.js +3 -11
- package/dist/components/TabPanel.d.ts +3 -8
- package/dist/components/TabPanel.js +2 -1
- package/dist/components/Tabs.d.ts +2 -2
- package/dist/components/Tabs.js +4 -3
- package/dist/components/Tag.d.ts +7 -9
- package/dist/components/Tag.js +2 -2
- package/dist/components/Text.js +2 -2
- package/dist/components/Title.js +2 -2
- package/dist/components/Tooltip.d.ts +1 -1
- package/dist/components/Tooltip.js +1 -1
- package/dist/components/select-parts.css +1 -1
- package/dist/elements/a-avatar.css +1 -1
- package/dist/elements/a-banner.css +1 -1
- package/dist/elements/a-box.css +1 -1
- package/dist/elements/a-box.d.ts +6 -6
- package/dist/elements/a-box.js +74 -23
- package/dist/elements/a-button.css +1 -1
- package/dist/elements/a-button.d.ts +16 -10
- package/dist/elements/a-button.js +64 -1
- package/dist/elements/a-calendar.css +1 -1
- package/dist/elements/a-capture.css +1 -1
- package/dist/elements/a-card.css +1 -1
- package/dist/elements/a-checkbox.css +1 -1
- package/dist/elements/a-checkbox.d.ts +3 -0
- package/dist/elements/a-checkbox.js +17 -1
- package/dist/elements/a-copy.css +1 -1
- package/dist/elements/a-dialog.css +1 -1
- package/dist/elements/a-expander.css +1 -1
- package/dist/elements/a-expander.js +1 -0
- package/dist/elements/a-icon.css +1 -1
- package/dist/elements/a-icon.shapes.css +1 -1
- package/dist/elements/a-input-time.css +1 -1
- package/dist/elements/a-input-time.d.ts +8 -0
- package/dist/elements/a-input-time.js +120 -15
- package/dist/elements/a-input.css +1 -1
- package/dist/elements/a-input.d.ts +27 -1
- package/dist/elements/a-input.js +180 -41
- package/dist/elements/a-loader.css +1 -1
- package/dist/elements/a-menu-group.css +1 -1
- package/dist/elements/a-menu-item.css +1 -1
- package/dist/elements/a-menu-item.js +1 -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 +8 -13
- package/dist/elements/a-menu.js +146 -45
- package/dist/elements/a-panel.css +1 -0
- package/dist/elements/a-panel.d.ts +16 -0
- package/dist/elements/a-panel.js +153 -0
- package/dist/elements/a-progress.css +1 -1
- package/dist/elements/a-radio-group.css +1 -1
- package/dist/elements/a-radio.css +1 -1
- package/dist/elements/a-radio.d.ts +4 -0
- package/dist/elements/a-radio.js +18 -0
- package/dist/elements/a-slider.css +1 -1
- package/dist/elements/a-slider.d.ts +1 -0
- package/dist/elements/a-slider.js +3 -6
- package/dist/elements/a-switch.css +1 -1
- package/dist/elements/a-switch.d.ts +3 -0
- package/dist/elements/a-switch.js +17 -1
- package/dist/elements/a-tab.css +1 -1
- package/dist/elements/a-tabpanel.css +1 -1
- package/dist/elements/a-tabs.css +1 -1
- package/dist/elements/a-tag.css +1 -1
- package/dist/elements/a-text.css +1 -1
- package/dist/elements/a-text.js +1 -0
- package/dist/elements/a-title.css +1 -1
- package/dist/elements/a-toast.css +1 -1
- package/dist/elements/a-toaster.css +1 -1
- package/dist/elements/a-tooltip.css +1 -1
- package/dist/elements/a-tooltip.d.ts +3 -4
- package/dist/elements/a-tooltip.js +30 -8
- package/dist/elements/focus.d.ts +9 -0
- package/dist/elements/focus.js +41 -0
- package/dist/elements/index.d.ts +1 -0
- package/dist/elements/index.js +3 -0
- package/dist/elements/panel-focus.d.ts +10 -0
- package/dist/elements/panel-focus.js +86 -0
- package/dist/elements/shadow-aria.d.ts +10 -0
- package/dist/elements/shadow-aria.js +155 -0
- package/dist/general_types.d.ts +70 -42
- package/dist/generate-icons.mjs +3 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +2 -0
- package/dist/jsx-runtime.d.ts +10 -1
- package/dist/reset.css +1 -1
- package/dist/theme-antithesis.css +1 -0
- package/dist/theme-antune.css +1 -0
- package/dist/tokens.css +1 -1
- package/docs/accessibility.md +4 -2
- package/docs/changelog.md +135 -0
- package/docs/colors.md +7 -7
- package/docs/comparison.md +2 -2
- package/docs/components/box.md +98 -34
- package/docs/components/breadcrumbs.md +75 -6
- package/docs/components/button.md +2 -2
- package/docs/components/capture.md +8 -8
- package/docs/components/checkbox.md +21 -16
- package/docs/components/input-autocomplete.md +6 -0
- package/docs/components/input-date.md +8 -2
- package/docs/components/input.md +99 -40
- package/docs/components/menu.md +5 -6
- package/docs/components/panel.md +189 -0
- package/docs/components/radio.md +16 -13
- package/docs/components/select-faceted.md +58 -2
- package/docs/components/select.md +72 -59
- package/docs/components/steps.md +4 -4
- package/docs/components/switch.md +16 -10
- package/docs/components/tabs.md +21 -8
- package/docs/components/tag.md +5 -3
- package/docs/components/tooltip.md +6 -4
- package/docs/index.md +1 -0
- package/docs/install-config.md +23 -12
- package/docs/normalization.md +6 -4
- package/docs/theming.md +95 -17
- package/package.json +8 -4
- package/dist/components/InputDate.module.css +0 -1
- package/dist/components/Select.module.css +0 -1
- package/dist/components/SelectFaceted.module.css +0 -1
- package/dist/search-index.json +0 -0
- package/dist/theme-anta.css +0 -1
package/dist/elements/a-input.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import { HTMLElementBase } from "../anta_helpers";
|
|
1
|
+
import { HTMLElementBase, SYNC_POPUP_ARIA } from "../anta_helpers";
|
|
2
|
+
import {
|
|
3
|
+
applyShadowAria,
|
|
4
|
+
ariaAttributeProperty,
|
|
5
|
+
SHADOW_ARIA_ATTRIBUTES,
|
|
6
|
+
SHADOW_ARIA_ATTRIBUTE_SET
|
|
7
|
+
} from "./shadow-aria";
|
|
2
8
|
import "./a-input.css";
|
|
3
9
|
const FORWARDED = [
|
|
4
10
|
"placeholder",
|
|
@@ -14,12 +20,7 @@ const FORWARDED = [
|
|
|
14
20
|
"required",
|
|
15
21
|
"min",
|
|
16
22
|
"max",
|
|
17
|
-
"step"
|
|
18
|
-
// `aria-label` on the host names the internal control (the actual textbox);
|
|
19
|
-
// without forwarding it, a bare `<a-input aria-label>` leaves the control
|
|
20
|
-
// unnamed. `applyLabelAria` already defers to a host `aria-label` over the
|
|
21
|
-
// label-slot text, so the two don't fight.
|
|
22
|
-
"aria-label"
|
|
23
|
+
"step"
|
|
23
24
|
];
|
|
24
25
|
const BOOL_FORWARDED = /* @__PURE__ */ new Set(["readonly", "required"]);
|
|
25
26
|
let focusFromKeyboard = false;
|
|
@@ -83,7 +84,7 @@ const SHADOW_STYLE = `
|
|
|
83
84
|
@media (hover: hover) and (pointer: fine) {
|
|
84
85
|
:host(:not(:disabled)) .field:hover { --_bw: 1px; }
|
|
85
86
|
}
|
|
86
|
-
:host(:not([readonly])) .field:has(input:focus, textarea:focus),
|
|
87
|
+
:host(:not([readonly])) .field:has(input:focus, textarea:focus, button:focus-visible),
|
|
87
88
|
:host([readonly]:state(kb-focus)) .field {
|
|
88
89
|
--_bw: 1px;
|
|
89
90
|
outline: 1px solid var(--focus-ring);
|
|
@@ -91,7 +92,7 @@ const SHADOW_STYLE = `
|
|
|
91
92
|
}
|
|
92
93
|
@media (forced-colors: active) { .field { border: 1px solid ButtonBorder; } }
|
|
93
94
|
|
|
94
|
-
input, textarea {
|
|
95
|
+
input, textarea, button {
|
|
95
96
|
flex: 1 1 auto;
|
|
96
97
|
min-width: 0;
|
|
97
98
|
width: 100%;
|
|
@@ -104,27 +105,27 @@ const SHADOW_STYLE = `
|
|
|
104
105
|
outline: none;
|
|
105
106
|
color: var(--input-text);
|
|
106
107
|
font-family: var(--sans-serif);
|
|
107
|
-
font-
|
|
108
|
-
font-
|
|
108
|
+
font-stretch: normal;
|
|
109
|
+
font-style: normal;
|
|
110
|
+
font-variation-settings: inherit;
|
|
109
111
|
font-size: var(--_fs);
|
|
110
112
|
line-height: var(--_lh);
|
|
111
113
|
font-weight: 400;
|
|
112
114
|
-webkit-appearance: none;
|
|
113
115
|
appearance: none;
|
|
114
116
|
}
|
|
115
|
-
@media (pointer: coarse) {
|
|
116
|
-
input:focus, textarea:focus { font-size: max(16px, var(--_fs)); }
|
|
117
|
-
}
|
|
118
117
|
textarea {
|
|
119
118
|
resize: none;
|
|
120
119
|
padding-block: var(--_pad-block);
|
|
121
120
|
overflow-y: auto;
|
|
122
121
|
}
|
|
122
|
+
button { text-align: start; white-space: nowrap; overflow: hidden; cursor: pointer; }
|
|
123
|
+
button.placeholder { color: var(--input-placeholder); }
|
|
123
124
|
:host([maxrows]:not([rows])) textarea {
|
|
124
125
|
max-height: calc(var(--_lh) * var(--_maxrows) + var(--_pad-block) * 2);
|
|
125
126
|
}
|
|
126
127
|
input::placeholder, textarea::placeholder { color: var(--input-placeholder); opacity: 1; }
|
|
127
|
-
input:disabled, textarea:disabled { cursor: not-allowed; }
|
|
128
|
+
input:disabled, textarea:disabled, button:disabled { cursor: not-allowed; }
|
|
128
129
|
:host([readonly]:not([disabled])) .field,
|
|
129
130
|
:host([readonly]:not([disabled])) input,
|
|
130
131
|
:host([readonly]:not([disabled])) textarea { cursor: pointer; }
|
|
@@ -142,7 +143,7 @@ const SHADOW_STYLE = `
|
|
|
142
143
|
color: var(--input-adornment);
|
|
143
144
|
font-size: var(--_fs);
|
|
144
145
|
line-height: var(--_lh);
|
|
145
|
-
font-
|
|
146
|
+
font-stretch: var(--_input-adornment-font-stretch, normal);
|
|
146
147
|
}
|
|
147
148
|
:host([dim-actions]) slot[name="leading"],
|
|
148
149
|
:host([dim-actions]) slot[name="trailing"],
|
|
@@ -183,13 +184,17 @@ const SHADOW_STYLE = `
|
|
|
183
184
|
line-height: calc(var(--_lh) - 2px);
|
|
184
185
|
}
|
|
185
186
|
`;
|
|
187
|
+
const READ_DELEGATED_ARIA = Symbol("readDelegatedAria");
|
|
188
|
+
const WRITE_DELEGATED_ARIA = Symbol("writeDelegatedAria");
|
|
186
189
|
class AInputElement extends HTMLElementBase {
|
|
187
190
|
static formAssociated = true;
|
|
188
191
|
static observedAttributes = [
|
|
189
192
|
...FORWARDED,
|
|
193
|
+
...SHADOW_ARIA_ATTRIBUTES,
|
|
190
194
|
"value",
|
|
191
195
|
"defaultvalue",
|
|
192
196
|
"multiline",
|
|
197
|
+
"button",
|
|
193
198
|
"rows",
|
|
194
199
|
"maxrows",
|
|
195
200
|
"status",
|
|
@@ -211,6 +216,18 @@ class AInputElement extends HTMLElementBase {
|
|
|
211
216
|
// Set by formDisabledCallback when an ancestor <fieldset disabled> / disabled
|
|
212
217
|
// form turns the field off (the host can't carry a [disabled] attribute itself).
|
|
213
218
|
formDisabled = false;
|
|
219
|
+
// Standard role/aria attributes are consumed from the neutral host and
|
|
220
|
+
// applied to the native shadow control. The values live off-DOM so the host
|
|
221
|
+
// does not become a second control in the accessibility tree.
|
|
222
|
+
delegatedAria = /* @__PURE__ */ new Map();
|
|
223
|
+
consumingAria = /* @__PURE__ */ new Set();
|
|
224
|
+
ariaApplyQueued = false;
|
|
225
|
+
// Direct element relationships supplied by an adjacent a-menu. These avoid
|
|
226
|
+
// renderer-local IDs and apply only when the consumer has not authored the
|
|
227
|
+
// corresponding ARIA relationship explicitly.
|
|
228
|
+
popupAriaSource;
|
|
229
|
+
popupControls = null;
|
|
230
|
+
popupActiveDescendant = null;
|
|
214
231
|
constructor() {
|
|
215
232
|
super();
|
|
216
233
|
try {
|
|
@@ -263,14 +280,6 @@ class AInputElement extends HTMLElementBase {
|
|
|
263
280
|
}
|
|
264
281
|
connectedCallback() {
|
|
265
282
|
trackFocusModality(this.doc);
|
|
266
|
-
const type = this.getAttribute("type")?.toLowerCase();
|
|
267
|
-
if (this.internals && type !== "number" && type !== "search") {
|
|
268
|
-
this.internals.role = "textbox";
|
|
269
|
-
} else if (this.internals && type === "number") {
|
|
270
|
-
this.internals.role = "spinbutton";
|
|
271
|
-
} else if (this.internals && type === "search") {
|
|
272
|
-
this.internals.role = "searchbox";
|
|
273
|
-
}
|
|
274
283
|
if (Object.prototype.hasOwnProperty.call(this, "value")) {
|
|
275
284
|
const v = this.value;
|
|
276
285
|
delete this.value;
|
|
@@ -279,13 +288,34 @@ class AInputElement extends HTMLElementBase {
|
|
|
279
288
|
if (!this.control) this.buildControl();
|
|
280
289
|
this.ready = true;
|
|
281
290
|
}
|
|
291
|
+
[SYNC_POPUP_ARIA](relations) {
|
|
292
|
+
if (relations.clear) {
|
|
293
|
+
if (this.popupAriaSource !== relations.source) return;
|
|
294
|
+
this.popupAriaSource = void 0;
|
|
295
|
+
this.popupControls = null;
|
|
296
|
+
this.popupActiveDescendant = null;
|
|
297
|
+
} else {
|
|
298
|
+
this.popupAriaSource = relations.source;
|
|
299
|
+
if ("controls" in relations) this.popupControls = relations.controls ?? null;
|
|
300
|
+
if ("activeDescendant" in relations)
|
|
301
|
+
this.popupActiveDescendant = relations.activeDescendant ?? null;
|
|
302
|
+
}
|
|
303
|
+
this.applyPopupAria();
|
|
304
|
+
}
|
|
282
305
|
attributeChangedCallback(name, _old, value) {
|
|
306
|
+
if (SHADOW_ARIA_ATTRIBUTE_SET.has(name)) {
|
|
307
|
+
if (this.consumingAria.has(name)) return;
|
|
308
|
+
this.consumeAria(name, value);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
283
311
|
if (!this.ready && name !== "value" && name !== "defaultvalue") return;
|
|
284
|
-
if (name === "multiline" || name === "rows" || name === "maxrows") {
|
|
312
|
+
if (name === "multiline" || name === "button" || name === "rows" || name === "maxrows") {
|
|
285
313
|
if (!this.control) return;
|
|
286
314
|
const needTextarea = this.hasAttribute("multiline") || this.hasAttribute("rows");
|
|
287
315
|
const isTextarea = this.control instanceof HTMLTextAreaElement;
|
|
288
|
-
|
|
316
|
+
const needButton = !needTextarea && this.hasAttribute("button");
|
|
317
|
+
const isButton = this.control instanceof HTMLButtonElement;
|
|
318
|
+
if (needTextarea !== isTextarea || needButton !== isButton) this.buildControl(this.value);
|
|
289
319
|
else if (this.control instanceof HTMLTextAreaElement) this.configureTextarea(this.control);
|
|
290
320
|
return;
|
|
291
321
|
}
|
|
@@ -305,22 +335,88 @@ class AInputElement extends HTMLElementBase {
|
|
|
305
335
|
if (name === "defaultvalue") return;
|
|
306
336
|
if (this.control) {
|
|
307
337
|
this.forward(name, value);
|
|
338
|
+
this.syncButtonPresentation();
|
|
308
339
|
this.updateValidity();
|
|
309
340
|
}
|
|
310
341
|
}
|
|
342
|
+
/** Standard ARIA is the raw custom-element API, but its semantic target is the
|
|
343
|
+
* native shadow field. Consume it synchronously so the host never remains a
|
|
344
|
+
* duplicate control after upgrade. */
|
|
345
|
+
consumeAria(name, value) {
|
|
346
|
+
if (value == null) this.delegatedAria.delete(name);
|
|
347
|
+
else this.delegatedAria.set(name, value);
|
|
348
|
+
if (this.hasAttribute(name)) {
|
|
349
|
+
this.consumingAria.add(name);
|
|
350
|
+
super.removeAttribute(name);
|
|
351
|
+
this.consumingAria.delete(name);
|
|
352
|
+
}
|
|
353
|
+
this.applyDelegatedAria(name);
|
|
354
|
+
this.queueDelegatedAria();
|
|
355
|
+
}
|
|
356
|
+
/** React/Preact may remove a prop after Anta has already consumed its host
|
|
357
|
+
* attribute. Catch that no-op DOM removal so the shadow control still updates. */
|
|
358
|
+
removeAttribute(name) {
|
|
359
|
+
if (SHADOW_ARIA_ATTRIBUTE_SET.has(name) && !this.consumingAria.has(name) && !this.hasAttribute(name)) {
|
|
360
|
+
const ariaName = name;
|
|
361
|
+
if (this.delegatedAria.delete(ariaName)) {
|
|
362
|
+
this.applyDelegatedAria(ariaName);
|
|
363
|
+
this.queueDelegatedAria();
|
|
364
|
+
}
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
super.removeAttribute(name);
|
|
368
|
+
}
|
|
369
|
+
toggleAttribute(name, force) {
|
|
370
|
+
if (SHADOW_ARIA_ATTRIBUTE_SET.has(name)) {
|
|
371
|
+
const ariaName = name;
|
|
372
|
+
const next = force ?? !this.delegatedAria.has(ariaName);
|
|
373
|
+
this.consumeAria(ariaName, next ? "" : null);
|
|
374
|
+
return next;
|
|
375
|
+
}
|
|
376
|
+
return super.toggleAttribute(name, force);
|
|
377
|
+
}
|
|
378
|
+
[READ_DELEGATED_ARIA](name) {
|
|
379
|
+
return this.delegatedAria.get(name) ?? null;
|
|
380
|
+
}
|
|
381
|
+
[WRITE_DELEGATED_ARIA](name, value) {
|
|
382
|
+
this.consumeAria(name, value == null ? null : String(value));
|
|
383
|
+
}
|
|
384
|
+
applyDelegatedAria(name) {
|
|
385
|
+
const control = this.control;
|
|
386
|
+
if (!control) return;
|
|
387
|
+
applyShadowAria(this, control, name, this.delegatedAria.get(name) ?? null);
|
|
388
|
+
if (name === "aria-label" || name === "aria-labelledby") this.applyLabelAria();
|
|
389
|
+
if (name === "aria-description" || name === "aria-describedby") this.applyDescriptionAria();
|
|
390
|
+
if (name === "aria-invalid" && !this.delegatedAria.has(name)) this.syncStatus();
|
|
391
|
+
if (name === "aria-controls" || name === "aria-activedescendant") this.applyPopupAria();
|
|
392
|
+
}
|
|
393
|
+
queueDelegatedAria() {
|
|
394
|
+
if (this.ariaApplyQueued) return;
|
|
395
|
+
this.ariaApplyQueued = true;
|
|
396
|
+
queueMicrotask(() => {
|
|
397
|
+
this.ariaApplyQueued = false;
|
|
398
|
+
const control = this.control;
|
|
399
|
+
if (!control) return;
|
|
400
|
+
for (const [name, value] of this.delegatedAria) applyShadowAria(this, control, name, value);
|
|
401
|
+
});
|
|
402
|
+
}
|
|
311
403
|
/** (Re)build the shadow control from the current attributes. */
|
|
312
404
|
buildControl(initial) {
|
|
313
405
|
const prev = this.control;
|
|
314
406
|
const refocus = prev != null && this.shadowRoot?.activeElement === prev;
|
|
315
407
|
let selStart = null;
|
|
316
408
|
let selEnd = null;
|
|
317
|
-
if (prev)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
409
|
+
if (prev instanceof HTMLInputElement || prev instanceof HTMLTextAreaElement) {
|
|
410
|
+
try {
|
|
411
|
+
selStart = prev.selectionStart;
|
|
412
|
+
selEnd = prev.selectionEnd;
|
|
413
|
+
} catch {
|
|
414
|
+
}
|
|
321
415
|
}
|
|
322
416
|
const multiline = this.hasAttribute("multiline") || this.hasAttribute("rows");
|
|
323
|
-
const
|
|
417
|
+
const button = !multiline && this.hasAttribute("button");
|
|
418
|
+
const next = document.createElement(button ? "button" : multiline ? "textarea" : "input");
|
|
419
|
+
if (next instanceof HTMLButtonElement) next.type = "button";
|
|
324
420
|
next.setAttribute("part", "input");
|
|
325
421
|
if (this.control) this.control.replaceWith(next);
|
|
326
422
|
else this.leadingSlot.after(next);
|
|
@@ -331,23 +427,29 @@ class AInputElement extends HTMLElementBase {
|
|
|
331
427
|
}
|
|
332
428
|
this.syncDisabled();
|
|
333
429
|
this.syncStatus();
|
|
430
|
+
for (const [name, value2] of this.delegatedAria) applyShadowAria(this, next, name, value2);
|
|
431
|
+
this.queueDelegatedAria();
|
|
334
432
|
this.applyLabelAria();
|
|
335
433
|
this.applyDescriptionAria();
|
|
434
|
+
this.applyPopupAria();
|
|
336
435
|
if (multiline) this.configureTextarea(next);
|
|
337
436
|
const value = initial ?? this.pendingValue ?? this.getAttribute("value") ?? this.getAttribute("defaultvalue") ?? "";
|
|
338
437
|
next.value = value;
|
|
438
|
+
this.syncButtonPresentation();
|
|
339
439
|
next.addEventListener("input", this.onInput);
|
|
340
440
|
next.addEventListener("change", this.onChange);
|
|
341
441
|
next.addEventListener("focus", this.onFocus);
|
|
342
442
|
next.addEventListener("blur", this.onBlur);
|
|
343
443
|
if (refocus) {
|
|
344
444
|
next.focus();
|
|
345
|
-
if (selStart != null)
|
|
346
|
-
|
|
347
|
-
|
|
445
|
+
if (selStart != null && (next instanceof HTMLInputElement || next instanceof HTMLTextAreaElement)) {
|
|
446
|
+
try {
|
|
447
|
+
next.setSelectionRange(selStart, selEnd ?? selStart);
|
|
448
|
+
} catch {
|
|
449
|
+
}
|
|
348
450
|
}
|
|
349
451
|
}
|
|
350
|
-
this.
|
|
452
|
+
this.syncFormValue(value);
|
|
351
453
|
this.updateValidity();
|
|
352
454
|
this.updateFilled();
|
|
353
455
|
this.syncAutoHeight();
|
|
@@ -387,6 +489,7 @@ class AInputElement extends HTMLElementBase {
|
|
|
387
489
|
forward(name, value) {
|
|
388
490
|
const c = this.control;
|
|
389
491
|
if (!c) return;
|
|
492
|
+
if (c instanceof HTMLButtonElement) return;
|
|
390
493
|
if (c instanceof HTMLTextAreaElement && name === "type") return;
|
|
391
494
|
if (BOOL_FORWARDED.has(name)) c.toggleAttribute(name, value != null);
|
|
392
495
|
else if (value == null) c.removeAttribute(name);
|
|
@@ -395,6 +498,16 @@ class AInputElement extends HTMLElementBase {
|
|
|
395
498
|
syncDisabled() {
|
|
396
499
|
if (this.control) this.control.disabled = this.hasAttribute("disabled") || this.formDisabled;
|
|
397
500
|
}
|
|
501
|
+
syncButtonPresentation() {
|
|
502
|
+
const button = this.control;
|
|
503
|
+
if (!(button instanceof HTMLButtonElement)) return;
|
|
504
|
+
const value = button.value;
|
|
505
|
+
button.textContent = value || this.getAttribute("placeholder") || "";
|
|
506
|
+
button.classList.toggle("placeholder", !value);
|
|
507
|
+
}
|
|
508
|
+
syncFormValue(value) {
|
|
509
|
+
this.internals?.setFormValue(this.control instanceof HTMLButtonElement ? null : value);
|
|
510
|
+
}
|
|
398
511
|
/** Reflect `status` into the control's `aria-invalid` and the `:state(invalid)`
|
|
399
512
|
* custom state. Called on `status` change AND from buildControl — so a field
|
|
400
513
|
* that mounts already `status="critical"` gets `:state(invalid)` on the FIRST
|
|
@@ -402,7 +515,8 @@ class AInputElement extends HTMLElementBase {
|
|
|
402
515
|
* `ready` is false and the early-return skips it). */
|
|
403
516
|
syncStatus() {
|
|
404
517
|
const critical = this.getAttribute("status") === "critical";
|
|
405
|
-
this.
|
|
518
|
+
const explicit = this.delegatedAria.get("aria-invalid");
|
|
519
|
+
this.control?.setAttribute("aria-invalid", explicit ?? (critical ? "true" : "false"));
|
|
406
520
|
try {
|
|
407
521
|
critical ? this.internals?.states?.add("invalid") : this.internals?.states?.delete("invalid");
|
|
408
522
|
} catch {
|
|
@@ -410,7 +524,7 @@ class AInputElement extends HTMLElementBase {
|
|
|
410
524
|
}
|
|
411
525
|
onInput = (event) => {
|
|
412
526
|
const v = this.control?.value ?? "";
|
|
413
|
-
this.
|
|
527
|
+
this.syncFormValue(v);
|
|
414
528
|
this.updateValidity();
|
|
415
529
|
this.updateFilled();
|
|
416
530
|
this.syncAutoHeight();
|
|
@@ -443,7 +557,7 @@ class AInputElement extends HTMLElementBase {
|
|
|
443
557
|
applyLabelAria() {
|
|
444
558
|
const c = this.control;
|
|
445
559
|
if (!c) return;
|
|
446
|
-
if (this.
|
|
560
|
+
if (this.delegatedAria.has("aria-label") || this.delegatedAria.has("aria-labelledby")) return;
|
|
447
561
|
const text = this.labelSlot.assignedNodes().map((n) => n.textContent ?? "").join(" ").trim();
|
|
448
562
|
if (text) c.setAttribute("aria-label", text);
|
|
449
563
|
else c.removeAttribute("aria-label");
|
|
@@ -454,11 +568,22 @@ class AInputElement extends HTMLElementBase {
|
|
|
454
568
|
applyDescriptionAria() {
|
|
455
569
|
const c = this.control;
|
|
456
570
|
if (!c) return;
|
|
457
|
-
if (this.
|
|
571
|
+
if (this.delegatedAria.has("aria-description") || this.delegatedAria.has("aria-describedby")) return;
|
|
458
572
|
const text = this.hintSlot.assignedNodes().map((n) => n.textContent ?? "").join(" ").trim();
|
|
459
573
|
if (text) c.setAttribute("aria-description", text);
|
|
460
574
|
else c.removeAttribute("aria-description");
|
|
461
575
|
}
|
|
576
|
+
applyPopupAria() {
|
|
577
|
+
const control = this.control;
|
|
578
|
+
if (!control) return;
|
|
579
|
+
try {
|
|
580
|
+
if (!this.delegatedAria.has("aria-controls") && "ariaControlsElements" in control)
|
|
581
|
+
control.ariaControlsElements = this.popupControls ? [this.popupControls] : null;
|
|
582
|
+
if (!this.delegatedAria.has("aria-activedescendant") && "ariaActiveDescendantElement" in control)
|
|
583
|
+
control.ariaActiveDescendantElement = this.popupActiveDescendant;
|
|
584
|
+
} catch {
|
|
585
|
+
}
|
|
586
|
+
}
|
|
462
587
|
updateFilled() {
|
|
463
588
|
if (this.value) this.internals?.states?.add("filled");
|
|
464
589
|
else this.internals?.states?.delete("filled");
|
|
@@ -481,7 +606,8 @@ class AInputElement extends HTMLElementBase {
|
|
|
481
606
|
set value(v) {
|
|
482
607
|
this.pendingValue = v;
|
|
483
608
|
if (this.control && this.control.value !== v) this.control.value = v;
|
|
484
|
-
this.
|
|
609
|
+
this.syncButtonPresentation();
|
|
610
|
+
this.syncFormValue(v);
|
|
485
611
|
this.updateValidity();
|
|
486
612
|
this.updateFilled();
|
|
487
613
|
this.syncAutoHeight();
|
|
@@ -497,7 +623,8 @@ class AInputElement extends HTMLElementBase {
|
|
|
497
623
|
clear() {
|
|
498
624
|
if (!this.control) return;
|
|
499
625
|
this.control.value = "";
|
|
500
|
-
this.
|
|
626
|
+
this.syncButtonPresentation();
|
|
627
|
+
this.syncFormValue("");
|
|
501
628
|
this.updateValidity();
|
|
502
629
|
this.updateFilled();
|
|
503
630
|
this.syncAutoHeight();
|
|
@@ -545,6 +672,18 @@ class AInputElement extends HTMLElementBase {
|
|
|
545
672
|
this.value = state ?? "";
|
|
546
673
|
}
|
|
547
674
|
}
|
|
675
|
+
for (const name of SHADOW_ARIA_ATTRIBUTES) {
|
|
676
|
+
Object.defineProperty(AInputElement.prototype, ariaAttributeProperty(name), {
|
|
677
|
+
configurable: true,
|
|
678
|
+
enumerable: true,
|
|
679
|
+
get() {
|
|
680
|
+
return this[READ_DELEGATED_ARIA](name);
|
|
681
|
+
},
|
|
682
|
+
set(value) {
|
|
683
|
+
this[WRITE_DELEGATED_ARIA](name, value);
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
}
|
|
548
687
|
function register_a_input() {
|
|
549
688
|
if (typeof customElements === "undefined") return;
|
|
550
689
|
if (!customElements.get("a-input")) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer anta.components{a-loader{color:var(--text-3)}@media not (forced-colors:active){a-loader[tone=brand]{color:var(--text-2-brand)}a-loader[tone=info]{color:var(--text-2-info)}a-loader[tone=success]{color:var(--text-2-success)}a-loader[tone=warning]{color:var(--text-2-warning)}a-loader[tone=critical]{color:var(--text-2-critical)}}:where(a-loader,a-icon[shape=loader]){display:inline-block;inline-size:var(--loader-size, var(--icon-size, 16px));block-size:var(--loader-size, var(--icon-size, 16px));flex:none;vertical-align:middle;border-radius:50%;animation:loader-spin var(--loader-speed, .75s) linear infinite;animation-delay:-9999s}a-loader{background:conic-gradient(from 0deg,color-mix(in oklch,currentColor 6%,transparent),color-mix(in oklch,currentColor 70%,transparent))}a-icon[shape=loader]{-webkit-mask-image:conic-gradient(from 0deg,color-mix(in oklch,#000 6%,transparent),color-mix(in oklch,#000 70%,transparent));mask-image:conic-gradient(from 0deg,color-mix(in oklch,#000 6%,transparent),color-mix(in oklch,#000 75%,transparent))}a-loader[value]{background:conic-gradient(from 0deg,color-mix(in oklch,currentColor 60%,transparent) 0,color-mix(in oklch,currentColor 75%,transparent) var(--loader-value, 0%),color-mix(in oklch,currentColor 6%,transparent) var(--loader-value, 0%) 100%);animation:none}@keyframes loader-spin{to{transform:rotate(1turn)}}@media(forced-colors:active){a-loader{forced-color-adjust:none;color:CanvasText}}}
|
|
1
|
+
@layer base,anta,components,utilities;@layer anta.reset,anta.components,anta.theme;@layer anta.components{a-loader{color:var(--text-3)}@media not (forced-colors:active){a-loader[tone=brand]{color:var(--text-2-brand)}a-loader[tone=info]{color:var(--text-2-info)}a-loader[tone=success]{color:var(--text-2-success)}a-loader[tone=warning]{color:var(--text-2-warning)}a-loader[tone=critical]{color:var(--text-2-critical)}}:where(a-loader,a-icon[shape=loader]){display:inline-block;inline-size:var(--loader-size, var(--icon-size, 16px));block-size:var(--loader-size, var(--icon-size, 16px));flex:none;vertical-align:middle;border-radius:50%;animation:loader-spin var(--loader-speed, .75s) linear infinite;animation-delay:-9999s}a-loader{background:conic-gradient(from 0deg,color-mix(in oklch,currentColor 6%,transparent),color-mix(in oklch,currentColor 70%,transparent))}a-icon[shape=loader]{-webkit-mask-image:conic-gradient(from 0deg,color-mix(in oklch,#000 6%,transparent),color-mix(in oklch,#000 70%,transparent));mask-image:conic-gradient(from 0deg,color-mix(in oklch,#000 6%,transparent),color-mix(in oklch,#000 75%,transparent))}a-loader[value]{background:conic-gradient(from 0deg,color-mix(in oklch,currentColor 60%,transparent) 0,color-mix(in oklch,currentColor 75%,transparent) var(--loader-value, 0%),color-mix(in oklch,currentColor 6%,transparent) var(--loader-value, 0%) 100%);animation:none}@keyframes loader-spin{to{transform:rotate(1turn)}}@media(forced-colors:active){a-loader{forced-color-adjust:none;color:CanvasText}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer anta.components{a-menu-group:not(:defined){display:none}a-menu-group{display:flex;flex-direction:column;gap:1px}a-menu-group-label{display:block;padding:6px 8px 2px;color:var(--text-5);font-size:.75em;font-weight:600;letter-spacing:.
|
|
1
|
+
@layer base,anta,components,utilities;@layer anta.reset,anta.components,anta.theme;@layer anta.components{a-menu-group:not(:defined){display:none}a-menu-group{display:flex;flex-direction:column;gap:1px}a-menu-group-label{display:block;padding:6px 8px 2px;color:var(--text-5);font-size:.75em;font-weight:600;letter-spacing:.03em;text-transform:uppercase;user-select:none}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer anta.components{a-menu-item:not(:defined){display:none}a[data-anta-menu-item]{text-decoration:none}a-menu-item,a[data-anta-menu-item]{--menu-item-color: var(--text-2);--menu-item-icon-color: var(--text-3);--menu-item-hint-color: var(--text-3);--menu-item-hover: 5
|
|
1
|
+
@layer base,anta,components,utilities;@layer anta.reset,anta.components,anta.theme;@layer anta.components{a-menu-item:not(:defined){display:none}a[data-anta-menu-item]{text-decoration:none}a-menu-item,a[data-anta-menu-item]{--menu-item-color: var(--text-2);--menu-item-icon-color: var(--text-3);--menu-item-hint-color: var(--text-3);--menu-item-hover-bg: light-dark( color-mix(in oklch, currentColor 5%, transparent), color-mix(in oklch, currentColor 10%, transparent) );--menu-item-active-bg: light-dark( color-mix(in oklch, currentColor 8%, transparent), color-mix(in oklch, currentColor 14%, transparent) );--menu-item-selected-bg: var(--menu-item-active-bg);--menu-item-timing-in: 60ms ease-in-out;--menu-item-timing-out: .28s ease-out;--menu-item-padding-x: 8px;--menu-item-padding-y: 6px;display:flex;flex-shrink:0;align-items:center;gap:.6ch;box-sizing:border-box;width:100%;min-height:28px;padding-block:var(--menu-item-padding-y);padding-inline:var(--menu-item-padding-x);border-radius:var(--radius-sm, 4px);color:var(--menu-item-color);background:transparent;transition:background-color var(--menu-item-timing-out);font:inherit;font-variation-settings:inherit;font-size:14px;line-height:16px;text-align:left;white-space:nowrap;cursor:pointer;user-select:none;outline:none}a-menu[round] a-menu-item,a-menu[round] a[data-anta-menu-item]{border-radius:999px}a-menu-item:hover,a-menu-item:focus-visible,a[data-anta-menu-item]:hover,a[data-anta-menu-item]:focus-visible,a-menu-item:has(>a-menu:state(open)),a-menu-item:state(active){background:var(--menu-item-hover-bg);transition:background-color var(--menu-item-timing-in)}a-menu-item:active,a[data-anta-menu-item]:active{background:var(--menu-item-active-bg);transition:none}a-menu-item[selected],a[data-anta-menu-item][aria-current=true]{background:var(--menu-item-selected-bg)}a-menu-item:focus-visible,a[data-anta-menu-item]:focus-visible{outline:1px solid var(--focus-ring);outline-offset:1px}a-menu-item>a-menu-item-label,a-menu-item>a-menu-item-text,a[data-anta-menu-item]>a-menu-item-label,a[data-anta-menu-item]>a-menu-item-text{flex:1 1 auto;min-width:0}a-menu-item>a-menu-item-text,a[data-anta-menu-item]>a-menu-item-text{display:flex;flex-direction:column}a-menu-item:has(>a-menu-item-text),a[data-anta-menu-item]:has(>a-menu-item-text){align-items:flex-start}a-menu-item-label{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis}a-menu-item-hint{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;margin-block-start:1px;color:var(--menu-item-hint-color);font-size:12px;line-height:15px}a-menu-item>a-icon,a[data-anta-menu-item]>a-icon{flex:none;--icon-size: 16px;color:var(--menu-item-icon-color)}a-menu-item>a-checkbox,a-menu-item>a-radio{flex:none;--checkbox-gap: 0;--radio-gap: 0;pointer-events:none}a-menu-item>a-checkbox:before,a-menu-item>a-checkbox:after,a-menu-item>a-radio:before{margin-block-start:0}a-menu-item>a-radio:after{margin-block-start:calc((var(--radio-control-size) - (var(--radio-dot-size) - var(--_radio-dot-adjust))) / 2)}a-menu-item:has(>:is(a-icon,a-checkbox,a-radio,[data-indicator]):first-child:not(:only-child)),a[data-anta-menu-item]:has(>:is(a-icon,[data-indicator]):first-child:not(:only-child)){padding-inline-start:var(--menu-item-padding-y)}a-menu-item:not([submenu]):has(>a-icon:last-child:not(:only-child)),a[data-anta-menu-item]:has(>a-icon:last-child:not(:only-child)){padding-inline-end:max(0px,var(--menu-item-padding-x) - 2px)}a-menu-item>kbd,a[data-anta-menu-item]>kbd{flex:none;margin-left:auto;padding-left:12px;color:var(--text-5);font:inherit;font-variation-settings:inherit;font-size:1em;letter-spacing:.1ch;white-space:nowrap}a-menu-item[submenu]>a-icon:last-of-type{margin-left:auto}a-menu-item[submenu]>a-icon:last-of-type,a-menu-item>a-icon:last-child:not(:only-child),a[data-anta-menu-item]>a-icon:last-child:not(:only-child){position:relative;inset-inline-end:-2px}a-menu-item[tone=brand],a-menu-item[tone=info],a-menu-item[tone=success],a-menu-item[tone=warning],a-menu-item[tone=critical],a[data-anta-menu-item][tone=brand],a[data-anta-menu-item][tone=info],a[data-anta-menu-item][tone=success],a[data-anta-menu-item][tone=warning],a[data-anta-menu-item][tone=critical]{--menu-item-icon-color: var(--menu-item-color)}a-menu-item[tone=brand],a[data-anta-menu-item][tone=brand]{--menu-item-color: var(--text-2-brand);--menu-item-hint-color: var(--text-3-brand)}a-menu-item[tone=info],a[data-anta-menu-item][tone=info]{--menu-item-color: var(--text-2-info);--menu-item-hint-color: var(--text-3-info)}a-menu-item[tone=success],a[data-anta-menu-item][tone=success]{--menu-item-color: var(--text-2-success);--menu-item-hint-color: var(--text-3-success)}a-menu-item[tone=warning],a[data-anta-menu-item][tone=warning]{--menu-item-color: var(--text-2-warning);--menu-item-hint-color: var(--text-3-warning)}a-menu-item[tone=critical],a[data-anta-menu-item][tone=critical]{--menu-item-color: var(--text-2-critical);--menu-item-hint-color: var(--text-3-critical)}a-menu-item[tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=info],[tone=success],[tone=warning],[tone=critical]),a[data-anta-menu-item][tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=info],[tone=success],[tone=warning],[tone=critical]){--menu-item-tone-source: var(--text-2);--menu-item-color: light-dark( oklch(from var(--menu-item-tone-source) .45 c h), oklch(from var(--menu-item-tone-source) .78 c h) );--menu-item-icon-color: var(--menu-item-color);--menu-item-hint-color: light-dark( oklch(from var(--menu-item-tone-source) .45 c h / .8), oklch(from var(--menu-item-tone-source) .78 c h / .8) );@supports (color: attr(probe type(<color>),red)){--menu-item-tone-source: attr(tone type(<color>), var(--text-2))}}a-menu-item[disabled],a[data-anta-menu-item][aria-disabled=true]{--menu-item-color: var(--text-5);--menu-item-icon-color: var(--text-5);--menu-item-hint-color: var(--text-5);cursor:default;pointer-events:none}}
|
|
@@ -15,6 +15,7 @@ class AMenuItemElement extends HTMLElementBase {
|
|
|
15
15
|
if (!this.internals) return;
|
|
16
16
|
if (on) this.internals?.states?.add("active");
|
|
17
17
|
else this.internals?.states?.delete("active");
|
|
18
|
+
this.internals.ariaSelected = this.getAttribute("role") === "option" ? on ? "true" : "false" : null;
|
|
18
19
|
}
|
|
19
20
|
get active() {
|
|
20
21
|
return this.internals?.states?.has("active") ?? false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer anta.components{a-menu-separator:not(:defined){display:none}a-menu-separator{--menu-separator-label-size: 13px;display:block;flex-shrink:0;height:1px;margin:2px 4px;background:var(--border-5)}a-menu-separator:not(:empty){height:auto;margin:0;padding:6px 8px;background:none;color:var(--text-3);font-size:var(--menu-separator-label-size);line-height:1.3;user-select:none}}
|
|
1
|
+
@layer base,anta,components,utilities;@layer anta.reset,anta.components,anta.theme;@layer anta.components{a-menu-separator:not(:defined){display:none}a-menu-separator{--menu-separator-label-size: 13px;display:block;flex-shrink:0;height:1px;margin:2px 4px;background:var(--border-5)}a-menu-separator:not(:empty){height:auto;margin:0;padding:6px 8px;background:none;color:var(--text-3);font-size:var(--menu-separator-label-size);line-height:1.3;user-select:none}}
|
package/dist/elements/a-menu.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer anta.components{a-menu:not(:defined){display:none}a-menu{--menu-bg: color-mix(in oklch, var(--bg-1) 90%, transparent);--menu-radius: var(--radius-md, 8px);--menu-border: 1px solid var(--border-3);--menu-shadow: 0 2px 6px color-mix(in oklch, var(--text-1) 8%, transparent), 0 8px 24px color-mix(in oklch, var(--text-1) 10%, transparent);--menu-padding: 4px;--menu-min-width: 88px;--menu-backdrop-filter: blur(20px);--menu-width-duration: .16s}@media(prefers-reduced-motion:reduce){a-menu{--menu-width-duration: 0}}a-menu[round]{--menu-radius: 20px;@supports (border-radius: attr(probe type(<length>),1px)){--menu-radius: attr(round type(<length>), 20px)}}.dark a-menu{--menu-
|
|
1
|
+
@layer base,anta,components,utilities;@layer anta.reset,anta.components,anta.theme;@layer anta.components{a-menu:not(:defined){display:none}a-menu{--menu-bg: light-dark( color-mix(in oklch, var(--bg-1) 90%, transparent), color-mix(in oklch, var(--bg-1) 78%, transparent) );--menu-radius: var(--radius-md, 8px);--menu-border: 1px solid var(--border-3);--menu-shadow: 0 2px 6px color-mix(in oklch, var(--text-1) 8%, transparent), 0 8px 24px color-mix(in oklch, var(--text-1) 10%, transparent);--menu-padding: 4px;--menu-min-width: 88px;--menu-backdrop-filter: blur(20px);--menu-width-duration: .16s}@media(prefers-reduced-motion:reduce){a-menu{--menu-width-duration: 0}}a-menu[round]{--menu-radius: 20px;@supports (border-radius: attr(probe type(<length>),1px)){--menu-radius: attr(round type(<length>), 20px)}}.dark a-menu{--menu-shadow: 0 2px 8px color-mix(in oklch, black 50%, transparent), 0 12px 32px color-mix(in oklch, black 40%, transparent), inset 0 0 0 1px color-mix(in oklch, white 8%, transparent)}}
|
|
@@ -42,6 +42,7 @@ export declare class AMenuElement extends HTMLElementBase {
|
|
|
42
42
|
private typeTimer?;
|
|
43
43
|
private activeItem;
|
|
44
44
|
private comboObserver?;
|
|
45
|
+
private accessibilityObserver?;
|
|
45
46
|
private _flippedTop;
|
|
46
47
|
private _flippedSide;
|
|
47
48
|
constructor();
|
|
@@ -73,9 +74,7 @@ export declare class AMenuElement extends HTMLElementBase {
|
|
|
73
74
|
* `.focus()` on one silently fails). `getClientRects` is the fallback where
|
|
74
75
|
* `checkVisibility` isn't available. */
|
|
75
76
|
private isVisible;
|
|
76
|
-
/**
|
|
77
|
-
* End / type-ahead navigation). Same visibility / disabled / ownership
|
|
78
|
-
* filter — just narrowed to `a-menu-item`. */
|
|
77
|
+
/** Custom menu rows that support the combobox cursor and selection state. */
|
|
79
78
|
private focusableItems;
|
|
80
79
|
/** The rows the arrow keys / Home / End / initial-focus step between:
|
|
81
80
|
* `focusableItems()` PLUS native-anchor link items (`<a data-anta-menu-item>`),
|
|
@@ -83,10 +82,7 @@ export declare class AMenuElement extends HTMLElementBase {
|
|
|
83
82
|
* custom-element-only because the combobox cursor (`setActive`) and selection
|
|
84
83
|
* seating are `a-menu-item` affordances a plain link doesn't carry. */
|
|
85
84
|
private navigableItems;
|
|
86
|
-
/**
|
|
87
|
-
* like inputs / sliders / buttons), in DOM order, visible and enabled —
|
|
88
|
-
* used to trap Tab within the open menu. Submenu contents are excluded
|
|
89
|
-
* (their nearest `a-menu` is the submenu). */
|
|
85
|
+
/** Tab stops in rendered order, excluding controls owned by nested menus. */
|
|
90
86
|
private focusables;
|
|
91
87
|
/** On open, seat initial focus like a native `<select>` / macOS menu: a menu
|
|
92
88
|
* carrying a current value opens *at* that value, not at the top. Brings the
|
|
@@ -107,10 +103,9 @@ export declare class AMenuElement extends HTMLElementBase {
|
|
|
107
103
|
* `.scroll` mask reads; runs on scroll and after every (re)position.
|
|
108
104
|
* Shadow-internal only. */
|
|
109
105
|
private updateScrollFade;
|
|
110
|
-
/** Move the combobox cursor. Sets the item's `active`
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* `aria-activedescendant` on the light-DOM field. `null` clears the cursor. */
|
|
106
|
+
/** Move the combobox cursor. Sets the item's `active` property for its
|
|
107
|
+
* off-DOM highlight/selected state, associates it directly with an Anta
|
|
108
|
+
* Input, and reports it for raw/custom observers. `null` clears the cursor. */
|
|
114
109
|
private setActive;
|
|
115
110
|
/** Re-seat the cursor on the first option — but only once the filter has input.
|
|
116
111
|
* An empty filter (e.g. right after opening) shows NO active row, so the first
|
|
@@ -168,8 +163,8 @@ export declare class AMenuElement extends HTMLElementBase {
|
|
|
168
163
|
* mutates deep in its subtree, not this menu's direct children, so it won't
|
|
169
164
|
* spuriously reset the cursor. */
|
|
170
165
|
private startComboObserver;
|
|
171
|
-
/** Apply CLOSE
|
|
172
|
-
*
|
|
166
|
+
/** Apply CLOSE without notifying this menu's owner. Notify nested menus so
|
|
167
|
+
* their controlled state follows the closing parent. */
|
|
173
168
|
private hide;
|
|
174
169
|
/** Shadow-only show: open the popover and position it. `instant` positions
|
|
175
170
|
* synchronously (no rAF), so a menu opening over an already-visible one is
|