UNPKG

easy-aria

Version:

The easiest (and safest) way to manipulate ARIA attributes in HTML.

967 lines (966 loc) 27.5 kB
var x = Object.defineProperty; var E = (i, e, s) => e in i ? x(i, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : i[e] = s; var b = (i, e, s) => (E(i, typeof e != "symbol" ? e + "" : e, s), s), g = (i, e, s) => { if (!e.has(i)) throw TypeError("Cannot " + s); }; var T = (i, e, s) => (g(i, e, "read from private field"), s ? s.call(i) : e.get(i)), d = (i, e, s) => { if (e.has(i)) throw TypeError("Cannot add the same private member more than once"); e instanceof WeakSet ? e.add(i) : e.set(i, s); }, q = (i, e, s, c) => (g(i, e, "write to private field"), c ? c.call(i, s) : e.set(i, s), s); var m = (i, e, s, c) => ({ set _(h) { q(i, e, h, s); }, get _() { return T(i, e, c); } }), r = (i, e, s) => (g(i, e, "access private method"), s); var f, w, k, l, u, a, t; const n = class n { constructor(e) { /** * Sets the given `aria-*` attribute on the wrapped Element * from the un-prefixed version. */ d(this, a); /** HTML Element wrapped by `EasyAria` object. */ b(this, "el"); this.el = e; } /** * @returns The *explicit* role defined on the wrapped Element. */ getRole() { return this.el.getAttribute("role"); } /** * Sets the `role` attribute on the wrapped Element to the given value. * * @param role The value to be assigned to the `role` attribute. */ setRole(e) { if (!arguments.length) throw new TypeError( "EasyAria.setRole() requires 1 argument, but received 0." ); if (typeof e != "string") throw new TypeError('Please specify an ARIA role (e.g., "group").'); return this.el.setAttribute("role", e), this; } /** * Takes a callback function which runs immediately, and is passed the * wrapped Element. The callback's return value is discarded, and the `EasyAria` * instance is returned. * * @param callback The callback function which is passed the wrapped Element. */ call(e) { if (!arguments.length) throw new TypeError( "EasyAria.call() requires 1 argument, but received 0." ); if (typeof e != "function") throw new TypeError("EasyAria.call() requires a function."); return e.call(this, this.el), this; } // Implementation for `set()` set(e, s) { var c, h; if (!arguments.length) throw new TypeError( "EasyAria.set() requires at least 1 argument, but received 0." ); if (typeof e != "string") throw new TypeError( 'Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").' ); switch (e = e.toLowerCase(), e) { case "keyshortcuts": case "label": case "placeholder": case "roledescription": case "valuetext": if (typeof s != "string") throw new TypeError(`"aria-${e}" requires a string.`); r(this, a, t).call(this, e, String(s)); break; case "activedescendant": case "details": case "errormessage": if (s instanceof Element) r(this, a, t).call(this, e, r(c = n, l, u).call(c, s)); else if (typeof s == "string") r(this, a, t).call(this, e, s); else throw new TypeError( `"aria-${e}" requires a string, or pass an Element to use its ID.` ); break; case "controls": case "describedby": case "flowto": case "labelledby": case "owns": if (s instanceof Element) r(this, a, t).call(this, e, r(h = n, l, u).call(h, s)); else if (Array.isArray(s) || s instanceof NodeList) r(this, a, t).call(this, e, Array.prototype.map.call(s, (o) => { var y; return r(y = n, l, u).call(y, o); }).filter(Boolean).join(" ")); else if (typeof s == "string") r(this, a, t).call(this, e, s); else throw new TypeError( `"aria-${e}" requires a string, or pass an Element or Array/NodeList of Elements to use their IDs.` ); break; case "atomic": case "busy": case "disabled": case "modal": case "multiline": case "multiselectable": case "readonly": case "required": if (typeof s > "u") r(this, a, t).call(this, e, String(!0)); else switch (s) { case !0: case !1: r(this, a, t).call(this, e, String(s)); break; default: throw new TypeError( `"aria-${e}" requires a boolean value.` ); } break; case "expanded": case "grabbed": case "hidden": case "selected": if (typeof s > "u") r(this, a, t).call(this, e, String(!0)); else switch (s) { case !0: case !1: r(this, a, t).call(this, e, String(s)); break; case "undefined": r(this, a, t).call(this, e, s); break; default: throw new TypeError( `"aria-${e}" requires a boolean value, or the string "undefined".` ); } break; case "checked": case "pressed": if (typeof s > "u") r(this, a, t).call(this, e, String(!0)); else switch (s) { case !0: case !1: r(this, a, t).call(this, e, String(s)); break; case "mixed": case "undefined": r(this, a, t).call(this, e, s); break; default: throw new TypeError( `"aria-${e}" requires a boolean value, or any of the following strings: "mixed", "undefined".` ); } break; case "current": if (typeof s > "u") r(this, a, t).call(this, e, String(!0)); else switch (s) { case !0: case !1: r(this, a, t).call(this, e, String(s)); break; case "page": case "step": case "location": case "date": case "time": r(this, a, t).call(this, e, s); break; default: throw new TypeError( `"aria-${e}" requires a boolean value, or any of the following strings: "page", "step", "location", "date", "time".` ); } break; case "haspopup": if (typeof s > "u") r(this, a, t).call(this, e, String(!0)); else switch (s) { case !0: case !1: r(this, a, t).call(this, e, String(s)); break; case "menu": case "listbox": case "tree": case "grid": case "dialog": r(this, a, t).call(this, e, s); break; default: throw new TypeError( `"aria-${e}" requires a boolean value, or any of the following strings: "menu", "listbox", "tree", "grid", "dialog".` ); } break; case "invalid": if (typeof s > "u") r(this, a, t).call(this, e, String(!0)); else switch (s) { case !0: case !1: r(this, a, t).call(this, e, String(s)); break; case "grammar": case "spelling": r(this, a, t).call(this, e, s); break; default: throw new TypeError( `"aria-${e}" requires a boolean value, or any of the following strings: "grammar", "spelling".` ); } break; case "autocomplete": switch (s) { case "both": case "inline": case "list": case "none": r(this, a, t).call(this, e, s); break; default: throw new TypeError( `"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}` ); } break; case "dropeffect": switch (s) { case "copy": case "execute": case "link": case "move": case "none": case "popup": r(this, a, t).call(this, e, s); break; default: throw new TypeError( `"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}` ); } break; case "live": switch (s) { case "assertive": case "off": case "polite": r(this, a, t).call(this, e, s); break; default: throw new TypeError( `"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}` ); } break; case "orientation": switch (s) { case "horizontal": case "undefined": case "vertical": r(this, a, t).call(this, e, s); break; default: throw new TypeError( `"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}` ); } break; case "relevant": switch (s) { case "additions": case "additions text": case "all": case "removals": case "text": r(this, a, t).call(this, e, s); break; default: throw new TypeError( `"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}` ); } break; case "sort": switch (s) { case "ascending": case "descending": case "none": case "other": r(this, a, t).call(this, e, s); break; default: throw new TypeError( `"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}` ); } break; case "colcount": case "colindex": case "colspan": case "level": case "posinset": case "rowcount": case "rowindex": case "rowspan": case "setsize": case "valuemax": case "valuemin": case "valuenow": { if (typeof s == "bigint" || typeof s == "number" || typeof s == "string") { const o = Number(s); if (Number.isNaN(o)) throw new TypeError( `"aria-${e}" requires a number or numerical string.` ); r(this, a, t).call(this, e, String(o)); } else throw new TypeError( `"aria-${e}" requires a number or numerical string.` ); break; } default: { const o = e; throw new TypeError( `Invalid attribute: "aria-${o}". Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").` ); } } return this; } /** * Removes the given aria attribute from the wrapped Element. * * @param attribute The aria attribute to remove, without the `aria-` prefix. */ unset(e) { if (!arguments.length) throw new TypeError( "EasyAria.unset() requires 1 argument, but received 0." ); if (typeof e != "string") throw new TypeError( 'Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").' ); switch (e = e.toLowerCase(), e) { case "keyshortcuts": case "label": case "placeholder": case "roledescription": case "valuetext": case "activedescendant": case "details": case "errormessage": case "controls": case "describedby": case "flowto": case "labelledby": case "owns": case "atomic": case "busy": case "disabled": case "modal": case "multiline": case "multiselectable": case "readonly": case "required": case "expanded": case "grabbed": case "hidden": case "selected": case "checked": case "current": case "haspopup": case "invalid": case "pressed": case "autocomplete": case "dropeffect": case "live": case "orientation": case "relevant": case "sort": case "colcount": case "colindex": case "colspan": case "level": case "posinset": case "rowcount": case "rowindex": case "rowspan": case "setsize": case "valuemax": case "valuemin": case "valuenow": this.el.removeAttribute(`aria-${e}`); break; default: { const s = e; throw new TypeError( `Invalid attribute: "aria-${s}". Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").` ); } } return this; } // Implementation for `get()` get(e) { if (!arguments.length) throw new TypeError( "EasyAria.get() requires 1 argument, but received 0." ); if (typeof e != "string") throw new TypeError( 'Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").' ); e = e.toLowerCase(); const s = this.el.getAttribute(`aria-${String(e)}`); switch (e) { case "activedescendant": case "controls": case "describedby": case "details": case "errormessage": case "flowto": case "keyshortcuts": case "label": case "labelledby": case "owns": case "placeholder": case "roledescription": case "valuetext": return s; case "autocomplete": switch (s) { case "both": case "inline": case "list": case "none": return s; } break; case "dropeffect": switch (s) { case "copy": case "execute": case "link": case "move": case "none": case "popup": return s; } break; case "live": switch (s) { case "assertive": case "off": case "polite": return s; } break; case "orientation": switch (s) { case "horizontal": case "undefined": case "vertical": return s; } break; case "relevant": switch (s) { case "additions": case "additions text": case "all": case "removals": case "text": return s; } break; case "sort": switch (s) { case "ascending": case "descending": case "none": case "other": return s; } break; case "expanded": case "grabbed": case "hidden": case "selected": switch (s) { case "true": return !0; case "false": return !1; case "undefined": return s; } break; case "checked": case "pressed": switch (s) { case "true": return !0; case "false": return !1; case "mixed": case "undefined": return s; } break; case "current": switch (s) { case "true": return !0; case "false": return !1; case "page": case "step": case "location": case "date": case "time": return s; } break; case "haspopup": switch (s) { case "true": return !0; case "false": return !1; case "menu": case "listbox": case "tree": case "grid": case "dialog": return s; } break; case "invalid": switch (s) { case "true": return !0; case "false": return !1; case "grammar": case "spelling": return s; } break; case "atomic": case "busy": case "disabled": case "modal": case "multiline": case "multiselectable": case "readonly": case "required": switch (s) { case "true": return !0; case "false": return !1; } break; case "colcount": case "colindex": case "colspan": case "level": case "posinset": case "rowcount": case "rowindex": case "rowspan": case "setsize": case "valuemax": case "valuemin": case "valuenow": { const c = Number(s); if (!Number.isNaN(c)) return c; break; } default: { const c = e; throw new TypeError( `Invalid attribute: "aria-${c}". Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").` ); } } return null; } // ================== Convenience methods ================== // =============== Setter methods =============== /** Sets `aria-checked` to `true`. */ check() { return this.set("checked"); } /** Sets `aria-checked` to `false`. */ uncheck() { return this.set("checked", !1); } /** * Toggles the state of `aria-checked` between `true` and `false`. * Sets it to `true` if its current value is neither. */ toggleChecked() { return this.set("checked", !this.isChecked()); } /** * Sets `aria-controls` to the given value. * * @param value A space-separated string of ID references, an Element, * or array/NodeList of Elements whose ID(s) to use for the attribute. */ control(e) { return this.set("controls", e); } /** * Sets `aria-describedby` to the given value. * * @param value A space-separated string of ID references, an Element, * or array/NodeList of Elements whose ID(s) to use for the attribute. */ describeWith(e) { return this.set("describedby", e); } /** Sets `aria-disabled` to `true`. */ disable() { return this.set("disabled"); } /** Sets `aria-disabled` to `false`. */ enable() { return this.set("disabled", !1); } /** * Toggles the state of `aria-disabled` between `true` and `false`. * Sets it to `true` if its current value is neither. */ toggleDisabled() { return this.set("disabled", !this.isDisabled()); } /** Sets `aria-expanded` to `true`. */ expand() { return this.set("expanded"); } /** Sets `aria-expanded` to `false`. */ collapse() { return this.set("expanded", !1); } /** * Toggles the state of `aria-expanded` between `true` and `false`. * Sets it to `true` if its current value is neither. */ toggleExpanded() { return this.set("expanded", !this.isExpanded()); } /** * Sets `aria-flowto` to the given value. * * @param value A space-separated string of ID references, an Element, * or array/NodeList of Elements whose ID(s) to use for the attribute. */ flowTo(e) { return this.set("flowto", e); } /** * Sets `aria-grabbed` to `true`. * * @deprecated in ARIA 1.1. * The `aria-grabbed` state is expected to be replaced by a new feature * in a future version of WAI-ARIA. Authors are therefore advised to treat * `aria-grabbed` as deprecated. */ grab() { return this.set("grabbed"); } /** * Sets `aria-grabbed` to `false`. * * @deprecated in ARIA 1.1. * The `aria-grabbed` state is expected to be replaced by a new feature * in a future version of WAI-ARIA. Authors are therefore advised to treat * `aria-grabbed` as deprecated. */ ungrab() { return this.set("grabbed", !1); } /** * Toggles the state of `aria-grabbed` between `true` and `false`. * Sets it to `true` if its current value is neither. * * @deprecated in ARIA 1.1. * The `aria-grabbed` state is expected to be replaced by a new feature * in a future version of WAI-ARIA. Authors are therefore advised to treat * `aria-grabbed` as deprecated. */ toggleGrabbed() { return this.set("grabbed", !this.isGrabbed()); } /** Sets `aria-hidden` to `true`. */ hide() { return this.set("hidden"); } /** Sets `aria-hidden` to `false`. */ unhide() { return this.set("hidden", !1); } /** * Toggles the state of `aria-expanded` between `true` and `false`. * Sets it to `true` if its current value is neither. */ toggleHidden() { return this.set("hidden", !this.isHidden()); } /** Sets `aria-label` to the given string. */ label(e) { return this.set("label", e); } /** * Sets `aria-labelledby` to the given value. * * @param value A space-separated string of ID references, an Element, * or array/NodeList of Elements whose ID(s) to use for the attribute. */ labelWith(e) { return this.set("labelledby", e); } /** * Sets `aria-owns` to the given value. * * @param value A space-separated string of ID references, an Element, * or array/NodeList of Elements whose ID(s) to use for the attribute. */ own(e) { return this.set("owns", e); } /** Sets `aria-pressed` to `true`. */ press() { return this.set("pressed"); } /** Sets `aria-pressed` to `false`. */ unpress() { return this.set("pressed", !1); } /** * Toggles the state of `aria-pressed` between `true` and `false`. * Sets it to `true` if its current value is neither. */ togglePressed() { return this.set("pressed", !this.isPressed()); } /** Sets `aria-required` to `true`. */ require() { return this.set("required"); } /** Sets `aria-required` to `false`. */ unrequire() { return this.set("required", !1); } /** * Toggles the state of `aria-required` between `true` and `false`. */ toggleRequired() { return this.set("required", !this.isRequired()); } /** Sets `aria-roledescription` to the given string. */ describeRole(e) { return this.set("roledescription", e); } /** Sets `aria-selected` to `true`. */ select() { return this.set("selected"); } /** Sets `aria-selected` to `false`. */ unselect() { return this.set("selected", !1); } /** * Toggles the state of `aria-selected` between `true` and `false`. * Sets it to `true` if its current value is neither. */ toggleSelected() { return this.set("selected", !this.isSelected()); } // =============== Boolean methods =============== /** * @returns `true` if `aria-atomic` is set to `true`, otherwise returns `false`. */ isAtomic() { return this.get("atomic") === !0; } /** * @returns `true` if `aria-busy` is set to `true`, otherwise returns `false`. */ isBusy() { return this.get("busy") === !0; } /** * @returns `true` if `aria-checked` is set to `true`, otherwise returns `false`. */ isChecked() { return this.get("checked") === !0; } /** * @param value Any of the tokens supported by `aria-current`, except `true` or `false`. * @returns `true` if `aria-current` is set to the given value, * or any of its supported values if none is provided, except `false`, * in which case it returns `false`. */ isCurrent(e) { const s = this.get("current"); return e ? s === e : s === !0 || s === "page" || s === "step" || s === "location" || s === "date" || s === "time"; } /** * @returns `true` if `aria-disabled` is set to `true`, otherwise returns `false`. */ isDisabled() { return this.get("disabled") === !0; } /** * @returns `true` if `aria-expanded` is set to `true`, otherwise returns `false`. */ isExpanded() { return this.get("expanded") === !0; } /** * @returns `true` if `aria-grabbed` is set to `true`, otherwise returns `false`. * @deprecated in ARIA 1.1. * The `aria-grabbed` state is expected to be replaced by a new feature * in a future version of WAI-ARIA. Authors are therefore advised to treat * `aria-grabbed` as deprecated. */ isGrabbed() { return this.get("grabbed") === !0; } /** * @param value Any of the tokens supported by `aria-haspopup`, except `true` or `false`. * @returns `true` if `aria-haspopup` is set to the given value, * or any of its supported values if none is provided, except `false`, * in which case it returns `false`. */ hasPopup(e) { const s = this.get("haspopup"); return e ? s === e : s === !0 || s === "menu" || s === "listbox" || s === "tree" || s === "grid" || s === "dialog"; } /** * @returns `true` if `aria-hidden` is set to `true` only on the wrapped Element. * This method does not consider whether an ancestor has `aria-hidden` set to `true`. */ isHidden() { return this.get("hidden") === !0; } /** * @param value Any of the tokens supported by `aria-invalid`, except `true` or `false`. * @returns `true` if `aria-invalid` is set to the given value, * or any of its supported values if none is provided, except `false`, * in which case it returns `false`. */ isInvalid(e) { const s = this.get("invalid"); return e ? s === e : s === !0 || s === "grammar" || s === "spelling"; } /** * @returns `true` if `aria-modal` is set to `true`, otherwise returns `false`. */ isModal() { return this.get("modal") === !0; } /** * @returns `true` if `aria-multiline` is set to `true`, otherwise returns `false`. */ isMultiline() { return this.get("multiline") === !0; } /** * @returns `true` if `aria-multiselectable` is set to `true`, otherwise returns `false`. */ isMultiselectable() { return this.get("multiselectable") === !0; } /** * @returns `true` if `aria-pressed` is set to `true`, otherwise returns `false`. */ isPressed() { return this.get("pressed") === !0; } /** * @returns `true` if `aria-readonly` is set to `true`, otherwise returns `false`. */ isReadonly() { return this.get("readonly") === !0; } /** * @returns `true` if `aria-required` is set to `true`, otherwise returns `false`. */ isRequired() { return this.get("required") === !0; } /** * @returns `true` if `aria-selected` is set to `true`, otherwise returns `false`. */ isSelected() { return this.get("selected") === !0; } }; f = new WeakMap(), w = new WeakSet(), k = function() { return `easy-aria-id-${m(this, f)._++}`; }, l = new WeakSet(), u = function(e) { var s; return e instanceof Element ? (e.id || (e.id = r(s = n, w, k).call(s)), e.id) : ""; }, a = new WeakSet(), t = function(e, s) { this.el.setAttribute(`aria-${e}`, s); }, /** Generates a unique ID. */ d(n, w), /** * Returns the ID of a given Element. If no ID exists, * assigns a newly generated ID and returns it. */ d(n, l), /** Counter for generating new IDs. */ d(n, f, 1); let p = n; function $(i) { if (typeof i == "string") { const e = document.querySelector(i); if (e) return new p(e); } else if (i instanceof Element) return new p(i); return null; } export { $ as default };