@compa11y/core 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/announcer/index.cjs +1 -49
- package/dist/announcer/index.js +1 -4
- package/dist/aria/index.cjs +1 -24
- package/dist/aria/index.js +1 -3
- package/dist/chunk-7BL2ABLF.cjs +1 -0
- package/dist/chunk-AQ6HEUSD.cjs +1 -0
- package/dist/chunk-BAFKUMWA.js +1 -0
- package/dist/chunk-C3VZQUKG.js +1 -0
- package/dist/chunk-EM45V5TK.cjs +1 -0
- package/dist/chunk-KQUAJKTG.cjs +1 -0
- package/dist/chunk-OSJIG3A2.cjs +1 -0
- package/dist/chunk-RE4QIUWR.js +1 -0
- package/dist/chunk-TGXWODB3.js +1 -0
- package/dist/chunk-ZAQMM5TA.js +1 -0
- package/dist/focus/index.cjs +1 -53
- package/dist/focus/index.js +1 -4
- package/dist/index.cjs +2 -567
- package/dist/index.js +2 -337
- package/dist/keyboard/index.cjs +1 -28
- package/dist/keyboard/index.js +1 -3
- package/package.json +1 -1
- package/dist/announcer/index.cjs.map +0 -1
- package/dist/announcer/index.js.map +0 -1
- package/dist/aria/index.cjs.map +0 -1
- package/dist/aria/index.js.map +0 -1
- package/dist/chunk-24U5HHMC.js +0 -309
- package/dist/chunk-24U5HHMC.js.map +0 -1
- package/dist/chunk-2CQOLVQH.js +0 -147
- package/dist/chunk-2CQOLVQH.js.map +0 -1
- package/dist/chunk-2PUYKF2E.js +0 -631
- package/dist/chunk-2PUYKF2E.js.map +0 -1
- package/dist/chunk-2WF5Y6D7.js +0 -175
- package/dist/chunk-2WF5Y6D7.js.map +0 -1
- package/dist/chunk-CQXMBRLD.cjs +0 -657
- package/dist/chunk-CQXMBRLD.cjs.map +0 -1
- package/dist/chunk-HQOFVJFO.cjs +0 -181
- package/dist/chunk-HQOFVJFO.cjs.map +0 -1
- package/dist/chunk-NBGFFCIJ.cjs +0 -314
- package/dist/chunk-NBGFFCIJ.cjs.map +0 -1
- package/dist/chunk-V6TZIZZ4.cjs +0 -158
- package/dist/chunk-V6TZIZZ4.cjs.map +0 -1
- package/dist/chunk-XEGB27QF.cjs +0 -78
- package/dist/chunk-XEGB27QF.cjs.map +0 -1
- package/dist/chunk-Z7K2G6FX.js +0 -66
- package/dist/chunk-Z7K2G6FX.js.map +0 -1
- package/dist/focus/index.cjs.map +0 -1
- package/dist/focus/index.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/keyboard/index.cjs.map +0 -1
- package/dist/keyboard/index.js.map +0 -1
package/dist/chunk-24U5HHMC.js
DELETED
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
// src/aria/aria-utils.ts
|
|
2
|
-
var aria = {
|
|
3
|
-
/**
|
|
4
|
-
* Set aria-hidden on an element
|
|
5
|
-
*/
|
|
6
|
-
hide(element) {
|
|
7
|
-
element.setAttribute("aria-hidden", "true");
|
|
8
|
-
},
|
|
9
|
-
/**
|
|
10
|
-
* Remove aria-hidden from an element
|
|
11
|
-
*/
|
|
12
|
-
show(element) {
|
|
13
|
-
element.removeAttribute("aria-hidden");
|
|
14
|
-
},
|
|
15
|
-
/**
|
|
16
|
-
* Set aria-expanded state
|
|
17
|
-
*/
|
|
18
|
-
setExpanded(element, expanded) {
|
|
19
|
-
element.setAttribute("aria-expanded", String(expanded));
|
|
20
|
-
},
|
|
21
|
-
/**
|
|
22
|
-
* Set aria-selected state
|
|
23
|
-
*/
|
|
24
|
-
setSelected(element, selected) {
|
|
25
|
-
element.setAttribute("aria-selected", String(selected));
|
|
26
|
-
},
|
|
27
|
-
/**
|
|
28
|
-
* Set aria-checked state
|
|
29
|
-
*/
|
|
30
|
-
setChecked(element, checked) {
|
|
31
|
-
element.setAttribute("aria-checked", String(checked));
|
|
32
|
-
},
|
|
33
|
-
/**
|
|
34
|
-
* Set aria-pressed state
|
|
35
|
-
*/
|
|
36
|
-
setPressed(element, pressed) {
|
|
37
|
-
element.setAttribute("aria-pressed", String(pressed));
|
|
38
|
-
},
|
|
39
|
-
/**
|
|
40
|
-
* Set aria-disabled state
|
|
41
|
-
*/
|
|
42
|
-
setDisabled(element, disabled) {
|
|
43
|
-
element.setAttribute("aria-disabled", String(disabled));
|
|
44
|
-
},
|
|
45
|
-
/**
|
|
46
|
-
* Set aria-busy state
|
|
47
|
-
*/
|
|
48
|
-
setBusy(element, busy) {
|
|
49
|
-
element.setAttribute("aria-busy", String(busy));
|
|
50
|
-
},
|
|
51
|
-
/**
|
|
52
|
-
* Set aria-current
|
|
53
|
-
*/
|
|
54
|
-
setCurrent(element, value) {
|
|
55
|
-
if (value === "false") {
|
|
56
|
-
element.removeAttribute("aria-current");
|
|
57
|
-
} else {
|
|
58
|
-
element.setAttribute("aria-current", value);
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
/**
|
|
62
|
-
* Set aria-invalid state
|
|
63
|
-
*/
|
|
64
|
-
setInvalid(element, invalid) {
|
|
65
|
-
if (invalid === false) {
|
|
66
|
-
element.removeAttribute("aria-invalid");
|
|
67
|
-
} else {
|
|
68
|
-
element.setAttribute("aria-invalid", String(invalid));
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
/**
|
|
72
|
-
* Set aria-label
|
|
73
|
-
*/
|
|
74
|
-
setLabel(element, label) {
|
|
75
|
-
if (label) {
|
|
76
|
-
element.setAttribute("aria-label", label);
|
|
77
|
-
} else {
|
|
78
|
-
element.removeAttribute("aria-label");
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
/**
|
|
82
|
-
* Set aria-labelledby
|
|
83
|
-
*/
|
|
84
|
-
setLabelledBy(element, ...ids) {
|
|
85
|
-
const value = ids.filter(Boolean).join(" ");
|
|
86
|
-
if (value) {
|
|
87
|
-
element.setAttribute("aria-labelledby", value);
|
|
88
|
-
} else {
|
|
89
|
-
element.removeAttribute("aria-labelledby");
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
/**
|
|
93
|
-
* Set aria-describedby
|
|
94
|
-
*/
|
|
95
|
-
setDescribedBy(element, ...ids) {
|
|
96
|
-
const value = ids.filter(Boolean).join(" ");
|
|
97
|
-
if (value) {
|
|
98
|
-
element.setAttribute("aria-describedby", value);
|
|
99
|
-
} else {
|
|
100
|
-
element.removeAttribute("aria-describedby");
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
/**
|
|
104
|
-
* Set aria-controls
|
|
105
|
-
*/
|
|
106
|
-
setControls(element, ...ids) {
|
|
107
|
-
const value = ids.filter(Boolean).join(" ");
|
|
108
|
-
if (value) {
|
|
109
|
-
element.setAttribute("aria-controls", value);
|
|
110
|
-
} else {
|
|
111
|
-
element.removeAttribute("aria-controls");
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
/**
|
|
115
|
-
* Set aria-owns
|
|
116
|
-
*/
|
|
117
|
-
setOwns(element, ...ids) {
|
|
118
|
-
const value = ids.filter(Boolean).join(" ");
|
|
119
|
-
if (value) {
|
|
120
|
-
element.setAttribute("aria-owns", value);
|
|
121
|
-
} else {
|
|
122
|
-
element.removeAttribute("aria-owns");
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
/**
|
|
126
|
-
* Set aria-activedescendant
|
|
127
|
-
*/
|
|
128
|
-
setActiveDescendant(element, id) {
|
|
129
|
-
if (id) {
|
|
130
|
-
element.setAttribute("aria-activedescendant", id);
|
|
131
|
-
} else {
|
|
132
|
-
element.removeAttribute("aria-activedescendant");
|
|
133
|
-
}
|
|
134
|
-
},
|
|
135
|
-
/**
|
|
136
|
-
* Set aria-haspopup
|
|
137
|
-
*/
|
|
138
|
-
setHasPopup(element, popup) {
|
|
139
|
-
if (popup === false) {
|
|
140
|
-
element.removeAttribute("aria-haspopup");
|
|
141
|
-
} else {
|
|
142
|
-
element.setAttribute("aria-haspopup", String(popup));
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
/**
|
|
146
|
-
* Set aria-level
|
|
147
|
-
*/
|
|
148
|
-
setLevel(element, level) {
|
|
149
|
-
element.setAttribute("aria-level", String(level));
|
|
150
|
-
},
|
|
151
|
-
/**
|
|
152
|
-
* Set aria-posinset and aria-setsize
|
|
153
|
-
*/
|
|
154
|
-
setPosition(element, position, setSize) {
|
|
155
|
-
element.setAttribute("aria-posinset", String(position));
|
|
156
|
-
element.setAttribute("aria-setsize", String(setSize));
|
|
157
|
-
},
|
|
158
|
-
/**
|
|
159
|
-
* Set aria-valuemin, aria-valuemax, aria-valuenow
|
|
160
|
-
*/
|
|
161
|
-
setValue(element, options) {
|
|
162
|
-
if (options.min !== void 0) {
|
|
163
|
-
element.setAttribute("aria-valuemin", String(options.min));
|
|
164
|
-
}
|
|
165
|
-
if (options.max !== void 0) {
|
|
166
|
-
element.setAttribute("aria-valuemax", String(options.max));
|
|
167
|
-
}
|
|
168
|
-
if (options.now !== void 0) {
|
|
169
|
-
element.setAttribute("aria-valuenow", String(options.now));
|
|
170
|
-
}
|
|
171
|
-
if (options.text !== void 0) {
|
|
172
|
-
element.setAttribute("aria-valuetext", options.text);
|
|
173
|
-
}
|
|
174
|
-
},
|
|
175
|
-
/**
|
|
176
|
-
* Set role attribute
|
|
177
|
-
*/
|
|
178
|
-
setRole(element, role) {
|
|
179
|
-
if (role) {
|
|
180
|
-
element.setAttribute("role", role);
|
|
181
|
-
} else {
|
|
182
|
-
element.removeAttribute("role");
|
|
183
|
-
}
|
|
184
|
-
},
|
|
185
|
-
/**
|
|
186
|
-
* Set aria-modal
|
|
187
|
-
*/
|
|
188
|
-
setModal(element, modal) {
|
|
189
|
-
if (modal) {
|
|
190
|
-
element.setAttribute("aria-modal", "true");
|
|
191
|
-
} else {
|
|
192
|
-
element.removeAttribute("aria-modal");
|
|
193
|
-
}
|
|
194
|
-
},
|
|
195
|
-
/**
|
|
196
|
-
* Set aria-orientation
|
|
197
|
-
*/
|
|
198
|
-
setOrientation(element, orientation) {
|
|
199
|
-
element.setAttribute("aria-orientation", orientation);
|
|
200
|
-
},
|
|
201
|
-
/**
|
|
202
|
-
* Set aria-required
|
|
203
|
-
*/
|
|
204
|
-
setRequired(element, required) {
|
|
205
|
-
element.setAttribute("aria-required", String(required));
|
|
206
|
-
},
|
|
207
|
-
/**
|
|
208
|
-
* Set aria-readonly
|
|
209
|
-
*/
|
|
210
|
-
setReadOnly(element, readOnly) {
|
|
211
|
-
element.setAttribute("aria-readonly", String(readOnly));
|
|
212
|
-
},
|
|
213
|
-
/**
|
|
214
|
-
* Set aria-autocomplete
|
|
215
|
-
*/
|
|
216
|
-
setAutocomplete(element, value) {
|
|
217
|
-
element.setAttribute("aria-autocomplete", value);
|
|
218
|
-
},
|
|
219
|
-
/**
|
|
220
|
-
* Set aria-multiselectable
|
|
221
|
-
*/
|
|
222
|
-
setMultiSelectable(element, multiselectable) {
|
|
223
|
-
element.setAttribute("aria-multiselectable", String(multiselectable));
|
|
224
|
-
},
|
|
225
|
-
/**
|
|
226
|
-
* Set aria-sort
|
|
227
|
-
*/
|
|
228
|
-
setSort(element, sort) {
|
|
229
|
-
element.setAttribute("aria-sort", sort);
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
|
-
function buildAriaProps(props) {
|
|
233
|
-
const result = {};
|
|
234
|
-
if (props.label) result["aria-label"] = props.label;
|
|
235
|
-
if (props.labelledBy) {
|
|
236
|
-
result["aria-labelledby"] = Array.isArray(props.labelledBy) ? props.labelledBy.join(" ") : props.labelledBy;
|
|
237
|
-
}
|
|
238
|
-
if (props.describedBy) {
|
|
239
|
-
result["aria-describedby"] = Array.isArray(props.describedBy) ? props.describedBy.join(" ") : props.describedBy;
|
|
240
|
-
}
|
|
241
|
-
if (props.controls) {
|
|
242
|
-
result["aria-controls"] = Array.isArray(props.controls) ? props.controls.join(" ") : props.controls;
|
|
243
|
-
}
|
|
244
|
-
if (props.owns) {
|
|
245
|
-
result["aria-owns"] = Array.isArray(props.owns) ? props.owns.join(" ") : props.owns;
|
|
246
|
-
}
|
|
247
|
-
if (props.expanded !== void 0) result["aria-expanded"] = String(props.expanded);
|
|
248
|
-
if (props.selected !== void 0) result["aria-selected"] = String(props.selected);
|
|
249
|
-
if (props.checked !== void 0) result["aria-checked"] = String(props.checked);
|
|
250
|
-
if (props.pressed !== void 0) result["aria-pressed"] = String(props.pressed);
|
|
251
|
-
if (props.disabled !== void 0) result["aria-disabled"] = String(props.disabled);
|
|
252
|
-
if (props.hidden !== void 0) result["aria-hidden"] = String(props.hidden);
|
|
253
|
-
if (props.modal !== void 0) result["aria-modal"] = String(props.modal);
|
|
254
|
-
if (props.busy !== void 0) result["aria-busy"] = String(props.busy);
|
|
255
|
-
if (props.current) result["aria-current"] = props.current;
|
|
256
|
-
if (props.invalid !== void 0) result["aria-invalid"] = String(props.invalid);
|
|
257
|
-
if (props.hasPopup !== void 0) result["aria-haspopup"] = String(props.hasPopup);
|
|
258
|
-
if (props.activeDescendant) result["aria-activedescendant"] = props.activeDescendant;
|
|
259
|
-
if (props.level !== void 0) result["aria-level"] = String(props.level);
|
|
260
|
-
if (props.posInSet !== void 0) result["aria-posinset"] = String(props.posInSet);
|
|
261
|
-
if (props.setSize !== void 0) result["aria-setsize"] = String(props.setSize);
|
|
262
|
-
if (props.valueMin !== void 0) result["aria-valuemin"] = String(props.valueMin);
|
|
263
|
-
if (props.valueMax !== void 0) result["aria-valuemax"] = String(props.valueMax);
|
|
264
|
-
if (props.valueNow !== void 0) result["aria-valuenow"] = String(props.valueNow);
|
|
265
|
-
if (props.valueText) result["aria-valuetext"] = props.valueText;
|
|
266
|
-
if (props.orientation) result["aria-orientation"] = props.orientation;
|
|
267
|
-
if (props.required !== void 0) result["aria-required"] = String(props.required);
|
|
268
|
-
if (props.readOnly !== void 0) result["aria-readonly"] = String(props.readOnly);
|
|
269
|
-
if (props.autocomplete) result["aria-autocomplete"] = props.autocomplete;
|
|
270
|
-
if (props.multiSelectable !== void 0) result["aria-multiselectable"] = String(props.multiSelectable);
|
|
271
|
-
if (props.sort) result["aria-sort"] = props.sort;
|
|
272
|
-
if (props.role) result.role = props.role;
|
|
273
|
-
return result;
|
|
274
|
-
}
|
|
275
|
-
function mergeAriaIds(...ids) {
|
|
276
|
-
const filtered = ids.filter(Boolean);
|
|
277
|
-
return filtered.length > 0 ? filtered.join(" ") : void 0;
|
|
278
|
-
}
|
|
279
|
-
function hasAccessibleName(element) {
|
|
280
|
-
if (element.getAttribute("aria-label")) {
|
|
281
|
-
return true;
|
|
282
|
-
}
|
|
283
|
-
const labelledBy = element.getAttribute("aria-labelledby");
|
|
284
|
-
if (labelledBy) {
|
|
285
|
-
const ids = labelledBy.split(" ");
|
|
286
|
-
const hasLabelContent = ids.some((id) => {
|
|
287
|
-
const labelElement = document.getElementById(id);
|
|
288
|
-
return labelElement && labelElement.textContent?.trim();
|
|
289
|
-
});
|
|
290
|
-
if (hasLabelContent) return true;
|
|
291
|
-
}
|
|
292
|
-
if (element.textContent?.trim()) {
|
|
293
|
-
return true;
|
|
294
|
-
}
|
|
295
|
-
if (element.getAttribute("title")) {
|
|
296
|
-
return true;
|
|
297
|
-
}
|
|
298
|
-
if ("labels" in element && element.labels?.length) {
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
301
|
-
if (element.tagName === "IMG" && element.getAttribute("alt")) {
|
|
302
|
-
return true;
|
|
303
|
-
}
|
|
304
|
-
return false;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
export { aria, buildAriaProps, hasAccessibleName, mergeAriaIds };
|
|
308
|
-
//# sourceMappingURL=chunk-24U5HHMC.js.map
|
|
309
|
-
//# sourceMappingURL=chunk-24U5HHMC.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/aria/aria-utils.ts"],"names":[],"mappings":"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","file":"chunk-24U5HHMC.js","sourcesContent":["/**\n * ARIA Utilities\n *\n * Helpers for managing ARIA attributes and relationships\n */\n\nimport type { AriaRole } from '../types';\n\n/**\n * ARIA attribute helpers\n */\nexport const aria = {\n /**\n * Set aria-hidden on an element\n */\n hide(element: HTMLElement): void {\n element.setAttribute('aria-hidden', 'true');\n },\n\n /**\n * Remove aria-hidden from an element\n */\n show(element: HTMLElement): void {\n element.removeAttribute('aria-hidden');\n },\n\n /**\n * Set aria-expanded state\n */\n setExpanded(element: HTMLElement, expanded: boolean): void {\n element.setAttribute('aria-expanded', String(expanded));\n },\n\n /**\n * Set aria-selected state\n */\n setSelected(element: HTMLElement, selected: boolean): void {\n element.setAttribute('aria-selected', String(selected));\n },\n\n /**\n * Set aria-checked state\n */\n setChecked(element: HTMLElement, checked: boolean | 'mixed'): void {\n element.setAttribute('aria-checked', String(checked));\n },\n\n /**\n * Set aria-pressed state\n */\n setPressed(element: HTMLElement, pressed: boolean | 'mixed'): void {\n element.setAttribute('aria-pressed', String(pressed));\n },\n\n /**\n * Set aria-disabled state\n */\n setDisabled(element: HTMLElement, disabled: boolean): void {\n element.setAttribute('aria-disabled', String(disabled));\n },\n\n /**\n * Set aria-busy state\n */\n setBusy(element: HTMLElement, busy: boolean): void {\n element.setAttribute('aria-busy', String(busy));\n },\n\n /**\n * Set aria-current\n */\n setCurrent(\n element: HTMLElement,\n value: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false'\n ): void {\n if (value === 'false') {\n element.removeAttribute('aria-current');\n } else {\n element.setAttribute('aria-current', value);\n }\n },\n\n /**\n * Set aria-invalid state\n */\n setInvalid(element: HTMLElement, invalid: boolean | 'grammar' | 'spelling'): void {\n if (invalid === false) {\n element.removeAttribute('aria-invalid');\n } else {\n element.setAttribute('aria-invalid', String(invalid));\n }\n },\n\n /**\n * Set aria-label\n */\n setLabel(element: HTMLElement, label: string): void {\n if (label) {\n element.setAttribute('aria-label', label);\n } else {\n element.removeAttribute('aria-label');\n }\n },\n\n /**\n * Set aria-labelledby\n */\n setLabelledBy(element: HTMLElement, ...ids: string[]): void {\n const value = ids.filter(Boolean).join(' ');\n if (value) {\n element.setAttribute('aria-labelledby', value);\n } else {\n element.removeAttribute('aria-labelledby');\n }\n },\n\n /**\n * Set aria-describedby\n */\n setDescribedBy(element: HTMLElement, ...ids: string[]): void {\n const value = ids.filter(Boolean).join(' ');\n if (value) {\n element.setAttribute('aria-describedby', value);\n } else {\n element.removeAttribute('aria-describedby');\n }\n },\n\n /**\n * Set aria-controls\n */\n setControls(element: HTMLElement, ...ids: string[]): void {\n const value = ids.filter(Boolean).join(' ');\n if (value) {\n element.setAttribute('aria-controls', value);\n } else {\n element.removeAttribute('aria-controls');\n }\n },\n\n /**\n * Set aria-owns\n */\n setOwns(element: HTMLElement, ...ids: string[]): void {\n const value = ids.filter(Boolean).join(' ');\n if (value) {\n element.setAttribute('aria-owns', value);\n } else {\n element.removeAttribute('aria-owns');\n }\n },\n\n /**\n * Set aria-activedescendant\n */\n setActiveDescendant(element: HTMLElement, id: string | null): void {\n if (id) {\n element.setAttribute('aria-activedescendant', id);\n } else {\n element.removeAttribute('aria-activedescendant');\n }\n },\n\n /**\n * Set aria-haspopup\n */\n setHasPopup(\n element: HTMLElement,\n popup: 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | boolean\n ): void {\n if (popup === false) {\n element.removeAttribute('aria-haspopup');\n } else {\n element.setAttribute('aria-haspopup', String(popup));\n }\n },\n\n /**\n * Set aria-level\n */\n setLevel(element: HTMLElement, level: number): void {\n element.setAttribute('aria-level', String(level));\n },\n\n /**\n * Set aria-posinset and aria-setsize\n */\n setPosition(element: HTMLElement, position: number, setSize: number): void {\n element.setAttribute('aria-posinset', String(position));\n element.setAttribute('aria-setsize', String(setSize));\n },\n\n /**\n * Set aria-valuemin, aria-valuemax, aria-valuenow\n */\n setValue(\n element: HTMLElement,\n options: {\n min?: number;\n max?: number;\n now?: number;\n text?: string;\n }\n ): void {\n if (options.min !== undefined) {\n element.setAttribute('aria-valuemin', String(options.min));\n }\n if (options.max !== undefined) {\n element.setAttribute('aria-valuemax', String(options.max));\n }\n if (options.now !== undefined) {\n element.setAttribute('aria-valuenow', String(options.now));\n }\n if (options.text !== undefined) {\n element.setAttribute('aria-valuetext', options.text);\n }\n },\n\n /**\n * Set role attribute\n */\n setRole(element: HTMLElement, role: AriaRole | null): void {\n if (role) {\n element.setAttribute('role', role);\n } else {\n element.removeAttribute('role');\n }\n },\n\n /**\n * Set aria-modal\n */\n setModal(element: HTMLElement, modal: boolean): void {\n if (modal) {\n element.setAttribute('aria-modal', 'true');\n } else {\n element.removeAttribute('aria-modal');\n }\n },\n\n /**\n * Set aria-orientation\n */\n setOrientation(element: HTMLElement, orientation: 'horizontal' | 'vertical'): void {\n element.setAttribute('aria-orientation', orientation);\n },\n\n /**\n * Set aria-required\n */\n setRequired(element: HTMLElement, required: boolean): void {\n element.setAttribute('aria-required', String(required));\n },\n\n /**\n * Set aria-readonly\n */\n setReadOnly(element: HTMLElement, readOnly: boolean): void {\n element.setAttribute('aria-readonly', String(readOnly));\n },\n\n /**\n * Set aria-autocomplete\n */\n setAutocomplete(element: HTMLElement, value: 'none' | 'inline' | 'list' | 'both'): void {\n element.setAttribute('aria-autocomplete', value);\n },\n\n /**\n * Set aria-multiselectable\n */\n setMultiSelectable(element: HTMLElement, multiselectable: boolean): void {\n element.setAttribute('aria-multiselectable', String(multiselectable));\n },\n\n /**\n * Set aria-sort\n */\n setSort(element: HTMLElement, sort: 'none' | 'ascending' | 'descending' | 'other'): void {\n element.setAttribute('aria-sort', sort);\n },\n};\n\n/**\n * Build ARIA props object for React/JS usage\n */\nexport function buildAriaProps(props: {\n label?: string;\n labelledBy?: string | string[];\n describedBy?: string | string[];\n controls?: string | string[];\n owns?: string | string[];\n expanded?: boolean;\n selected?: boolean;\n checked?: boolean | 'mixed';\n pressed?: boolean | 'mixed';\n disabled?: boolean;\n hidden?: boolean;\n modal?: boolean;\n busy?: boolean;\n current?: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false';\n invalid?: boolean | 'grammar' | 'spelling';\n hasPopup?: 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | boolean;\n activeDescendant?: string;\n level?: number;\n posInSet?: number;\n setSize?: number;\n valueMin?: number;\n valueMax?: number;\n valueNow?: number;\n valueText?: string;\n orientation?: 'horizontal' | 'vertical';\n required?: boolean;\n readOnly?: boolean;\n autocomplete?: 'none' | 'inline' | 'list' | 'both';\n multiSelectable?: boolean;\n sort?: 'none' | 'ascending' | 'descending' | 'other';\n role?: AriaRole;\n}): Record<string, string | undefined> {\n const result: Record<string, string | undefined> = {};\n\n if (props.label) result['aria-label'] = props.label;\n if (props.labelledBy) {\n result['aria-labelledby'] = Array.isArray(props.labelledBy)\n ? props.labelledBy.join(' ')\n : props.labelledBy;\n }\n if (props.describedBy) {\n result['aria-describedby'] = Array.isArray(props.describedBy)\n ? props.describedBy.join(' ')\n : props.describedBy;\n }\n if (props.controls) {\n result['aria-controls'] = Array.isArray(props.controls)\n ? props.controls.join(' ')\n : props.controls;\n }\n if (props.owns) {\n result['aria-owns'] = Array.isArray(props.owns)\n ? props.owns.join(' ')\n : props.owns;\n }\n if (props.expanded !== undefined) result['aria-expanded'] = String(props.expanded);\n if (props.selected !== undefined) result['aria-selected'] = String(props.selected);\n if (props.checked !== undefined) result['aria-checked'] = String(props.checked);\n if (props.pressed !== undefined) result['aria-pressed'] = String(props.pressed);\n if (props.disabled !== undefined) result['aria-disabled'] = String(props.disabled);\n if (props.hidden !== undefined) result['aria-hidden'] = String(props.hidden);\n if (props.modal !== undefined) result['aria-modal'] = String(props.modal);\n if (props.busy !== undefined) result['aria-busy'] = String(props.busy);\n if (props.current) result['aria-current'] = props.current;\n if (props.invalid !== undefined) result['aria-invalid'] = String(props.invalid);\n if (props.hasPopup !== undefined) result['aria-haspopup'] = String(props.hasPopup);\n if (props.activeDescendant) result['aria-activedescendant'] = props.activeDescendant;\n if (props.level !== undefined) result['aria-level'] = String(props.level);\n if (props.posInSet !== undefined) result['aria-posinset'] = String(props.posInSet);\n if (props.setSize !== undefined) result['aria-setsize'] = String(props.setSize);\n if (props.valueMin !== undefined) result['aria-valuemin'] = String(props.valueMin);\n if (props.valueMax !== undefined) result['aria-valuemax'] = String(props.valueMax);\n if (props.valueNow !== undefined) result['aria-valuenow'] = String(props.valueNow);\n if (props.valueText) result['aria-valuetext'] = props.valueText;\n if (props.orientation) result['aria-orientation'] = props.orientation;\n if (props.required !== undefined) result['aria-required'] = String(props.required);\n if (props.readOnly !== undefined) result['aria-readonly'] = String(props.readOnly);\n if (props.autocomplete) result['aria-autocomplete'] = props.autocomplete;\n if (props.multiSelectable !== undefined) result['aria-multiselectable'] = String(props.multiSelectable);\n if (props.sort) result['aria-sort'] = props.sort;\n if (props.role) result.role = props.role;\n\n return result;\n}\n\n/**\n * Merge multiple aria-labelledby or aria-describedby values\n */\nexport function mergeAriaIds(...ids: (string | undefined | null)[]): string | undefined {\n const filtered = ids.filter(Boolean) as string[];\n return filtered.length > 0 ? filtered.join(' ') : undefined;\n}\n\n/**\n * Check if an element has an accessible name\n */\nexport function hasAccessibleName(element: HTMLElement): boolean {\n // Check aria-label\n if (element.getAttribute('aria-label')) {\n return true;\n }\n\n // Check aria-labelledby\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const ids = labelledBy.split(' ');\n const hasLabelContent = ids.some((id) => {\n const labelElement = document.getElementById(id);\n return labelElement && labelElement.textContent?.trim();\n });\n if (hasLabelContent) return true;\n }\n\n // Check text content (for buttons, links, etc.)\n if (element.textContent?.trim()) {\n return true;\n }\n\n // Check title attribute (fallback)\n if (element.getAttribute('title')) {\n return true;\n }\n\n // Check associated label (for form elements)\n if ('labels' in element && (element as HTMLInputElement).labels?.length) {\n return true;\n }\n\n // Check alt attribute (for images)\n if (element.tagName === 'IMG' && element.getAttribute('alt')) {\n return true;\n }\n\n return false;\n}\n"]}
|
package/dist/chunk-2CQOLVQH.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { isBrowser } from './chunk-Z7K2G6FX.js';
|
|
2
|
-
|
|
3
|
-
// src/announcer/live-announcer.ts
|
|
4
|
-
var politeRegion = null;
|
|
5
|
-
var assertiveRegion = null;
|
|
6
|
-
var isInitialized = false;
|
|
7
|
-
var messageQueue = [];
|
|
8
|
-
var queueTimeout = null;
|
|
9
|
-
function getHiddenStyles() {
|
|
10
|
-
return {
|
|
11
|
-
position: "absolute",
|
|
12
|
-
width: "1px",
|
|
13
|
-
height: "1px",
|
|
14
|
-
padding: "0",
|
|
15
|
-
margin: "-1px",
|
|
16
|
-
overflow: "hidden",
|
|
17
|
-
clip: "rect(0, 0, 0, 0)",
|
|
18
|
-
whiteSpace: "nowrap",
|
|
19
|
-
border: "0"
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
function createLiveRegion(politeness) {
|
|
23
|
-
const element = document.createElement("div");
|
|
24
|
-
element.setAttribute("role", "status");
|
|
25
|
-
element.setAttribute("aria-live", politeness);
|
|
26
|
-
element.setAttribute("aria-atomic", "true");
|
|
27
|
-
element.setAttribute("aria-relevant", "additions text");
|
|
28
|
-
element.id = `compa11y-announcer-${politeness}`;
|
|
29
|
-
const styles = getHiddenStyles();
|
|
30
|
-
Object.assign(element.style, styles);
|
|
31
|
-
document.body.appendChild(element);
|
|
32
|
-
return { element, politeness };
|
|
33
|
-
}
|
|
34
|
-
function initAnnouncer() {
|
|
35
|
-
if (!isBrowser() || isInitialized) {
|
|
36
|
-
return () => {
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
isInitialized = true;
|
|
40
|
-
politeRegion = createLiveRegion("polite");
|
|
41
|
-
assertiveRegion = createLiveRegion("assertive");
|
|
42
|
-
return () => {
|
|
43
|
-
if (politeRegion) {
|
|
44
|
-
politeRegion.element.remove();
|
|
45
|
-
politeRegion = null;
|
|
46
|
-
}
|
|
47
|
-
if (assertiveRegion) {
|
|
48
|
-
assertiveRegion.element.remove();
|
|
49
|
-
assertiveRegion = null;
|
|
50
|
-
}
|
|
51
|
-
if (queueTimeout) {
|
|
52
|
-
clearTimeout(queueTimeout);
|
|
53
|
-
queueTimeout = null;
|
|
54
|
-
}
|
|
55
|
-
messageQueue = [];
|
|
56
|
-
isInitialized = false;
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
function ensureAnnouncer() {
|
|
60
|
-
if (!isInitialized && isBrowser()) {
|
|
61
|
-
initAnnouncer();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
function clearRegion(region) {
|
|
65
|
-
region.element.textContent = "";
|
|
66
|
-
}
|
|
67
|
-
function announce(message, options = {}) {
|
|
68
|
-
if (!isBrowser()) return;
|
|
69
|
-
const {
|
|
70
|
-
politeness = "polite",
|
|
71
|
-
delay = 0,
|
|
72
|
-
clearPrevious = false,
|
|
73
|
-
timeout = 7e3
|
|
74
|
-
} = options;
|
|
75
|
-
ensureAnnouncer();
|
|
76
|
-
const region = politeness === "assertive" ? assertiveRegion : politeRegion;
|
|
77
|
-
if (!region) return;
|
|
78
|
-
const doAnnounce = () => {
|
|
79
|
-
if (clearPrevious) {
|
|
80
|
-
clearRegion(region);
|
|
81
|
-
}
|
|
82
|
-
region.element.textContent = "";
|
|
83
|
-
requestAnimationFrame(() => {
|
|
84
|
-
region.element.textContent = message;
|
|
85
|
-
if (timeout > 0) {
|
|
86
|
-
setTimeout(() => {
|
|
87
|
-
if (region.element.textContent === message) {
|
|
88
|
-
region.element.textContent = "";
|
|
89
|
-
}
|
|
90
|
-
}, timeout);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
if (delay > 0) {
|
|
95
|
-
setTimeout(doAnnounce, delay);
|
|
96
|
-
} else {
|
|
97
|
-
doAnnounce();
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
function announcePolite(message, options) {
|
|
101
|
-
announce(message, { ...options, politeness: "polite" });
|
|
102
|
-
}
|
|
103
|
-
function announceAssertive(message, options) {
|
|
104
|
-
announce(message, { ...options, politeness: "assertive" });
|
|
105
|
-
}
|
|
106
|
-
function clearAnnouncements() {
|
|
107
|
-
if (politeRegion) clearRegion(politeRegion);
|
|
108
|
-
if (assertiveRegion) clearRegion(assertiveRegion);
|
|
109
|
-
}
|
|
110
|
-
function queueAnnouncement(message, options = {}) {
|
|
111
|
-
const { debounce = 150, ...announceOptions } = options;
|
|
112
|
-
messageQueue.push({ message, options: announceOptions });
|
|
113
|
-
if (queueTimeout) {
|
|
114
|
-
clearTimeout(queueTimeout);
|
|
115
|
-
}
|
|
116
|
-
queueTimeout = setTimeout(() => {
|
|
117
|
-
const lastMessage = messageQueue[messageQueue.length - 1];
|
|
118
|
-
if (lastMessage) {
|
|
119
|
-
announce(lastMessage.message, lastMessage.options);
|
|
120
|
-
}
|
|
121
|
-
messageQueue = [];
|
|
122
|
-
queueTimeout = null;
|
|
123
|
-
}, debounce);
|
|
124
|
-
}
|
|
125
|
-
function createAnnouncer(defaultOptions = {}) {
|
|
126
|
-
return {
|
|
127
|
-
announce: (message, options) => announce(message, { ...defaultOptions, ...options }),
|
|
128
|
-
polite: (message, options) => announcePolite(message, { ...defaultOptions, ...options }),
|
|
129
|
-
assertive: (message, options) => announceAssertive(message, { ...defaultOptions, ...options }),
|
|
130
|
-
queue: (message, options) => queueAnnouncement(message, { ...defaultOptions, ...options }),
|
|
131
|
-
clear: clearAnnouncements
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
function announceStatus(message) {
|
|
135
|
-
announcePolite(message);
|
|
136
|
-
}
|
|
137
|
-
function announceError(message) {
|
|
138
|
-
announceAssertive(message);
|
|
139
|
-
}
|
|
140
|
-
function announceProgress(current, total, template = "{current} of {total}") {
|
|
141
|
-
const message = template.replace("{current}", String(current)).replace("{total}", String(total));
|
|
142
|
-
announcePolite(message);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export { announce, announceAssertive, announceError, announcePolite, announceProgress, announceStatus, clearAnnouncements, createAnnouncer, initAnnouncer, queueAnnouncement };
|
|
146
|
-
//# sourceMappingURL=chunk-2CQOLVQH.js.map
|
|
147
|
-
//# sourceMappingURL=chunk-2CQOLVQH.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/announcer/live-announcer.ts"],"names":[],"mappings":"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","file":"chunk-2CQOLVQH.js","sourcesContent":["/**\n * Live Announcer\n *\n * Provides screen reader announcements via ARIA live regions\n */\n\nimport type { AriaLivePoliteness, AnnouncerOptions } from '../types';\nimport { isBrowser } from '../utils/platform';\n\ninterface LiveRegion {\n element: HTMLElement;\n politeness: AriaLivePoliteness;\n}\n\n// Singleton regions\nlet politeRegion: LiveRegion | null = null;\nlet assertiveRegion: LiveRegion | null = null;\nlet isInitialized = false;\n\n// Message queue for debouncing\nlet messageQueue: Array<{\n message: string;\n options: AnnouncerOptions;\n}> = [];\nlet queueTimeout: ReturnType<typeof setTimeout> | null = null;\n\n/**\n * Create the visually hidden styles for live regions\n */\nfunction getHiddenStyles(): Partial<CSSStyleDeclaration> {\n return {\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: '0',\n margin: '-1px',\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n border: '0',\n };\n}\n\n/**\n * Create a live region element\n */\nfunction createLiveRegion(politeness: AriaLivePoliteness): LiveRegion {\n const element = document.createElement('div');\n\n // Set ARIA attributes\n element.setAttribute('role', 'status');\n element.setAttribute('aria-live', politeness);\n element.setAttribute('aria-atomic', 'true');\n element.setAttribute('aria-relevant', 'additions text');\n element.id = `compa11y-announcer-${politeness}`;\n\n // Apply visually hidden styles\n const styles = getHiddenStyles();\n Object.assign(element.style, styles);\n\n // Add to DOM\n document.body.appendChild(element);\n\n return { element, politeness };\n}\n\n/**\n * Initialize the live announcer\n * Call this once at app startup\n */\nexport function initAnnouncer(): () => void {\n if (!isBrowser() || isInitialized) {\n return () => {};\n }\n\n isInitialized = true;\n\n // Create live regions\n politeRegion = createLiveRegion('polite');\n assertiveRegion = createLiveRegion('assertive');\n\n // Cleanup function\n return () => {\n if (politeRegion) {\n politeRegion.element.remove();\n politeRegion = null;\n }\n if (assertiveRegion) {\n assertiveRegion.element.remove();\n assertiveRegion = null;\n }\n if (queueTimeout) {\n clearTimeout(queueTimeout);\n queueTimeout = null;\n }\n messageQueue = [];\n isInitialized = false;\n };\n}\n\n/**\n * Get or create the announcer (auto-init if needed)\n */\nfunction ensureAnnouncer(): void {\n if (!isInitialized && isBrowser()) {\n initAnnouncer();\n }\n}\n\n/**\n * Clear a live region's content\n */\nfunction clearRegion(region: LiveRegion): void {\n region.element.textContent = '';\n}\n\n/**\n * Announce a message to screen readers\n */\nexport function announce(\n message: string,\n options: AnnouncerOptions = {}\n): void {\n if (!isBrowser()) return;\n\n const {\n politeness = 'polite',\n delay = 0,\n clearPrevious = false,\n timeout = 7000,\n } = options;\n\n ensureAnnouncer();\n\n const region = politeness === 'assertive' ? assertiveRegion : politeRegion;\n if (!region) return;\n\n const doAnnounce = () => {\n if (clearPrevious) {\n clearRegion(region);\n }\n\n region.element.textContent = '';\n\n requestAnimationFrame(() => {\n region.element.textContent = message;\n\n // Auto-clear after timeout\n if (timeout > 0) {\n setTimeout(() => {\n if (region.element.textContent === message) {\n region.element.textContent = '';\n }\n }, timeout);\n }\n });\n };\n\n if (delay > 0) {\n setTimeout(doAnnounce, delay);\n } else {\n doAnnounce();\n }\n}\n\n/**\n * Announce a polite message (non-interruptive)\n */\nexport function announcePolite(\n message: string,\n options?: Omit<AnnouncerOptions, 'politeness'>\n): void {\n announce(message, { ...options, politeness: 'polite' });\n}\n\n/**\n * Announce an assertive message (interruptive)\n */\nexport function announceAssertive(\n message: string,\n options?: Omit<AnnouncerOptions, 'politeness'>\n): void {\n announce(message, { ...options, politeness: 'assertive' });\n}\n\n/**\n * Clear all announcements\n */\nexport function clearAnnouncements(): void {\n if (politeRegion) clearRegion(politeRegion);\n if (assertiveRegion) clearRegion(assertiveRegion);\n}\n\n/**\n * Queue multiple announcements (debounced)\n */\nexport function queueAnnouncement(\n message: string,\n options: AnnouncerOptions & { debounce?: number } = {}\n): void {\n const { debounce = 150, ...announceOptions } = options;\n\n messageQueue.push({ message, options: announceOptions });\n\n if (queueTimeout) {\n clearTimeout(queueTimeout);\n }\n\n queueTimeout = setTimeout(() => {\n // Combine messages or use the last one\n const lastMessage = messageQueue[messageQueue.length - 1];\n if (lastMessage) {\n announce(lastMessage.message, lastMessage.options);\n }\n messageQueue = [];\n queueTimeout = null;\n }, debounce);\n}\n\n/**\n * Create an announcer instance for a specific context\n */\nexport function createAnnouncer(defaultOptions: AnnouncerOptions = {}) {\n return {\n announce: (message: string, options?: AnnouncerOptions) =>\n announce(message, { ...defaultOptions, ...options }),\n polite: (message: string, options?: Omit<AnnouncerOptions, 'politeness'>) =>\n announcePolite(message, { ...defaultOptions, ...options }),\n assertive: (\n message: string,\n options?: Omit<AnnouncerOptions, 'politeness'>\n ) => announceAssertive(message, { ...defaultOptions, ...options }),\n queue: (\n message: string,\n options?: AnnouncerOptions & { debounce?: number }\n ) => queueAnnouncement(message, { ...defaultOptions, ...options }),\n clear: clearAnnouncements,\n };\n}\n\n/**\n * Status announcer - for status updates like \"Saved\", \"Loading complete\"\n */\nexport function announceStatus(message: string): void {\n announcePolite(message);\n}\n\n/**\n * Error announcer - for error messages\n */\nexport function announceError(message: string): void {\n announceAssertive(message);\n}\n\n/**\n * Progress announcer - for progress updates\n */\nexport function announceProgress(\n current: number,\n total: number,\n template = '{current} of {total}'\n): void {\n const message = template\n .replace('{current}', String(current))\n .replace('{total}', String(total));\n announcePolite(message);\n}\n"]}
|