praxis-kit 3.1.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +141 -126
- package/dist/chunk-TJRHF6MS.js +2777 -0
- package/dist/codemod/index.js +20 -20
- package/dist/contract/index.d.ts +2 -258
- package/dist/contract/index.js +158 -1190
- package/dist/eslint/index.js +403 -178
- package/dist/lit/index.d.ts +5 -235
- package/dist/lit/index.js +1384 -747
- package/dist/merge-refs-DUuHyTRO.d.ts +144 -0
- package/dist/preact/index.d.ts +9 -254
- package/dist/preact/index.js +1686 -1025
- package/dist/react/index.d.ts +23 -11
- package/dist/react/index.js +115 -116
- package/dist/react/legacy.d.ts +7 -11
- package/dist/react/legacy.js +116 -136
- package/dist/solid/index.d.ts +5 -250
- package/dist/solid/index.js +1476 -706
- package/dist/svelte/index.d.ts +5 -325
- package/dist/svelte/index.js +1407 -725
- package/dist/tailwind/index.d.ts +5 -4
- package/dist/tailwind/index.js +366 -90
- package/dist/ts-plugin/index.cjs +5 -5
- package/dist/vite-plugin/index.d.ts +91 -120
- package/dist/vite-plugin/index.js +568 -347
- package/dist/vue/index.d.ts +12 -257
- package/dist/vue/index.js +1701 -926
- package/dist/web/index.d.ts +9 -238
- package/dist/web/index.js +1369 -732
- package/package.json +4 -3
- package/dist/chunk-6RJN5B6L.js +0 -2221
- package/dist/merge-refs-BKyE8h8M.d.ts +0 -381
package/dist/lit/index.js
CHANGED
|
@@ -1,58 +1,17 @@
|
|
|
1
1
|
// ../../adapters/lit/src/create-contract-component.ts
|
|
2
2
|
import { LitElement, html } from "lit";
|
|
3
3
|
|
|
4
|
-
// ../../lib/
|
|
5
|
-
function applyFilter(props, filterProps, variantKeys) {
|
|
6
|
-
const out = {};
|
|
7
|
-
for (const k in props) {
|
|
8
|
-
if (!Object.hasOwn(props, k)) continue;
|
|
9
|
-
if (filterProps(k, variantKeys)) continue;
|
|
10
|
-
out[k] = props[k];
|
|
11
|
-
}
|
|
12
|
-
return out;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// ../../lib/adapter-utils/src/define-component.ts
|
|
16
|
-
function defineContractComponent(options) {
|
|
17
|
-
return (factory) => factory(options);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// ../core/dist/chunk-KKSHJDE7.js
|
|
4
|
+
// ../../lib/primitive/src/tag/resolve-tag.ts
|
|
21
5
|
function makeResolveTag(defaultTag) {
|
|
22
6
|
return function tag(as) {
|
|
23
7
|
return as ?? defaultTag;
|
|
24
8
|
};
|
|
25
9
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
32
|
-
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
33
|
-
var o = e.length;
|
|
34
|
-
for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
|
|
35
|
-
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
36
|
-
return n;
|
|
37
|
-
}
|
|
38
|
-
function clsx() {
|
|
39
|
-
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
40
|
-
return n;
|
|
41
|
-
}
|
|
42
|
-
function cn(...inputs) {
|
|
43
|
-
return clsx(...inputs);
|
|
44
|
-
}
|
|
45
|
-
function mergeProps(defaultProps, props) {
|
|
46
|
-
return {
|
|
47
|
-
...defaultProps ?? {},
|
|
48
|
-
...props
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
function isNull(value) {
|
|
52
|
-
return value === null;
|
|
53
|
-
}
|
|
54
|
-
function isObject(value) {
|
|
55
|
-
return !isNull(value) && typeof value === "object";
|
|
10
|
+
|
|
11
|
+
// ../../lib/primitive/src/utils/is-object.ts
|
|
12
|
+
function isObject(value, excludeArrays = false) {
|
|
13
|
+
if (value === null || typeof value !== "object") return false;
|
|
14
|
+
return excludeArrays ? !Array.isArray(value) : true;
|
|
56
15
|
}
|
|
57
16
|
function isString(value) {
|
|
58
17
|
return typeof value === "string";
|
|
@@ -60,308 +19,197 @@ function isString(value) {
|
|
|
60
19
|
function isNumber(value) {
|
|
61
20
|
return typeof value === "number";
|
|
62
21
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const patched = normalizers.reduce(
|
|
68
|
-
(acc, normalizer) => ({ ...acc, ...normalizer(acc) }),
|
|
69
|
-
props
|
|
70
|
-
);
|
|
71
|
-
return fn ? fn(patched) : patched;
|
|
72
|
-
});
|
|
22
|
+
|
|
23
|
+
// ../../lib/primitive/src/utils/assert-never.ts
|
|
24
|
+
function assertNever(value) {
|
|
25
|
+
throw new Error(`Unexpected value: ${String(value)}`);
|
|
73
26
|
}
|
|
74
|
-
|
|
75
|
-
|
|
27
|
+
|
|
28
|
+
// ../../lib/primitive/src/utils/cn.ts
|
|
29
|
+
import { clsx } from "clsx";
|
|
30
|
+
function cn(...inputs) {
|
|
31
|
+
return clsx(...inputs);
|
|
76
32
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
...whenDefined("baseClassName", styling?.base),
|
|
88
|
-
...whenDefined("tagMap", styling?.tags),
|
|
89
|
-
...whenDefined("recipeMap", styling?.presets),
|
|
90
|
-
...whenDefined("variants", styling?.variants),
|
|
91
|
-
...whenDefined("defaultVariants", styling?.defaults),
|
|
92
|
-
...whenDefined("compoundVariants", styling?.compounds),
|
|
93
|
-
...whenDefined("normalizeFn", composedNormalizeFn),
|
|
94
|
-
...whenDefined("ariaRules", enforcement?.aria),
|
|
95
|
-
...whenDefined("childRules", enforcement?.children),
|
|
96
|
-
...whenDefined("allowedAs", enforcement?.allowedAs),
|
|
97
|
-
...whenDefined("precomputedClasses", styling?.precomputedClasses)
|
|
98
|
-
});
|
|
33
|
+
|
|
34
|
+
// ../../lib/primitive/src/utils/iterate.ts
|
|
35
|
+
function find(iterable, callback) {
|
|
36
|
+
for (const value of iterable) {
|
|
37
|
+
const result = callback(value);
|
|
38
|
+
if (result != null) {
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
99
43
|
}
|
|
100
|
-
function
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
44
|
+
function some(iterable, predicate) {
|
|
45
|
+
for (const value of iterable) {
|
|
46
|
+
if (predicate(value)) return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
105
49
|
}
|
|
106
|
-
function
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const checkSelection = (label2, selection) => {
|
|
112
|
-
const record = selection;
|
|
113
|
-
for (const dim in record) {
|
|
114
|
-
const value = record[dim];
|
|
115
|
-
if (value === void 0 || value === null) continue;
|
|
116
|
-
if (!variants || !Object.hasOwn(variants, dim)) {
|
|
117
|
-
report(strict, `${name}: ${label2} references unknown variant "${dim}".`);
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
const states = variants[dim];
|
|
121
|
-
const stateKey = String(value);
|
|
122
|
-
if (!Object.hasOwn(states, stateKey)) {
|
|
123
|
-
report(
|
|
124
|
-
strict,
|
|
125
|
-
`${name}: ${label2} sets "${dim}" to unknown value "${stateKey}" (valid: ${Object.keys(states).join(", ")}).`
|
|
126
|
-
);
|
|
127
|
-
}
|
|
50
|
+
function every(iterable, predicate) {
|
|
51
|
+
let index = 0;
|
|
52
|
+
for (const value of iterable) {
|
|
53
|
+
if (!predicate(value, index++)) {
|
|
54
|
+
return false;
|
|
128
55
|
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
function* filter(iterable, predicate) {
|
|
60
|
+
let index = 0;
|
|
61
|
+
for (const value of iterable) {
|
|
62
|
+
if (predicate(value, index++)) {
|
|
63
|
+
yield value;
|
|
134
64
|
}
|
|
135
65
|
}
|
|
136
|
-
if (resolved.defaultVariants) checkSelection("defaults", resolved.defaultVariants);
|
|
137
66
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
67
|
+
function* map(iterable, callback) {
|
|
68
|
+
let index = 0;
|
|
69
|
+
for (const value of iterable) {
|
|
70
|
+
yield callback(value, index++);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function forEach(iterable, callback) {
|
|
74
|
+
let index = 0;
|
|
75
|
+
for (const value of iterable) {
|
|
76
|
+
callback(value, index++);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function reduce(iterable, initial, callback) {
|
|
80
|
+
let accumulator = initial;
|
|
81
|
+
let index = 0;
|
|
82
|
+
for (const value of iterable) {
|
|
83
|
+
accumulator = callback(accumulator, value, index++);
|
|
84
|
+
}
|
|
85
|
+
return accumulator;
|
|
86
|
+
}
|
|
87
|
+
function collect(iterable, callback) {
|
|
88
|
+
const result = {};
|
|
89
|
+
let index = 0;
|
|
90
|
+
for (const value of iterable) {
|
|
91
|
+
const entry = callback(value, index++);
|
|
92
|
+
if (entry === null) {
|
|
93
|
+
return null;
|
|
159
94
|
}
|
|
160
|
-
|
|
95
|
+
result[entry[0]] = entry[1];
|
|
161
96
|
}
|
|
162
|
-
|
|
163
|
-
warned.add(message);
|
|
164
|
-
console.warn(message);
|
|
97
|
+
return result;
|
|
165
98
|
}
|
|
166
|
-
function
|
|
167
|
-
|
|
99
|
+
function findLast(value, callback) {
|
|
100
|
+
for (let index = value.length - 1; index >= 0; index--) {
|
|
101
|
+
const result = callback(value[index], index);
|
|
102
|
+
if (result != null) {
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
168
107
|
}
|
|
169
|
-
function
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
108
|
+
function* items(collection) {
|
|
109
|
+
for (let i = 0; i < collection.length; i++) {
|
|
110
|
+
const item = collection.item(i);
|
|
111
|
+
if (item !== null) {
|
|
112
|
+
yield item;
|
|
113
|
+
}
|
|
175
114
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
`${tag} Variant "${key}=${String(value)}" is not a defined value for the "${key}" dimension.`
|
|
186
|
-
);
|
|
115
|
+
}
|
|
116
|
+
function nodeList(list) {
|
|
117
|
+
return {
|
|
118
|
+
*[Symbol.iterator]() {
|
|
119
|
+
for (let i = 0; i < list.length; i++) {
|
|
120
|
+
const node = list.item(i);
|
|
121
|
+
if (node !== null) {
|
|
122
|
+
yield node;
|
|
123
|
+
}
|
|
187
124
|
}
|
|
188
125
|
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function mapEntries(m) {
|
|
129
|
+
return m.entries();
|
|
130
|
+
}
|
|
131
|
+
function set(s) {
|
|
132
|
+
return s.values();
|
|
133
|
+
}
|
|
134
|
+
function hasOwn(object, key) {
|
|
135
|
+
return Object.hasOwn(object, key);
|
|
136
|
+
}
|
|
137
|
+
function* entries(object) {
|
|
138
|
+
for (const key in object) {
|
|
139
|
+
if (!hasOwn(object, key)) continue;
|
|
140
|
+
yield [key, object[key]];
|
|
189
141
|
}
|
|
190
142
|
}
|
|
191
|
-
function
|
|
192
|
-
|
|
143
|
+
function* keys(object) {
|
|
144
|
+
for (const [key] of entries(object)) {
|
|
145
|
+
yield key;
|
|
146
|
+
}
|
|
193
147
|
}
|
|
194
|
-
function
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
148
|
+
function* values(object) {
|
|
149
|
+
for (const [, value] of entries(object)) {
|
|
150
|
+
yield value;
|
|
151
|
+
}
|
|
198
152
|
}
|
|
199
|
-
function
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
if (typeof plugin.pipeline !== "function")
|
|
206
|
-
panic(
|
|
207
|
-
`[praxis-kit] Plugin factory return value is missing a 'pipeline' function. Got pipeline: ${typeof plugin.pipeline}.`
|
|
208
|
-
);
|
|
153
|
+
function mapValues(object, callback) {
|
|
154
|
+
const result = {};
|
|
155
|
+
for (const [key, value] of entries(object)) {
|
|
156
|
+
result[key] = callback(value, key);
|
|
157
|
+
}
|
|
158
|
+
return result;
|
|
209
159
|
}
|
|
210
|
-
function
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (typeof result !== "string")
|
|
215
|
-
panic(`[praxis-kit] Plugin pipeline must return a string. Got: ${describe(result)}.`);
|
|
216
|
-
return result;
|
|
217
|
-
};
|
|
160
|
+
function forEachEntry(object, callback) {
|
|
161
|
+
for (const [key, value] of entries(object)) {
|
|
162
|
+
callback(key, value);
|
|
163
|
+
}
|
|
218
164
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (!factory) {
|
|
223
|
-
const createClassPipeline2 = capabilities?.createClassPipeline;
|
|
224
|
-
const classPipeline2 = createClassPipeline2 ? createClassPipeline2(resolved) : NOOP_CLASS_PIPELINE;
|
|
225
|
-
return { pluginResult: void 0, classPipeline: classPipeline2 };
|
|
165
|
+
function forEachKey(object, callback) {
|
|
166
|
+
for (const key of keys(object)) {
|
|
167
|
+
callback(key);
|
|
226
168
|
}
|
|
227
|
-
const pluginResult = factory(resolved, strict);
|
|
228
|
-
assertPluginShape(pluginResult);
|
|
229
|
-
const classPipeline = guardPipeline(pluginResult.pipeline);
|
|
230
|
-
return { pluginResult, classPipeline };
|
|
231
169
|
}
|
|
232
|
-
function
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
return mergeProps(resolved.defaultProps, props);
|
|
237
|
-
},
|
|
238
|
-
resolveClasses(tag, props, className, recipe) {
|
|
239
|
-
if (process.env.NODE_ENV !== "production") {
|
|
240
|
-
validateRenderProps(resolved, props, recipe);
|
|
241
|
-
}
|
|
242
|
-
return classPipeline(tag, props, className, recipe);
|
|
243
|
-
},
|
|
244
|
-
resolveAria(tag, props) {
|
|
245
|
-
if (!engine) return { props };
|
|
246
|
-
const result = engine.validate(tag, props);
|
|
247
|
-
return { props: result.props };
|
|
248
|
-
}
|
|
249
|
-
};
|
|
170
|
+
function forEachValue(object, callback) {
|
|
171
|
+
for (const value of values(object)) {
|
|
172
|
+
callback(value);
|
|
173
|
+
}
|
|
250
174
|
}
|
|
251
|
-
function
|
|
252
|
-
|
|
175
|
+
function forEachSet(s, callback) {
|
|
176
|
+
for (const value of s) {
|
|
177
|
+
callback(value);
|
|
178
|
+
}
|
|
253
179
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
180
|
+
var iterate = Object.freeze({
|
|
181
|
+
entries,
|
|
182
|
+
filter,
|
|
183
|
+
find,
|
|
184
|
+
findLast,
|
|
185
|
+
forEach,
|
|
186
|
+
forEachEntry,
|
|
187
|
+
forEachKey,
|
|
188
|
+
forEachSet,
|
|
189
|
+
forEachValue,
|
|
190
|
+
items,
|
|
191
|
+
keys,
|
|
192
|
+
map,
|
|
193
|
+
mapEntries,
|
|
194
|
+
mapValues,
|
|
195
|
+
nodeList,
|
|
196
|
+
reduce,
|
|
197
|
+
collect,
|
|
198
|
+
set,
|
|
199
|
+
some,
|
|
200
|
+
every,
|
|
201
|
+
values
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// ../../lib/primitive/src/utils/merge-props.ts
|
|
205
|
+
function mergeProps(defaultProps, props) {
|
|
206
|
+
return {
|
|
207
|
+
...defaultProps ?? {},
|
|
208
|
+
...props
|
|
209
|
+
};
|
|
280
210
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
"alertdialog",
|
|
284
|
-
"application",
|
|
285
|
-
"article",
|
|
286
|
-
"banner",
|
|
287
|
-
"blockquote",
|
|
288
|
-
"button",
|
|
289
|
-
"caption",
|
|
290
|
-
"cell",
|
|
291
|
-
"checkbox",
|
|
292
|
-
"code",
|
|
293
|
-
"columnheader",
|
|
294
|
-
"combobox",
|
|
295
|
-
"complementary",
|
|
296
|
-
"contentinfo",
|
|
297
|
-
"definition",
|
|
298
|
-
"deletion",
|
|
299
|
-
"dialog",
|
|
300
|
-
"document",
|
|
301
|
-
"emphasis",
|
|
302
|
-
"feed",
|
|
303
|
-
"figure",
|
|
304
|
-
"form",
|
|
305
|
-
"generic",
|
|
306
|
-
"grid",
|
|
307
|
-
"gridcell",
|
|
308
|
-
"group",
|
|
309
|
-
"heading",
|
|
310
|
-
"img",
|
|
311
|
-
"insertion",
|
|
312
|
-
"link",
|
|
313
|
-
"list",
|
|
314
|
-
"listbox",
|
|
315
|
-
"listitem",
|
|
316
|
-
"log",
|
|
317
|
-
"main",
|
|
318
|
-
"marquee",
|
|
319
|
-
"math",
|
|
320
|
-
"menu",
|
|
321
|
-
"menubar",
|
|
322
|
-
"menuitem",
|
|
323
|
-
"menuitemcheckbox",
|
|
324
|
-
"menuitemradio",
|
|
325
|
-
"meter",
|
|
326
|
-
"navigation",
|
|
327
|
-
"none",
|
|
328
|
-
"note",
|
|
329
|
-
"option",
|
|
330
|
-
"paragraph",
|
|
331
|
-
"presentation",
|
|
332
|
-
"progressbar",
|
|
333
|
-
"radio",
|
|
334
|
-
"radiogroup",
|
|
335
|
-
"region",
|
|
336
|
-
"row",
|
|
337
|
-
"rowgroup",
|
|
338
|
-
"rowheader",
|
|
339
|
-
"scrollbar",
|
|
340
|
-
"search",
|
|
341
|
-
"searchbox",
|
|
342
|
-
"separator",
|
|
343
|
-
"slider",
|
|
344
|
-
"spinbutton",
|
|
345
|
-
"status",
|
|
346
|
-
"strong",
|
|
347
|
-
"subscript",
|
|
348
|
-
"superscript",
|
|
349
|
-
"switch",
|
|
350
|
-
"tab",
|
|
351
|
-
"table",
|
|
352
|
-
"tablist",
|
|
353
|
-
"tabpanel",
|
|
354
|
-
"term",
|
|
355
|
-
"textbox",
|
|
356
|
-
"time",
|
|
357
|
-
"timer",
|
|
358
|
-
"toolbar",
|
|
359
|
-
"tooltip",
|
|
360
|
-
"tree",
|
|
361
|
-
"treegrid",
|
|
362
|
-
"treeitem"
|
|
363
|
-
];
|
|
364
|
-
var KNOWN_ARIA_ROLES_SET = new Set(KNOWN_ARIA_ROLES);
|
|
211
|
+
|
|
212
|
+
// ../../lib/primitive/src/constants/aria/global-aria-attributes.ts
|
|
365
213
|
var GLOBAL_ARIA_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
366
214
|
"aria-atomic",
|
|
367
215
|
"aria-busy",
|
|
@@ -381,29 +229,59 @@ var GLOBAL_ARIA_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
|
381
229
|
"aria-relevant",
|
|
382
230
|
"aria-roledescription"
|
|
383
231
|
]);
|
|
232
|
+
|
|
233
|
+
// ../../lib/primitive/src/constants/aria/implicit-role-record.ts
|
|
384
234
|
var IMPLICIT_ROLE_RECORD = {
|
|
235
|
+
// Landmarks
|
|
385
236
|
article: "article",
|
|
386
237
|
aside: "complementary",
|
|
387
238
|
footer: "contentinfo",
|
|
388
239
|
header: "banner",
|
|
389
240
|
main: "main",
|
|
390
241
|
nav: "navigation",
|
|
391
|
-
|
|
242
|
+
// Interactive
|
|
392
243
|
a: "link",
|
|
244
|
+
button: "button",
|
|
393
245
|
select: "listbox",
|
|
246
|
+
textarea: "textbox",
|
|
247
|
+
// Headings
|
|
394
248
|
h1: "heading",
|
|
395
249
|
h2: "heading",
|
|
396
250
|
h3: "heading",
|
|
397
251
|
h4: "heading",
|
|
398
252
|
h5: "heading",
|
|
399
253
|
h6: "heading",
|
|
254
|
+
// Lists
|
|
400
255
|
ul: "list",
|
|
401
256
|
ol: "list",
|
|
402
257
|
li: "listitem",
|
|
258
|
+
// Tables
|
|
403
259
|
table: "table",
|
|
404
260
|
tr: "row",
|
|
405
261
|
td: "cell",
|
|
406
|
-
th: "columnheader"
|
|
262
|
+
th: "columnheader",
|
|
263
|
+
// Structural / semantic
|
|
264
|
+
dialog: "dialog",
|
|
265
|
+
fieldset: "group",
|
|
266
|
+
figure: "figure",
|
|
267
|
+
meter: "meter",
|
|
268
|
+
output: "status",
|
|
269
|
+
progress: "progressbar"
|
|
270
|
+
};
|
|
271
|
+
var INPUT_TYPE_ROLE_MAP = {
|
|
272
|
+
checkbox: "checkbox",
|
|
273
|
+
radio: "radio",
|
|
274
|
+
range: "slider",
|
|
275
|
+
number: "spinbutton",
|
|
276
|
+
search: "searchbox",
|
|
277
|
+
text: "textbox",
|
|
278
|
+
email: "textbox",
|
|
279
|
+
tel: "textbox",
|
|
280
|
+
url: "textbox",
|
|
281
|
+
button: "button",
|
|
282
|
+
submit: "button",
|
|
283
|
+
reset: "button",
|
|
284
|
+
image: "button"
|
|
407
285
|
};
|
|
408
286
|
var STRONG_ROLES = [
|
|
409
287
|
"main",
|
|
@@ -415,6 +293,8 @@ var STRONG_ROLES = [
|
|
|
415
293
|
var STANDALONE_ROLES = ["article"];
|
|
416
294
|
var STRONG_ROLES_SET = new Set(STRONG_ROLES);
|
|
417
295
|
var STANDALONE_ROLES_SET = new Set(STANDALONE_ROLES);
|
|
296
|
+
|
|
297
|
+
// ../../lib/primitive/src/constants/aria/role-restricted-attributes.ts
|
|
418
298
|
var ROLE_RESTRICTED_ATTRIBUTES = /* @__PURE__ */ new Map([
|
|
419
299
|
[
|
|
420
300
|
"aria-activedescendant",
|
|
@@ -564,9 +444,18 @@ var ROLE_RESTRICTED_ATTRIBUTES = /* @__PURE__ */ new Map([
|
|
|
564
444
|
/* @__PURE__ */ new Set(["meter", "progressbar", "scrollbar", "separator", "slider", "spinbutton"])
|
|
565
445
|
]
|
|
566
446
|
]);
|
|
447
|
+
|
|
448
|
+
// ../../lib/primitive/src/guards/foundational/is-defined.ts
|
|
567
449
|
function isUndefined(value) {
|
|
568
450
|
return value === void 0;
|
|
569
451
|
}
|
|
452
|
+
|
|
453
|
+
// ../../lib/primitive/src/guards/foundational/is-null.ts
|
|
454
|
+
function isNull(value) {
|
|
455
|
+
return value === null;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// ../../lib/primitive/src/guards/aria/is-aria-attribute.ts
|
|
570
459
|
function isGlobalAriaAttribute(attr) {
|
|
571
460
|
return GLOBAL_ARIA_ATTRIBUTES.has(attr);
|
|
572
461
|
}
|
|
@@ -576,6 +465,8 @@ function isAriaAttributeValidForRole(attr, role) {
|
|
|
576
465
|
if (isUndefined(role)) return false;
|
|
577
466
|
return allowedRoles.has(role);
|
|
578
467
|
}
|
|
468
|
+
|
|
469
|
+
// ../../lib/primitive/src/guards/aria/is-aria-role.ts
|
|
579
470
|
function isStrongImplicitRole(tag) {
|
|
580
471
|
if (!(tag in IMPLICIT_ROLE_RECORD)) return false;
|
|
581
472
|
return STRONG_ROLES_SET.has(IMPLICIT_ROLE_RECORD[tag]);
|
|
@@ -584,116 +475,509 @@ function isStandaloneTag(tag) {
|
|
|
584
475
|
if (!(tag in IMPLICIT_ROLE_RECORD)) return false;
|
|
585
476
|
return STANDALONE_ROLES_SET.has(IMPLICIT_ROLE_RECORD[tag]);
|
|
586
477
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
button: "button",
|
|
597
|
-
a: "link",
|
|
598
|
-
select: "listbox",
|
|
599
|
-
h1: "heading",
|
|
600
|
-
h2: "heading",
|
|
601
|
-
h3: "heading",
|
|
602
|
-
h4: "heading",
|
|
603
|
-
h5: "heading",
|
|
604
|
-
h6: "heading",
|
|
605
|
-
ul: "list",
|
|
606
|
-
ol: "list",
|
|
607
|
-
li: "listitem",
|
|
608
|
-
table: "table",
|
|
609
|
-
tr: "row",
|
|
610
|
-
td: "cell",
|
|
611
|
-
th: "columnheader"
|
|
612
|
-
};
|
|
613
|
-
function getImplicitRole(tag) {
|
|
614
|
-
if (tag in IMPLICIT_ROLE_RECORD2) return IMPLICIT_ROLE_RECORD2[tag];
|
|
478
|
+
function getInputImplicitRole(type) {
|
|
479
|
+
if (type == null || !(type in INPUT_TYPE_ROLE_MAP)) return void 0;
|
|
480
|
+
return INPUT_TYPE_ROLE_MAP[type];
|
|
481
|
+
}
|
|
482
|
+
function getConditionalImplicitRole(tag, ariaLabel, ariaLabelledBy) {
|
|
483
|
+
const isNamed = typeof ariaLabel === "string" || typeof ariaLabelledBy === "string";
|
|
484
|
+
if (!isNamed) return void 0;
|
|
485
|
+
if (tag === "section") return "region";
|
|
486
|
+
if (tag === "form") return "form";
|
|
615
487
|
return void 0;
|
|
616
488
|
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
const
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
489
|
+
|
|
490
|
+
// ../../lib/adapter-utils/src/apply-filter.ts
|
|
491
|
+
function applyFilter(props, filterProps, variantKeys) {
|
|
492
|
+
const out = {};
|
|
493
|
+
iterate.forEachEntry(props, (k) => {
|
|
494
|
+
if (!Object.hasOwn(props, k)) return;
|
|
495
|
+
if (filterProps(k, variantKeys)) return;
|
|
496
|
+
out[k] = props[k];
|
|
497
|
+
});
|
|
498
|
+
return out;
|
|
624
499
|
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
if (
|
|
629
|
-
if (
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
return
|
|
500
|
+
|
|
501
|
+
// ../../lib/contract/src/aria/aria-role-policy.ts
|
|
502
|
+
function getImplicitRole(tag, props) {
|
|
503
|
+
if (tag in IMPLICIT_ROLE_RECORD) return IMPLICIT_ROLE_RECORD[tag];
|
|
504
|
+
if (tag === "input") return getInputImplicitRole(props?.type);
|
|
505
|
+
if (tag === "img") return props?.alt === "" ? "none" : "img";
|
|
506
|
+
if (tag === "section" || tag === "form") {
|
|
507
|
+
return getConditionalImplicitRole(tag, props?.["aria-label"], props?.["aria-labelledby"]);
|
|
633
508
|
}
|
|
634
509
|
return void 0;
|
|
635
510
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
};
|
|
511
|
+
|
|
512
|
+
// ../../lib/contract/src/strict/invariant-base.ts
|
|
513
|
+
var InvariantBase = class {
|
|
514
|
+
diagnostics;
|
|
515
|
+
constructor(diagnostics) {
|
|
516
|
+
this.diagnostics = diagnostics;
|
|
643
517
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
var pendingAsyncWarns2 = /* @__PURE__ */ new Set();
|
|
650
|
-
var asyncWarnScheduled2 = false;
|
|
651
|
-
function flushAsyncWarns2() {
|
|
652
|
-
asyncWarnScheduled2 = false;
|
|
653
|
-
const messages = [...pendingAsyncWarns2];
|
|
654
|
-
pendingAsyncWarns2.clear();
|
|
655
|
-
for (const msg of messages) {
|
|
656
|
-
console.warn(msg);
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
function scheduleAsyncWarn(message) {
|
|
660
|
-
if (pendingAsyncWarns2.has(message)) return;
|
|
661
|
-
pendingAsyncWarns2.add(message);
|
|
662
|
-
if (!asyncWarnScheduled2) {
|
|
663
|
-
asyncWarnScheduled2 = true;
|
|
664
|
-
queueMicrotask(flushAsyncWarns2);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
var StrictBase = class {
|
|
668
|
-
strict;
|
|
669
|
-
constructor(strict) {
|
|
670
|
-
this.strict = strict;
|
|
671
|
-
}
|
|
672
|
-
violate(message) {
|
|
673
|
-
if (this.strict === true || this.strict === "throw") {
|
|
674
|
-
throw new Error(message);
|
|
675
|
-
}
|
|
676
|
-
this.warn(message);
|
|
518
|
+
get active() {
|
|
519
|
+
return this.diagnostics.active;
|
|
520
|
+
}
|
|
521
|
+
violate(input) {
|
|
522
|
+
this.diagnostics.error(input);
|
|
677
523
|
}
|
|
678
|
-
// Always caps at
|
|
524
|
+
// Always caps at warn — never throws. ARIA 'warning' violations route here
|
|
679
525
|
// so they surface even in strict='throw' mode without aborting a render.
|
|
680
|
-
warn(
|
|
681
|
-
|
|
682
|
-
if (this.strict === "async-warn") {
|
|
683
|
-
scheduleAsyncWarn(message);
|
|
684
|
-
return;
|
|
685
|
-
}
|
|
686
|
-
console.warn(message);
|
|
526
|
+
warn(input) {
|
|
527
|
+
this.diagnostics.warn(input);
|
|
687
528
|
}
|
|
688
|
-
invariant(condition,
|
|
689
|
-
if (!condition)
|
|
690
|
-
this.violate(message);
|
|
691
|
-
}
|
|
529
|
+
invariant(condition, input) {
|
|
530
|
+
if (!condition) this.violate(input);
|
|
692
531
|
}
|
|
693
532
|
};
|
|
694
|
-
|
|
695
|
-
|
|
533
|
+
|
|
534
|
+
// ../../lib/diagnostics/src/category.ts
|
|
535
|
+
var DiagnosticCategory = /* @__PURE__ */ ((DiagnosticCategory2) => {
|
|
536
|
+
DiagnosticCategory2[DiagnosticCategory2["Contract"] = 0] = "Contract";
|
|
537
|
+
DiagnosticCategory2[DiagnosticCategory2["HTML"] = 1] = "HTML";
|
|
538
|
+
DiagnosticCategory2[DiagnosticCategory2["ARIA"] = 2] = "ARIA";
|
|
539
|
+
DiagnosticCategory2[DiagnosticCategory2["Composition"] = 3] = "Composition";
|
|
540
|
+
DiagnosticCategory2[DiagnosticCategory2["Rendering"] = 4] = "Rendering";
|
|
541
|
+
DiagnosticCategory2[DiagnosticCategory2["Accessibility"] = 5] = "Accessibility";
|
|
542
|
+
DiagnosticCategory2[DiagnosticCategory2["Performance"] = 6] = "Performance";
|
|
543
|
+
DiagnosticCategory2[DiagnosticCategory2["Internal"] = 7] = "Internal";
|
|
544
|
+
DiagnosticCategory2[DiagnosticCategory2["Deprecation"] = 8] = "Deprecation";
|
|
545
|
+
DiagnosticCategory2[DiagnosticCategory2["Lint"] = 9] = "Lint";
|
|
546
|
+
return DiagnosticCategory2;
|
|
547
|
+
})(DiagnosticCategory || {});
|
|
548
|
+
|
|
549
|
+
// ../../lib/diagnostics/src/error.ts
|
|
550
|
+
var PraxisError = class extends Error {
|
|
551
|
+
diagnostic;
|
|
552
|
+
constructor(diagnostic) {
|
|
553
|
+
super(diagnostic.message);
|
|
554
|
+
this.name = "PraxisError";
|
|
555
|
+
this.diagnostic = diagnostic;
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
// ../../lib/diagnostics/src/severity.ts
|
|
560
|
+
var Severity = /* @__PURE__ */ ((Severity2) => {
|
|
561
|
+
Severity2[Severity2["Debug"] = 0] = "Debug";
|
|
562
|
+
Severity2[Severity2["Info"] = 1] = "Info";
|
|
563
|
+
Severity2[Severity2["Warning"] = 2] = "Warning";
|
|
564
|
+
Severity2[Severity2["Error"] = 3] = "Error";
|
|
565
|
+
Severity2[Severity2["Fatal"] = 4] = "Fatal";
|
|
566
|
+
return Severity2;
|
|
567
|
+
})(Severity || {});
|
|
568
|
+
|
|
569
|
+
// ../../lib/diagnostics/src/policy.ts
|
|
570
|
+
var DefaultPolicy = class {
|
|
571
|
+
reportThreshold;
|
|
572
|
+
throwThreshold;
|
|
573
|
+
constructor({
|
|
574
|
+
reportThreshold = 1 /* Info */,
|
|
575
|
+
throwThreshold = 4 /* Fatal */
|
|
576
|
+
} = {}) {
|
|
577
|
+
this.reportThreshold = reportThreshold;
|
|
578
|
+
this.throwThreshold = throwThreshold;
|
|
579
|
+
}
|
|
580
|
+
resolve(diagnostic) {
|
|
581
|
+
if (diagnostic.severity >= this.throwThreshold) return 2 /* Throw */;
|
|
582
|
+
if (diagnostic.severity >= this.reportThreshold) return 1 /* Report */;
|
|
583
|
+
return 0 /* Ignore */;
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
// ../../lib/diagnostics/src/diagnostics.ts
|
|
588
|
+
var Diagnostics = class {
|
|
589
|
+
reporter;
|
|
590
|
+
policy;
|
|
591
|
+
// Pre-computed at construction time: true if Warning-level diagnostics are not ignored.
|
|
592
|
+
active;
|
|
593
|
+
constructor(reporter, policy = new DefaultPolicy()) {
|
|
594
|
+
this.reporter = reporter;
|
|
595
|
+
this.policy = policy;
|
|
596
|
+
this.active = policy.resolve({ severity: 2 /* Warning */ }) !== 0 /* Ignore */;
|
|
597
|
+
}
|
|
598
|
+
report(diagnostic) {
|
|
599
|
+
const enforcement = this.policy.resolve(diagnostic);
|
|
600
|
+
if (enforcement === 0 /* Ignore */) return diagnostic;
|
|
601
|
+
if (enforcement === 2 /* Throw */) throw new PraxisError(diagnostic);
|
|
602
|
+
this.reporter.report(diagnostic);
|
|
603
|
+
return diagnostic;
|
|
604
|
+
}
|
|
605
|
+
warn(input) {
|
|
606
|
+
return this.report({ ...input, severity: 2 /* Warning */ });
|
|
607
|
+
}
|
|
608
|
+
error(input) {
|
|
609
|
+
return this.report({ ...input, severity: 3 /* Error */ });
|
|
610
|
+
}
|
|
611
|
+
info(input) {
|
|
612
|
+
return this.report({ ...input, severity: 1 /* Info */ });
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
// ../../lib/diagnostics/src/formatter.ts
|
|
617
|
+
function formatDiagnostic(diagnostic) {
|
|
618
|
+
const level = Severity[diagnostic.severity];
|
|
619
|
+
const category = DiagnosticCategory[diagnostic.category];
|
|
620
|
+
const prefix = category !== void 0 ? `[${category}] ` : "";
|
|
621
|
+
return `${level} ${diagnostic.code}: ${prefix}${diagnostic.message}`;
|
|
696
622
|
}
|
|
623
|
+
|
|
624
|
+
// ../../lib/diagnostics/src/console-reporter.ts
|
|
625
|
+
var ConsoleReporter = class {
|
|
626
|
+
report(diagnostic) {
|
|
627
|
+
const message = formatDiagnostic(diagnostic);
|
|
628
|
+
switch (diagnostic.severity) {
|
|
629
|
+
case 0 /* Debug */:
|
|
630
|
+
console.debug(message);
|
|
631
|
+
break;
|
|
632
|
+
case 1 /* Info */:
|
|
633
|
+
console.info(message);
|
|
634
|
+
break;
|
|
635
|
+
case 2 /* Warning */:
|
|
636
|
+
console.warn(message);
|
|
637
|
+
break;
|
|
638
|
+
case 3 /* Error */:
|
|
639
|
+
case 4 /* Fatal */:
|
|
640
|
+
console.error(message);
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
// ../../lib/diagnostics/src/null-reporter.ts
|
|
647
|
+
var nullReporter = {
|
|
648
|
+
report() {
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
// ../../lib/diagnostics/src/presets.ts
|
|
653
|
+
var ignoreAllPolicy = {
|
|
654
|
+
resolve(_) {
|
|
655
|
+
return 0 /* Ignore */;
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
var warnOnlyReporter = {
|
|
659
|
+
report(diagnostic) {
|
|
660
|
+
console.warn(formatDiagnostic(diagnostic));
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
var silentDiagnostics = new Diagnostics(nullReporter, ignoreAllPolicy);
|
|
664
|
+
var warnDiagnostics = new Diagnostics(
|
|
665
|
+
warnOnlyReporter,
|
|
666
|
+
new DefaultPolicy({ reportThreshold: 2 /* Warning */, throwThreshold: 4 /* Fatal */ })
|
|
667
|
+
);
|
|
668
|
+
var throwDiagnostics = new Diagnostics(
|
|
669
|
+
new ConsoleReporter(),
|
|
670
|
+
new DefaultPolicy({ reportThreshold: 2 /* Warning */, throwThreshold: 3 /* Error */ })
|
|
671
|
+
);
|
|
672
|
+
|
|
673
|
+
// ../../lib/contract/src/diagnostics/aria.ts
|
|
674
|
+
var AriaDiagnostics = {
|
|
675
|
+
/** Generic bridge for violations produced by external AriaRule functions. */
|
|
676
|
+
fromViolation(v) {
|
|
677
|
+
return {
|
|
678
|
+
code: "ARIA2002" /* AriaViolation */,
|
|
679
|
+
category: 2 /* ARIA */,
|
|
680
|
+
message: v.message
|
|
681
|
+
};
|
|
682
|
+
},
|
|
683
|
+
attributeInvalid(key, role) {
|
|
684
|
+
return {
|
|
685
|
+
code: "ARIA2003" /* AriaAttributeInvalid */,
|
|
686
|
+
category: 2 /* ARIA */,
|
|
687
|
+
message: `"${key}" is not valid on role="${role}". It will be removed.`,
|
|
688
|
+
rationale: "Invalid ARIA attributes are ignored by assistive technology and may trigger accessibility-tree warnings in browser devtools.",
|
|
689
|
+
suggestions: [
|
|
690
|
+
{
|
|
691
|
+
title: "Remove the attribute",
|
|
692
|
+
description: `"${key}" is not in the allowed attribute set for role="${role}".`
|
|
693
|
+
}
|
|
694
|
+
]
|
|
695
|
+
};
|
|
696
|
+
},
|
|
697
|
+
missingLiveRegion(role, impliedLive) {
|
|
698
|
+
return {
|
|
699
|
+
code: "ARIA2004" /* AriaMissingLiveRegion */,
|
|
700
|
+
category: 2 /* ARIA */,
|
|
701
|
+
message: `role="${role}" implies aria-live="${impliedLive}" but it is missing. It has been injected.`,
|
|
702
|
+
rationale: "Live-region roles announce dynamic content changes to screen readers. Without aria-live the politeness level is unspecified and announcements may be silent.",
|
|
703
|
+
suggestions: [
|
|
704
|
+
{
|
|
705
|
+
title: `Add aria-live="${impliedLive}"`,
|
|
706
|
+
description: `role="${role}" conventionally implies aria-live="${impliedLive}".`,
|
|
707
|
+
fix: `aria-live="${impliedLive}"`
|
|
708
|
+
}
|
|
709
|
+
]
|
|
710
|
+
};
|
|
711
|
+
},
|
|
712
|
+
missingAtomic(role) {
|
|
713
|
+
return {
|
|
714
|
+
code: "ARIA2005" /* AriaMissingAtomic */,
|
|
715
|
+
category: 2 /* ARIA */,
|
|
716
|
+
message: `role="${role}" is a live region. Consider setting aria-atomic="true" if the full region should be announced as a unit, or aria-atomic="false" if only changed nodes should be read.`,
|
|
717
|
+
rationale: "aria-atomic controls whether assistive technology announces the entire live region or only the changed nodes. Omitting it leaves the behaviour browser-defined."
|
|
718
|
+
};
|
|
719
|
+
},
|
|
720
|
+
relevantInvalidTokens(invalid) {
|
|
721
|
+
const quoted = invalid.map((t) => `"${t}"`).join(", ");
|
|
722
|
+
return {
|
|
723
|
+
code: "ARIA2006" /* AriaRelevantInvalidToken */,
|
|
724
|
+
category: 2 /* ARIA */,
|
|
725
|
+
message: `aria-relevant contains invalid token(s): ${quoted}. Valid tokens are: additions, removals, text, all.`,
|
|
726
|
+
rationale: "aria-relevant accepts a space-separated list of change types. Unrecognised tokens are silently ignored by assistive technology, making the attribute ineffective.",
|
|
727
|
+
suggestions: [
|
|
728
|
+
{
|
|
729
|
+
title: "Use only valid tokens",
|
|
730
|
+
description: "Valid values are: additions, removals, text, all (or a space-separated combination)."
|
|
731
|
+
}
|
|
732
|
+
]
|
|
733
|
+
};
|
|
734
|
+
},
|
|
735
|
+
relevantSuperseded() {
|
|
736
|
+
return {
|
|
737
|
+
code: "ARIA2007" /* AriaRelevantSuperseded */,
|
|
738
|
+
category: 2 /* ARIA */,
|
|
739
|
+
message: 'aria-relevant includes "all" alongside other tokens. "all" supersedes additions, removals, and text \u2014 use aria-relevant="all" alone.',
|
|
740
|
+
rationale: '"all" is equivalent to "additions removals text". Combining it with other tokens is redundant and may confuse readers of the markup.',
|
|
741
|
+
suggestions: [
|
|
742
|
+
{
|
|
743
|
+
title: 'Use aria-relevant="all"',
|
|
744
|
+
fix: 'aria-relevant="all"'
|
|
745
|
+
}
|
|
746
|
+
]
|
|
747
|
+
};
|
|
748
|
+
},
|
|
749
|
+
missingAccessibleName(tag) {
|
|
750
|
+
return {
|
|
751
|
+
code: "ARIA2009" /* AriaMissingAccessibleName */,
|
|
752
|
+
category: 2 /* ARIA */,
|
|
753
|
+
message: `<${tag}> has no accessible name. Add aria-label or aria-labelledby.`,
|
|
754
|
+
rationale: "Elements with a landmark or interactive role must have an accessible name so that assistive technology can identify them when presenting the page outline.",
|
|
755
|
+
suggestions: [
|
|
756
|
+
{
|
|
757
|
+
title: "Add aria-label",
|
|
758
|
+
description: `Add aria-label="\u2026" directly to the <${tag}> element.`
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
title: "Add aria-labelledby",
|
|
762
|
+
description: "Point aria-labelledby at the id of an existing heading or label element."
|
|
763
|
+
}
|
|
764
|
+
]
|
|
765
|
+
};
|
|
766
|
+
},
|
|
767
|
+
attributeOnPresentational(attr, tag) {
|
|
768
|
+
return {
|
|
769
|
+
code: "ARIA2010" /* AriaAttributeOnPresentational */,
|
|
770
|
+
category: 2 /* ARIA */,
|
|
771
|
+
message: `"${attr}" is not allowed on a presentational <${tag}>. Presentational elements are invisible to assistive technology.`,
|
|
772
|
+
rationale: 'role="none" and role="presentation" (including <img alt="">) remove an element from the accessibility tree. ARIA attributes on such elements are ignored by assistive technology.',
|
|
773
|
+
suggestions: [
|
|
774
|
+
{
|
|
775
|
+
title: "Remove the attribute",
|
|
776
|
+
description: `"${attr}" has no effect when the element has role="none" or role="presentation".`
|
|
777
|
+
}
|
|
778
|
+
]
|
|
779
|
+
};
|
|
780
|
+
},
|
|
781
|
+
ariaHiddenOnFocusable(tag) {
|
|
782
|
+
return {
|
|
783
|
+
code: "ARIA2011" /* AriaHiddenOnFocusable */,
|
|
784
|
+
category: 2 /* ARIA */,
|
|
785
|
+
message: `aria-hidden="true" must not be used on focusable <${tag}> elements. Screen reader users who navigate by keyboard will encounter the element but receive no information about it.`,
|
|
786
|
+
rationale: 'aria-hidden removes an element from the accessibility tree while leaving it keyboard-reachable. This creates a "ghost" \u2014 a focusable element assistive technology cannot describe.',
|
|
787
|
+
suggestions: [
|
|
788
|
+
{
|
|
789
|
+
title: "Remove aria-hidden",
|
|
790
|
+
description: "If the element should be hidden from all users, use the HTML hidden attribute or CSS display:none instead."
|
|
791
|
+
},
|
|
792
|
+
{
|
|
793
|
+
title: "Make the element non-focusable",
|
|
794
|
+
description: 'If the element is intentionally decorative, add tabindex="-1" and disable it so it is not reachable by keyboard.'
|
|
795
|
+
}
|
|
796
|
+
]
|
|
797
|
+
};
|
|
798
|
+
},
|
|
799
|
+
invalidAttributeValue(attr, value, expected) {
|
|
800
|
+
const got = value === null ? "null" : value === void 0 ? "undefined" : typeof value === "string" ? `"${value}"` : String(value);
|
|
801
|
+
return {
|
|
802
|
+
code: "ARIA2013" /* AriaInvalidAttributeValue */,
|
|
803
|
+
category: 2 /* ARIA */,
|
|
804
|
+
message: `"${attr}" has an invalid value (${got}). Expected: ${expected}.`,
|
|
805
|
+
rationale: "ARIA attributes with invalid values are silently ignored by assistive technology, making the markup semantically inert.",
|
|
806
|
+
suggestions: [
|
|
807
|
+
{
|
|
808
|
+
title: `Use a valid value for ${attr}`,
|
|
809
|
+
description: `Valid values are: ${expected}.`
|
|
810
|
+
}
|
|
811
|
+
]
|
|
812
|
+
};
|
|
813
|
+
},
|
|
814
|
+
redundantAriaLevel(tag, level) {
|
|
815
|
+
return {
|
|
816
|
+
code: "ARIA2014" /* AriaRedundantLevelAttribute */,
|
|
817
|
+
category: 2 /* ARIA */,
|
|
818
|
+
message: `aria-level="${level}" is redundant on <${tag}>: the element already has an implicit heading level of ${level}. Remove the attribute.`,
|
|
819
|
+
rationale: 'Restating the implicit aria-level adds noise without semantic value. Use aria-level only to override the native heading level (e.g. aria-level="3" on <h2>).',
|
|
820
|
+
suggestions: [
|
|
821
|
+
{
|
|
822
|
+
title: "Remove aria-level",
|
|
823
|
+
description: `<${tag}> already implies aria-level="${level}".`
|
|
824
|
+
}
|
|
825
|
+
]
|
|
826
|
+
};
|
|
827
|
+
},
|
|
828
|
+
requiredProperty(attr, role) {
|
|
829
|
+
return {
|
|
830
|
+
code: "ARIA2012" /* AriaRequiredProperty */,
|
|
831
|
+
category: 2 /* ARIA */,
|
|
832
|
+
message: `"${attr}" is required for role="${role}" but is missing.`,
|
|
833
|
+
rationale: `WAI-ARIA 1.2 specifies required states and properties for certain roles. Without "${attr}", assistive technology cannot correctly communicate the element's state to users.`,
|
|
834
|
+
suggestions: [
|
|
835
|
+
{
|
|
836
|
+
title: `Add ${attr}`,
|
|
837
|
+
description: `role="${role}" requires "${attr}" to be present.`
|
|
838
|
+
}
|
|
839
|
+
]
|
|
840
|
+
};
|
|
841
|
+
},
|
|
842
|
+
invalidRole(role, tag) {
|
|
843
|
+
return {
|
|
844
|
+
code: "ARIA2008" /* AriaInvalidRole */,
|
|
845
|
+
category: 2 /* ARIA */,
|
|
846
|
+
message: `Invalid role "${role ?? ""}" on <${tag}>.`,
|
|
847
|
+
rationale: "An unrecognised or misapplied ARIA role is ignored by assistive technology and may degrade the accessibility of the element."
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
// ../../lib/contract/src/diagnostics/contract.ts
|
|
853
|
+
var ContractDiagnostics = {
|
|
854
|
+
unexpectedChild(typeName, index, context) {
|
|
855
|
+
return {
|
|
856
|
+
code: "COMP1004" /* UnexpectedChild */,
|
|
857
|
+
category: 0 /* Contract */,
|
|
858
|
+
component: context,
|
|
859
|
+
message: `${context}: unexpected child "${typeName}" at index ${index}.`
|
|
860
|
+
};
|
|
861
|
+
},
|
|
862
|
+
ambiguousChild(typeName, index, ruleNames, context) {
|
|
863
|
+
const quoted = ruleNames.map((n) => `"${n}"`).join(" and ");
|
|
864
|
+
return {
|
|
865
|
+
code: "COMP1005" /* AmbiguousChild */,
|
|
866
|
+
category: 0 /* Contract */,
|
|
867
|
+
component: context,
|
|
868
|
+
message: `${context}: child "${typeName}" at index ${index} matches multiple child rules: ${quoted}.`
|
|
869
|
+
};
|
|
870
|
+
},
|
|
871
|
+
cardinalityMin(ruleName, min, context) {
|
|
872
|
+
return {
|
|
873
|
+
code: "COMP1006" /* CardinalityMin */,
|
|
874
|
+
category: 0 /* Contract */,
|
|
875
|
+
component: context,
|
|
876
|
+
message: `${context}: "${ruleName}" requires at least ${min}.`
|
|
877
|
+
};
|
|
878
|
+
},
|
|
879
|
+
cardinalityMax(ruleName, max, context) {
|
|
880
|
+
return {
|
|
881
|
+
code: "COMP1007" /* CardinalityMax */,
|
|
882
|
+
category: 0 /* Contract */,
|
|
883
|
+
component: context,
|
|
884
|
+
message: `${context}: "${ruleName}" allows at most ${max}.`
|
|
885
|
+
};
|
|
886
|
+
},
|
|
887
|
+
positionViolation(ruleName, position, index, context) {
|
|
888
|
+
return {
|
|
889
|
+
code: "COMP1008" /* PositionViolation */,
|
|
890
|
+
category: 0 /* Contract */,
|
|
891
|
+
component: context,
|
|
892
|
+
message: `${context}: "${ruleName}" must be ${position}, got index ${index}`
|
|
893
|
+
};
|
|
894
|
+
},
|
|
895
|
+
unknownVariantDim(component, label2, dim) {
|
|
896
|
+
return {
|
|
897
|
+
code: "COMP1010" /* ContractUnknownVariantDim */,
|
|
898
|
+
category: 0 /* Contract */,
|
|
899
|
+
message: `${component}: ${label2} references unknown variant "${dim}".`
|
|
900
|
+
};
|
|
901
|
+
},
|
|
902
|
+
unknownVariantValue(component, label2, dim, value, valid) {
|
|
903
|
+
return {
|
|
904
|
+
code: "COMP1011" /* ContractUnknownVariantValue */,
|
|
905
|
+
category: 0 /* Contract */,
|
|
906
|
+
message: `${component}: ${label2} sets "${dim}" to unknown value "${value}" (valid: ${valid.join(", ")}).`
|
|
907
|
+
};
|
|
908
|
+
},
|
|
909
|
+
unknownRecipeKey(component, key) {
|
|
910
|
+
return {
|
|
911
|
+
code: "COMP1012" /* ContractUnknownRecipeKey */,
|
|
912
|
+
category: 0 /* Contract */,
|
|
913
|
+
message: `${component} Unknown recipeKey "${key}" \u2014 no preset with that name exists.`
|
|
914
|
+
};
|
|
915
|
+
},
|
|
916
|
+
invalidVariantValue(component, key, value) {
|
|
917
|
+
return {
|
|
918
|
+
code: "COMP1013" /* ContractInvalidVariantValue */,
|
|
919
|
+
category: 0 /* Contract */,
|
|
920
|
+
message: `${component} Variant "${key}=${value}" is not a defined value for the "${key}" dimension.`
|
|
921
|
+
};
|
|
922
|
+
},
|
|
923
|
+
allowedAsViolation(tag, allowedAs, component) {
|
|
924
|
+
const allowed = allowedAs.map((t) => `"${String(t)}"`).join(", ");
|
|
925
|
+
return {
|
|
926
|
+
code: "COMP1009" /* AllowedAsViolation */,
|
|
927
|
+
category: 0 /* Contract */,
|
|
928
|
+
component,
|
|
929
|
+
message: `<${component}>: "as" prop received "${tag}" but only [${allowed}] are allowed.`
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
|
|
934
|
+
// ../../lib/contract/src/diagnostics/html.ts
|
|
935
|
+
var HtmlDiagnostics = {
|
|
936
|
+
emptyRole(tag) {
|
|
937
|
+
return {
|
|
938
|
+
code: "HTML3002" /* HtmlEmptyRole */,
|
|
939
|
+
category: 1 /* HTML */,
|
|
940
|
+
message: `<${tag}> has an explicit empty role="". Omit the attribute instead.`
|
|
941
|
+
};
|
|
942
|
+
},
|
|
943
|
+
implicitRoleRedundant(tag, implicitRole) {
|
|
944
|
+
return {
|
|
945
|
+
code: "HTML3003" /* HtmlImplicitRoleRedundant */,
|
|
946
|
+
category: 1 /* HTML */,
|
|
947
|
+
message: `<${tag}> already has implicit role="${implicitRole}". Avoid redundant role assignment.`
|
|
948
|
+
};
|
|
949
|
+
},
|
|
950
|
+
implicitRoleOverride(tag, implicitRole, role) {
|
|
951
|
+
return {
|
|
952
|
+
code: "HTML3004" /* HtmlImplicitRoleOverride */,
|
|
953
|
+
category: 1 /* HTML */,
|
|
954
|
+
message: `<${tag}> should not override its implicit role="${implicitRole}" with role="${role}".`
|
|
955
|
+
};
|
|
956
|
+
},
|
|
957
|
+
standaloneRegionOverride(tag, implicitRole) {
|
|
958
|
+
return {
|
|
959
|
+
code: "HTML3005" /* HtmlStandaloneRegionOverride */,
|
|
960
|
+
category: 1 /* HTML */,
|
|
961
|
+
message: `<${tag}> is a self-contained element with implicit role="${implicitRole}". Assigning role="region" has been removed.`
|
|
962
|
+
};
|
|
963
|
+
},
|
|
964
|
+
landmarkRoleOverride(tag, implicitRole, role) {
|
|
965
|
+
return {
|
|
966
|
+
code: "HTML3006" /* HtmlLandmarkRoleOverride */,
|
|
967
|
+
category: 1 /* HTML */,
|
|
968
|
+
message: `<${tag}> has a fixed landmark role="${implicitRole}". role="${role}" overrides it and confuses assistive technology. The override has been removed.`
|
|
969
|
+
};
|
|
970
|
+
},
|
|
971
|
+
invalidChild(child, parent, allowed) {
|
|
972
|
+
return {
|
|
973
|
+
code: "HTML3007" /* HtmlInvalidChild */,
|
|
974
|
+
category: 1 /* HTML */,
|
|
975
|
+
message: `<${child}> is not a valid direct child of <${parent}>. Allowed: ${allowed}.`
|
|
976
|
+
};
|
|
977
|
+
}
|
|
978
|
+
};
|
|
979
|
+
|
|
980
|
+
// ../../lib/contract/src/aria/polymorphic-validator.ts
|
|
697
981
|
var VALID = [{ valid: true }];
|
|
698
982
|
function isIntrinsicTag(tag) {
|
|
699
983
|
return isString(tag);
|
|
@@ -702,26 +986,28 @@ function omitProp(obj, key) {
|
|
|
702
986
|
const { [key]: _, ...rest } = obj;
|
|
703
987
|
return rest;
|
|
704
988
|
}
|
|
705
|
-
var AriaPolicyEngine = class _AriaPolicyEngine extends
|
|
989
|
+
var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
706
990
|
#extraRules;
|
|
707
991
|
#planCache = /* @__PURE__ */ new Map();
|
|
708
992
|
static #MAX_CACHE = 100;
|
|
709
993
|
// Memoized AriaFix objects keyed by attribute name — the ARIA attribute set is
|
|
710
994
|
// finite so this Map is bounded and avoids recreating closures on every cache miss.
|
|
711
995
|
static #removeAttributeFixCache = /* @__PURE__ */ new Map();
|
|
712
|
-
constructor(
|
|
713
|
-
super(
|
|
996
|
+
constructor(diagnostics, options) {
|
|
997
|
+
super(diagnostics);
|
|
714
998
|
this.#extraRules = options?.rules ?? [];
|
|
715
999
|
}
|
|
716
1000
|
static #normalizeEmptyRole(tag, props) {
|
|
717
1001
|
if (props.role !== "") return { normalized: false };
|
|
1002
|
+
const d = HtmlDiagnostics.emptyRole(tag);
|
|
718
1003
|
return {
|
|
719
1004
|
normalized: true,
|
|
720
1005
|
result: {
|
|
721
1006
|
props: omitProp(props, "role"),
|
|
722
1007
|
violations: [
|
|
723
1008
|
{
|
|
724
|
-
message:
|
|
1009
|
+
message: d.message,
|
|
1010
|
+
diagnostic: d,
|
|
725
1011
|
tag,
|
|
726
1012
|
role: "",
|
|
727
1013
|
attribute: void 0,
|
|
@@ -734,10 +1020,9 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
734
1020
|
}
|
|
735
1021
|
static #deriveContext(tag, props) {
|
|
736
1022
|
if (!isIntrinsicTag(tag)) return { proceed: false, result: { props, violations: [] } };
|
|
737
|
-
const implicitRole = getImplicitRole(tag);
|
|
738
|
-
const
|
|
739
|
-
if (!
|
|
740
|
-
return { proceed: false, result: { props, violations: [] } };
|
|
1023
|
+
const implicitRole = getImplicitRole(tag, props);
|
|
1024
|
+
const hasRole = implicitRole != null || isString(props.role) && props.role.length > 0;
|
|
1025
|
+
if (!hasRole) return { proceed: false, result: { props, violations: [] } };
|
|
741
1026
|
const normalized = _AriaPolicyEngine.#normalizeEmptyRole(tag, props);
|
|
742
1027
|
if (normalized.normalized) return { proceed: false, result: normalized.result };
|
|
743
1028
|
const effectiveRole = props.role ?? implicitRole;
|
|
@@ -752,25 +1037,36 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
752
1037
|
static #runRules(rules, context) {
|
|
753
1038
|
const violations = [];
|
|
754
1039
|
const fixes = [];
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
if (
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
1040
|
+
iterate.forEach(rules, (rule) => {
|
|
1041
|
+
iterate.forEach(rule(context), (result) => {
|
|
1042
|
+
if (result.valid) return;
|
|
1043
|
+
const {
|
|
1044
|
+
tag,
|
|
1045
|
+
props: { role }
|
|
1046
|
+
} = context;
|
|
1047
|
+
const { message, attribute, severity } = result;
|
|
1048
|
+
const resolvedMessage = message ?? result.diagnostic?.message;
|
|
1049
|
+
const fallbackDiag = resolvedMessage == null ? AriaDiagnostics.invalidRole(role, tag) : void 0;
|
|
1050
|
+
violations.push({
|
|
1051
|
+
message: resolvedMessage ?? fallbackDiag.message,
|
|
1052
|
+
tag,
|
|
1053
|
+
role,
|
|
1054
|
+
attribute,
|
|
1055
|
+
severity,
|
|
1056
|
+
phase: "evaluate",
|
|
1057
|
+
...result.diagnostic != null && { diagnostic: result.diagnostic },
|
|
1058
|
+
...fallbackDiag != null && { diagnostic: fallbackDiag }
|
|
1059
|
+
});
|
|
1060
|
+
if (result.fixable) fixes.push(result.fix);
|
|
1061
|
+
});
|
|
1062
|
+
});
|
|
770
1063
|
return { violations, fixes };
|
|
771
1064
|
}
|
|
772
1065
|
static #getRules(context) {
|
|
773
|
-
|
|
1066
|
+
if (_AriaPolicyEngine.#hasRole(context.props) || context.effectiveRole != null && _AriaPolicyEngine.#LIVE_REGION_ROLES.has(context.effectiveRole)) {
|
|
1067
|
+
return _AriaPolicyEngine.#pipeline;
|
|
1068
|
+
}
|
|
1069
|
+
return _AriaPolicyEngine.#implicitOnlyRules;
|
|
774
1070
|
}
|
|
775
1071
|
static evaluate(tag, props) {
|
|
776
1072
|
const derived = _AriaPolicyEngine.#deriveContext(tag, props);
|
|
@@ -795,10 +1091,11 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
795
1091
|
return { props: next, violations };
|
|
796
1092
|
}
|
|
797
1093
|
report(violations) {
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
1094
|
+
iterate.forEach(violations, (v) => {
|
|
1095
|
+
const d = v.diagnostic ?? AriaDiagnostics.fromViolation(v);
|
|
1096
|
+
if (v.severity === "error") this.violate(d);
|
|
1097
|
+
else this.warn(d);
|
|
1098
|
+
});
|
|
802
1099
|
}
|
|
803
1100
|
// Cache key covers only the aria-relevant subset of props (tag + role + aria-* attrs).
|
|
804
1101
|
// Non-aria props (className, onClick, etc.) do not affect ARIA decisions and are excluded
|
|
@@ -810,27 +1107,26 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
810
1107
|
if (!isIntrinsicTag(tag)) return null;
|
|
811
1108
|
const parts = [tag];
|
|
812
1109
|
if (typeof props.role === "string") parts.push(`role:${props.role}`);
|
|
1110
|
+
if (tag === "input" && typeof props.type === "string") parts.push(`type:${props.type}`);
|
|
1111
|
+
if (tag === "img") parts.push(`alt:${props.alt === "" ? "empty" : "present"}`);
|
|
813
1112
|
const ariaEntries = [];
|
|
814
|
-
|
|
815
|
-
if (!
|
|
816
|
-
|
|
817
|
-
if (!isString(v) && !isNumber(v) && typeof v !== "boolean") continue;
|
|
1113
|
+
iterate.forEachEntry(props, (k, v) => {
|
|
1114
|
+
if (!k.startsWith("aria-")) return;
|
|
1115
|
+
if (!isString(v) && !isNumber(v) && typeof v !== "boolean") return;
|
|
818
1116
|
ariaEntries.push(`${k}:${String(v)}`);
|
|
819
|
-
}
|
|
1117
|
+
});
|
|
820
1118
|
if (ariaEntries.length > 0) parts.push(...ariaEntries.sort());
|
|
821
1119
|
return parts.join("|");
|
|
822
1120
|
}
|
|
823
1121
|
static #computePlan(inputProps, resultProps) {
|
|
824
1122
|
const removals = /* @__PURE__ */ new Set();
|
|
825
1123
|
const updates = {};
|
|
826
|
-
|
|
827
|
-
if (
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
if (!Object.hasOwn(resultProps, key)) continue;
|
|
831
|
-
const resultVal = resultProps[key];
|
|
1124
|
+
iterate.forEachKey(inputProps, (key) => {
|
|
1125
|
+
if (!(key in resultProps)) removals.add(key);
|
|
1126
|
+
});
|
|
1127
|
+
iterate.forEachEntry(resultProps, (key, resultVal) => {
|
|
832
1128
|
if (inputProps[key] !== resultVal) updates[key] = resultVal;
|
|
833
|
-
}
|
|
1129
|
+
});
|
|
834
1130
|
return { removals, updates };
|
|
835
1131
|
}
|
|
836
1132
|
static #applyPlan(props, removals, updates) {
|
|
@@ -838,15 +1134,15 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
838
1134
|
const hasUpdates = Object.keys(updates).length > 0;
|
|
839
1135
|
if (!hasRemovals && !hasUpdates) return props;
|
|
840
1136
|
const next = {};
|
|
841
|
-
|
|
842
|
-
if (
|
|
843
|
-
}
|
|
1137
|
+
iterate.forEachEntry(props, (k, v) => {
|
|
1138
|
+
if (!removals.has(k)) next[k] = v;
|
|
1139
|
+
});
|
|
844
1140
|
Object.assign(next, updates);
|
|
845
1141
|
return next;
|
|
846
1142
|
}
|
|
847
1143
|
validate(tag, props) {
|
|
848
1144
|
const key = _AriaPolicyEngine.#createPlanKey(tag, props);
|
|
849
|
-
if (!
|
|
1145
|
+
if (!isNull(key)) {
|
|
850
1146
|
const cached = this.#planCache.get(key);
|
|
851
1147
|
if (cached !== void 0) {
|
|
852
1148
|
this.#planCache.delete(key);
|
|
@@ -860,7 +1156,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
860
1156
|
}
|
|
861
1157
|
const result = this.#extraRules.length ? _AriaPolicyEngine.#evaluateWithRules(tag, props, this.#extraRules) : _AriaPolicyEngine.evaluate(tag, props);
|
|
862
1158
|
if (result.violations.length > 0) this.report(result.violations);
|
|
863
|
-
if (!
|
|
1159
|
+
if (!isNull(key)) {
|
|
864
1160
|
const { removals, updates } = _AriaPolicyEngine.#computePlan(
|
|
865
1161
|
props,
|
|
866
1162
|
result.props
|
|
@@ -881,12 +1177,12 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
881
1177
|
if (fixes.length === 0) return props;
|
|
882
1178
|
const sorted = [...fixes].sort((a, b) => (a.priority ?? Infinity) - (b.priority ?? Infinity));
|
|
883
1179
|
let next = props;
|
|
884
|
-
|
|
1180
|
+
iterate.forEach(sorted, ({ apply }) => {
|
|
885
1181
|
const effectiveRole = next.role ?? implicitRole;
|
|
886
1182
|
const fixContext = { tag, implicitRole, effectiveRole, props: next };
|
|
887
1183
|
const fixResult = apply(fixContext);
|
|
888
1184
|
if (fixResult.applied) next = fixResult.next;
|
|
889
|
-
}
|
|
1185
|
+
});
|
|
890
1186
|
return next;
|
|
891
1187
|
}
|
|
892
1188
|
static #removeRole = {
|
|
@@ -914,10 +1210,26 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
914
1210
|
_AriaPolicyEngine.#checkInvalidRoleOverride,
|
|
915
1211
|
_AriaPolicyEngine.#checkRedundantRole,
|
|
916
1212
|
_AriaPolicyEngine.#checkStandaloneRegion,
|
|
1213
|
+
_AriaPolicyEngine.#checkAriaAttributeValues,
|
|
917
1214
|
_AriaPolicyEngine.#checkInvalidAriaAttributes,
|
|
1215
|
+
_AriaPolicyEngine.#checkRequiredAriaProperties,
|
|
1216
|
+
_AriaPolicyEngine.#checkNameRequiredRoles,
|
|
1217
|
+
_AriaPolicyEngine.#checkRedundantAriaLevel,
|
|
918
1218
|
_AriaPolicyEngine.#checkMissingLiveRegion,
|
|
919
1219
|
_AriaPolicyEngine.#checkMissingAtomic,
|
|
920
|
-
_AriaPolicyEngine.#checkInvalidAriaRelevant
|
|
1220
|
+
_AriaPolicyEngine.#checkInvalidAriaRelevant,
|
|
1221
|
+
_AriaPolicyEngine.#checkAriaHiddenOnFocusable,
|
|
1222
|
+
_AriaPolicyEngine.#checkPresentationalAriaAttributes
|
|
1223
|
+
];
|
|
1224
|
+
// Rules for elements with an implicit role but no explicit role (not a live region).
|
|
1225
|
+
static #implicitOnlyRules = [
|
|
1226
|
+
_AriaPolicyEngine.#checkAriaAttributeValues,
|
|
1227
|
+
_AriaPolicyEngine.#checkInvalidAriaAttributes,
|
|
1228
|
+
_AriaPolicyEngine.#checkRequiredAriaProperties,
|
|
1229
|
+
_AriaPolicyEngine.#checkNameRequiredRoles,
|
|
1230
|
+
_AriaPolicyEngine.#checkRedundantAriaLevel,
|
|
1231
|
+
_AriaPolicyEngine.#checkAriaHiddenOnFocusable,
|
|
1232
|
+
_AriaPolicyEngine.#checkPresentationalAriaAttributes
|
|
921
1233
|
];
|
|
922
1234
|
static #checkInvalidRoleOverride({
|
|
923
1235
|
tag,
|
|
@@ -933,7 +1245,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
933
1245
|
fixable: true,
|
|
934
1246
|
severity: "error",
|
|
935
1247
|
fix: _AriaPolicyEngine.#removeRole,
|
|
936
|
-
|
|
1248
|
+
diagnostic: HtmlDiagnostics.implicitRoleOverride(tag, implicitRole, role)
|
|
937
1249
|
}
|
|
938
1250
|
];
|
|
939
1251
|
}
|
|
@@ -947,45 +1259,302 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
947
1259
|
valid: false,
|
|
948
1260
|
fixable: true,
|
|
949
1261
|
severity: "warning",
|
|
950
|
-
fix: _AriaPolicyEngine.#removeRole,
|
|
951
|
-
|
|
1262
|
+
fix: _AriaPolicyEngine.#removeRole,
|
|
1263
|
+
diagnostic: HtmlDiagnostics.implicitRoleRedundant(tag, implicitRole)
|
|
1264
|
+
}
|
|
1265
|
+
];
|
|
1266
|
+
}
|
|
1267
|
+
static #checkStandaloneRegion({ tag, props, implicitRole }) {
|
|
1268
|
+
const role = props.role;
|
|
1269
|
+
if (role !== "region") return VALID;
|
|
1270
|
+
if (!isStandaloneTag(tag)) return VALID;
|
|
1271
|
+
return [
|
|
1272
|
+
{
|
|
1273
|
+
valid: false,
|
|
1274
|
+
fixable: true,
|
|
1275
|
+
severity: "error",
|
|
1276
|
+
fix: _AriaPolicyEngine.#removeRole,
|
|
1277
|
+
diagnostic: HtmlDiagnostics.standaloneRegionOverride(tag, implicitRole ?? tag)
|
|
1278
|
+
}
|
|
1279
|
+
];
|
|
1280
|
+
}
|
|
1281
|
+
static #checkInvalidAriaAttributes({
|
|
1282
|
+
tag,
|
|
1283
|
+
props,
|
|
1284
|
+
effectiveRole
|
|
1285
|
+
}) {
|
|
1286
|
+
if (effectiveRole === "none" || effectiveRole === "presentation") return VALID;
|
|
1287
|
+
const results = [];
|
|
1288
|
+
iterate.forEachEntry(props, (key) => {
|
|
1289
|
+
if (!key.startsWith("aria-")) return;
|
|
1290
|
+
if (isGlobalAriaAttribute(key)) return;
|
|
1291
|
+
if (isAriaAttributeValidForRole(key, effectiveRole)) return;
|
|
1292
|
+
results.push({
|
|
1293
|
+
valid: false,
|
|
1294
|
+
severity: "warning",
|
|
1295
|
+
fixable: true,
|
|
1296
|
+
attribute: key,
|
|
1297
|
+
diagnostic: AriaDiagnostics.attributeInvalid(key, effectiveRole ?? tag),
|
|
1298
|
+
fix: _AriaPolicyEngine.#makeRemoveAttributeFix(key)
|
|
1299
|
+
});
|
|
1300
|
+
});
|
|
1301
|
+
return results;
|
|
1302
|
+
}
|
|
1303
|
+
// ─── ARIA attribute value validation ──────────────────────────────────────
|
|
1304
|
+
// Accepted value shapes for typed ARIA attributes.
|
|
1305
|
+
// Attributes not in this map are unconstrained (arbitrary string values permitted).
|
|
1306
|
+
static #ARIA_VALUE_TYPES = /* @__PURE__ */ new Map([
|
|
1307
|
+
// Boolean (true | false)
|
|
1308
|
+
["aria-atomic", { kind: "boolean" }],
|
|
1309
|
+
["aria-busy", { kind: "boolean" }],
|
|
1310
|
+
["aria-disabled", { kind: "boolean" }],
|
|
1311
|
+
["aria-expanded", { kind: "boolean" }],
|
|
1312
|
+
["aria-hidden", { kind: "boolean" }],
|
|
1313
|
+
["aria-modal", { kind: "boolean" }],
|
|
1314
|
+
["aria-multiline", { kind: "boolean" }],
|
|
1315
|
+
["aria-multiselectable", { kind: "boolean" }],
|
|
1316
|
+
["aria-readonly", { kind: "boolean" }],
|
|
1317
|
+
["aria-required", { kind: "boolean" }],
|
|
1318
|
+
["aria-selected", { kind: "boolean" }],
|
|
1319
|
+
// Tristate (true | false | mixed)
|
|
1320
|
+
["aria-checked", { kind: "tristate" }],
|
|
1321
|
+
["aria-pressed", { kind: "tristate" }],
|
|
1322
|
+
// Numeric (any finite number)
|
|
1323
|
+
["aria-valuenow", { kind: "number" }],
|
|
1324
|
+
["aria-valuemin", { kind: "number" }],
|
|
1325
|
+
["aria-valuemax", { kind: "number" }],
|
|
1326
|
+
// Integer with optional range
|
|
1327
|
+
["aria-level", { kind: "integer", min: 1, max: 6 }],
|
|
1328
|
+
["aria-posinset", { kind: "integer", min: 1 }],
|
|
1329
|
+
["aria-setsize", { kind: "integer", min: -1 }],
|
|
1330
|
+
["aria-rowcount", { kind: "integer", min: -1 }],
|
|
1331
|
+
["aria-colcount", { kind: "integer", min: -1 }],
|
|
1332
|
+
["aria-rowindex", { kind: "integer", min: 1 }],
|
|
1333
|
+
["aria-colindex", { kind: "integer", min: 1 }],
|
|
1334
|
+
["aria-rowspan", { kind: "integer", min: 0 }],
|
|
1335
|
+
["aria-colspan", { kind: "integer", min: 0 }],
|
|
1336
|
+
// Enum (specific allowed tokens)
|
|
1337
|
+
["aria-autocomplete", { kind: "enum", values: /* @__PURE__ */ new Set(["inline", "list", "both", "none"]) }],
|
|
1338
|
+
[
|
|
1339
|
+
"aria-current",
|
|
1340
|
+
{
|
|
1341
|
+
kind: "enum",
|
|
1342
|
+
values: /* @__PURE__ */ new Set(["page", "step", "location", "date", "time", "true", "false"])
|
|
1343
|
+
}
|
|
1344
|
+
],
|
|
1345
|
+
[
|
|
1346
|
+
"aria-haspopup",
|
|
1347
|
+
{
|
|
1348
|
+
kind: "enum",
|
|
1349
|
+
values: /* @__PURE__ */ new Set(["false", "true", "menu", "listbox", "tree", "grid", "dialog"])
|
|
1350
|
+
}
|
|
1351
|
+
],
|
|
1352
|
+
["aria-invalid", { kind: "enum", values: /* @__PURE__ */ new Set(["grammar", "false", "spelling", "true"]) }],
|
|
1353
|
+
["aria-live", { kind: "enum", values: /* @__PURE__ */ new Set(["assertive", "off", "polite"]) }],
|
|
1354
|
+
[
|
|
1355
|
+
"aria-orientation",
|
|
1356
|
+
{ kind: "enum", values: /* @__PURE__ */ new Set(["horizontal", "vertical", "undefined"]) }
|
|
1357
|
+
],
|
|
1358
|
+
["aria-sort", { kind: "enum", values: /* @__PURE__ */ new Set(["ascending", "descending", "none", "other"]) }]
|
|
1359
|
+
]);
|
|
1360
|
+
static #isValidAriaValue(value, type) {
|
|
1361
|
+
switch (type.kind) {
|
|
1362
|
+
case "boolean":
|
|
1363
|
+
return value === "true" || value === "false" || value === true || value === false;
|
|
1364
|
+
case "tristate":
|
|
1365
|
+
return value === "true" || value === "false" || value === "mixed" || value === true || value === false;
|
|
1366
|
+
case "number": {
|
|
1367
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
1368
|
+
if (typeof value !== "string") return false;
|
|
1369
|
+
const n = parseFloat(value);
|
|
1370
|
+
return Number.isFinite(n);
|
|
1371
|
+
}
|
|
1372
|
+
case "integer": {
|
|
1373
|
+
const n = typeof value === "number" ? value : typeof value === "string" ? parseInt(value, 10) : NaN;
|
|
1374
|
+
if (!Number.isFinite(n) || !Number.isInteger(n)) return false;
|
|
1375
|
+
if (type.min !== void 0 && n < type.min) return false;
|
|
1376
|
+
if (type.max !== void 0 && n > type.max) return false;
|
|
1377
|
+
return true;
|
|
1378
|
+
}
|
|
1379
|
+
case "enum":
|
|
1380
|
+
return typeof value === "string" && type.values.has(value);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
static #describeExpected(type) {
|
|
1384
|
+
switch (type.kind) {
|
|
1385
|
+
case "boolean":
|
|
1386
|
+
return '"true" or "false"';
|
|
1387
|
+
case "tristate":
|
|
1388
|
+
return '"true", "false", or "mixed"';
|
|
1389
|
+
case "number":
|
|
1390
|
+
return "a finite number";
|
|
1391
|
+
case "integer": {
|
|
1392
|
+
const parts = ["an integer"];
|
|
1393
|
+
if (type.min !== void 0 && type.max !== void 0)
|
|
1394
|
+
parts.push(`between ${type.min} and ${type.max}`);
|
|
1395
|
+
else if (type.min !== void 0) parts.push(`\u2265 ${type.min}`);
|
|
1396
|
+
else if (type.max !== void 0) parts.push(`\u2264 ${type.max}`);
|
|
1397
|
+
return parts.join(" ");
|
|
1398
|
+
}
|
|
1399
|
+
case "enum":
|
|
1400
|
+
return [...type.values].map((v) => `"${v}"`).join(", ");
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
static #checkAriaAttributeValues({ props, effectiveRole }) {
|
|
1404
|
+
if (effectiveRole === "none" || effectiveRole === "presentation") return VALID;
|
|
1405
|
+
const results = [];
|
|
1406
|
+
iterate.forEachEntry(props, (key, value) => {
|
|
1407
|
+
if (!key.startsWith("aria-")) return;
|
|
1408
|
+
const type = _AriaPolicyEngine.#ARIA_VALUE_TYPES.get(key);
|
|
1409
|
+
if (type == null) return;
|
|
1410
|
+
if (_AriaPolicyEngine.#isValidAriaValue(value, type)) return;
|
|
1411
|
+
results.push({
|
|
1412
|
+
valid: false,
|
|
1413
|
+
fixable: true,
|
|
1414
|
+
severity: "warning",
|
|
1415
|
+
attribute: key,
|
|
1416
|
+
diagnostic: AriaDiagnostics.invalidAttributeValue(
|
|
1417
|
+
key,
|
|
1418
|
+
value,
|
|
1419
|
+
_AriaPolicyEngine.#describeExpected(type)
|
|
1420
|
+
),
|
|
1421
|
+
fix: _AriaPolicyEngine.#makeRemoveAttributeFix(key)
|
|
1422
|
+
});
|
|
1423
|
+
});
|
|
1424
|
+
return results;
|
|
1425
|
+
}
|
|
1426
|
+
// ─── Heading implicit level ────────────────────────────────────────────────
|
|
1427
|
+
static #HEADING_IMPLICIT_LEVELS = /* @__PURE__ */ new Map([
|
|
1428
|
+
["h1", 1],
|
|
1429
|
+
["h2", 2],
|
|
1430
|
+
["h3", 3],
|
|
1431
|
+
["h4", 4],
|
|
1432
|
+
["h5", 5],
|
|
1433
|
+
["h6", 6]
|
|
1434
|
+
]);
|
|
1435
|
+
static #checkRedundantAriaLevel({
|
|
1436
|
+
tag,
|
|
1437
|
+
props,
|
|
1438
|
+
effectiveRole
|
|
1439
|
+
}) {
|
|
1440
|
+
if (effectiveRole === "none" || effectiveRole === "presentation") return VALID;
|
|
1441
|
+
const implicitLevel = _AriaPolicyEngine.#HEADING_IMPLICIT_LEVELS.get(tag);
|
|
1442
|
+
if (implicitLevel == null) return VALID;
|
|
1443
|
+
const raw = props["aria-level"];
|
|
1444
|
+
if (raw == null) return VALID;
|
|
1445
|
+
const n = typeof raw === "number" ? raw : typeof raw === "string" ? parseInt(raw, 10) : NaN;
|
|
1446
|
+
if (!Number.isFinite(n) || n !== implicitLevel) return VALID;
|
|
1447
|
+
return [
|
|
1448
|
+
{
|
|
1449
|
+
valid: false,
|
|
1450
|
+
fixable: true,
|
|
1451
|
+
severity: "warning",
|
|
1452
|
+
attribute: "aria-level",
|
|
1453
|
+
diagnostic: AriaDiagnostics.redundantAriaLevel(tag, implicitLevel),
|
|
1454
|
+
fix: _AriaPolicyEngine.#makeRemoveAttributeFix("aria-level")
|
|
1455
|
+
}
|
|
1456
|
+
];
|
|
1457
|
+
}
|
|
1458
|
+
// ─── Name-required roles ───────────────────────────────────────────────────
|
|
1459
|
+
// Roles that always require an accessible name per WAI-ARIA APG.
|
|
1460
|
+
// Dialog and landmark names are enforced via contracts (ariaContract) rather than
|
|
1461
|
+
// the built-in pipeline so consumers can opt in; img is built in because role=img
|
|
1462
|
+
// on any element (including bare <img>) is definitionally useless without a name.
|
|
1463
|
+
static #NAME_REQUIRED_ROLES = /* @__PURE__ */ new Set(["img"]);
|
|
1464
|
+
static #checkNameRequiredRoles({
|
|
1465
|
+
tag,
|
|
1466
|
+
props,
|
|
1467
|
+
effectiveRole
|
|
1468
|
+
}) {
|
|
1469
|
+
if (!effectiveRole || !_AriaPolicyEngine.#NAME_REQUIRED_ROLES.has(effectiveRole)) return VALID;
|
|
1470
|
+
if ("aria-label" in props || "aria-labelledby" in props) return VALID;
|
|
1471
|
+
if (tag === "img" && typeof props.alt === "string" && props.alt.length > 0) return VALID;
|
|
1472
|
+
return [
|
|
1473
|
+
{
|
|
1474
|
+
valid: false,
|
|
1475
|
+
fixable: false,
|
|
1476
|
+
severity: "warning",
|
|
1477
|
+
diagnostic: AriaDiagnostics.missingAccessibleName(tag)
|
|
952
1478
|
}
|
|
953
1479
|
];
|
|
954
1480
|
}
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1481
|
+
// WAI-ARIA 1.2 required states and properties, keyed by role.
|
|
1482
|
+
// Source: https://www.w3.org/TR/wai-aria-1.2/#requiredState
|
|
1483
|
+
static #REQUIRED_PROPERTIES = /* @__PURE__ */ new Map([
|
|
1484
|
+
["combobox", ["aria-expanded"]],
|
|
1485
|
+
["option", ["aria-selected"]],
|
|
1486
|
+
["slider", ["aria-valuenow"]],
|
|
1487
|
+
["scrollbar", ["aria-controls", "aria-valuenow"]],
|
|
1488
|
+
["spinbutton", ["aria-valuenow"]]
|
|
1489
|
+
]);
|
|
1490
|
+
static #checkRequiredAriaProperties({
|
|
1491
|
+
props,
|
|
1492
|
+
effectiveRole
|
|
1493
|
+
}) {
|
|
1494
|
+
if (!effectiveRole) return VALID;
|
|
1495
|
+
const required = _AriaPolicyEngine.#REQUIRED_PROPERTIES.get(effectiveRole);
|
|
1496
|
+
if (required == null) return VALID;
|
|
1497
|
+
const results = [];
|
|
1498
|
+
iterate.forEach(required, (attr) => {
|
|
1499
|
+
if (attr in props) return;
|
|
1500
|
+
results.push({
|
|
1501
|
+
valid: false,
|
|
1502
|
+
fixable: false,
|
|
1503
|
+
severity: "warning",
|
|
1504
|
+
attribute: attr,
|
|
1505
|
+
diagnostic: AriaDiagnostics.requiredProperty(attr, effectiveRole)
|
|
1506
|
+
});
|
|
1507
|
+
});
|
|
1508
|
+
return results;
|
|
1509
|
+
}
|
|
1510
|
+
// Natively interactive HTML elements — always keyboard-reachable unless explicitly disabled.
|
|
1511
|
+
static #INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
|
|
1512
|
+
"a",
|
|
1513
|
+
"button",
|
|
1514
|
+
"input",
|
|
1515
|
+
"select",
|
|
1516
|
+
"textarea"
|
|
1517
|
+
]);
|
|
1518
|
+
// WAI-ARIA 1.2 §6.6: aria-hidden="true" must not be placed on focusable elements.
|
|
1519
|
+
static #checkAriaHiddenOnFocusable({ tag, props }) {
|
|
1520
|
+
if (props["aria-hidden"] !== "true" && props["aria-hidden"] !== true) return VALID;
|
|
1521
|
+
const isInteractive = _AriaPolicyEngine.#INTERACTIVE_TAGS.has(tag);
|
|
1522
|
+
if (!isInteractive) {
|
|
1523
|
+
const tabindex = props.tabindex;
|
|
1524
|
+
const n = typeof tabindex === "number" ? tabindex : typeof tabindex === "string" ? parseInt(tabindex, 10) : NaN;
|
|
1525
|
+
if (!Number.isFinite(n) || n < 0) return VALID;
|
|
1526
|
+
}
|
|
959
1527
|
return [
|
|
960
1528
|
{
|
|
961
1529
|
valid: false,
|
|
962
|
-
fixable:
|
|
1530
|
+
fixable: false,
|
|
963
1531
|
severity: "error",
|
|
964
|
-
|
|
965
|
-
|
|
1532
|
+
attribute: "aria-hidden",
|
|
1533
|
+
diagnostic: AriaDiagnostics.ariaHiddenOnFocusable(tag)
|
|
966
1534
|
}
|
|
967
1535
|
];
|
|
968
1536
|
}
|
|
969
|
-
|
|
1537
|
+
// Presentational elements (role=none/presentation, including <img alt="">) are removed
|
|
1538
|
+
// from the accessibility tree — ARIA attributes on them are meaningless and misleading.
|
|
1539
|
+
static #checkPresentationalAriaAttributes({
|
|
970
1540
|
tag,
|
|
971
1541
|
props,
|
|
972
1542
|
effectiveRole
|
|
973
1543
|
}) {
|
|
1544
|
+
if (effectiveRole !== "none" && effectiveRole !== "presentation") return VALID;
|
|
974
1545
|
const results = [];
|
|
975
|
-
|
|
976
|
-
if (!
|
|
977
|
-
if (
|
|
978
|
-
if (isGlobalAriaAttribute(key)) continue;
|
|
979
|
-
if (isAriaAttributeValidForRole(key, effectiveRole)) continue;
|
|
1546
|
+
iterate.forEachEntry(props, (key) => {
|
|
1547
|
+
if (!key.startsWith("aria-")) return;
|
|
1548
|
+
if (key === "aria-hidden") return;
|
|
980
1549
|
results.push({
|
|
981
1550
|
valid: false,
|
|
982
|
-
severity: "warning",
|
|
983
1551
|
fixable: true,
|
|
1552
|
+
severity: "warning",
|
|
984
1553
|
attribute: key,
|
|
985
|
-
|
|
1554
|
+
diagnostic: AriaDiagnostics.attributeOnPresentational(key, tag),
|
|
986
1555
|
fix: _AriaPolicyEngine.#makeRemoveAttributeFix(key)
|
|
987
1556
|
});
|
|
988
|
-
}
|
|
1557
|
+
});
|
|
989
1558
|
return results;
|
|
990
1559
|
}
|
|
991
1560
|
// WAI-ARIA live region roles and their implied aria-live politeness values.
|
|
@@ -1014,7 +1583,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
1014
1583
|
fixable: true,
|
|
1015
1584
|
severity: "warning",
|
|
1016
1585
|
fix: injectLive,
|
|
1017
|
-
|
|
1586
|
+
diagnostic: AriaDiagnostics.missingLiveRegion(effectiveRole, impliedLive)
|
|
1018
1587
|
}
|
|
1019
1588
|
];
|
|
1020
1589
|
}
|
|
@@ -1026,7 +1595,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
1026
1595
|
valid: false,
|
|
1027
1596
|
fixable: false,
|
|
1028
1597
|
severity: "warning",
|
|
1029
|
-
|
|
1598
|
+
diagnostic: AriaDiagnostics.missingAtomic(effectiveRole)
|
|
1030
1599
|
}
|
|
1031
1600
|
];
|
|
1032
1601
|
}
|
|
@@ -1055,7 +1624,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
1055
1624
|
fixable: true,
|
|
1056
1625
|
severity: "warning",
|
|
1057
1626
|
attribute: "aria-relevant",
|
|
1058
|
-
|
|
1627
|
+
diagnostic: AriaDiagnostics.relevantInvalidTokens(invalid),
|
|
1059
1628
|
fix: _AriaPolicyEngine.#makeRemoveAttributeFix("aria-relevant")
|
|
1060
1629
|
}
|
|
1061
1630
|
];
|
|
@@ -1067,7 +1636,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
1067
1636
|
fixable: true,
|
|
1068
1637
|
severity: "warning",
|
|
1069
1638
|
attribute: "aria-relevant",
|
|
1070
|
-
|
|
1639
|
+
diagnostic: AriaDiagnostics.relevantSuperseded(),
|
|
1071
1640
|
fix: _AriaPolicyEngine.#normalizeRelevantAllFix
|
|
1072
1641
|
}
|
|
1073
1642
|
];
|
|
@@ -1075,6 +1644,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
1075
1644
|
return VALID;
|
|
1076
1645
|
}
|
|
1077
1646
|
};
|
|
1647
|
+
|
|
1648
|
+
// ../../lib/contract/src/children/get-type-name.ts
|
|
1078
1649
|
function getTypeName(value) {
|
|
1079
1650
|
if (value === null) return "null";
|
|
1080
1651
|
if (value === void 0) return "undefined";
|
|
@@ -1085,39 +1656,8 @@ function getTypeName(value) {
|
|
|
1085
1656
|
const name = value.constructor?.name;
|
|
1086
1657
|
return typeof name === "string" && name !== "Object" ? name : "object";
|
|
1087
1658
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
constructor(ctx = "") {
|
|
1091
|
-
this.#prefix = ctx ? `${ctx}:
|
|
1092
|
-
` : "";
|
|
1093
|
-
}
|
|
1094
|
-
#template(typeName, index, prefix = "", suffix = "") {
|
|
1095
|
-
const leadingStr = prefix ? `${prefix} ` : "";
|
|
1096
|
-
const followingStr = suffix ? ` ${suffix}` : "";
|
|
1097
|
-
return `${leadingStr}child "${typeName}" at index ${index}${followingStr}.`;
|
|
1098
|
-
}
|
|
1099
|
-
unexpectedChild(typeName, index) {
|
|
1100
|
-
return this.#template(typeName, index, "unexpected");
|
|
1101
|
-
}
|
|
1102
|
-
multipleMatches(typeName, index, ruleNames) {
|
|
1103
|
-
const quoted = ruleNames.map((n) => `"${n}"`);
|
|
1104
|
-
return this.#template(
|
|
1105
|
-
typeName,
|
|
1106
|
-
index,
|
|
1107
|
-
"",
|
|
1108
|
-
`matches multiple child rules: ${quoted.join(" and ")}`
|
|
1109
|
-
);
|
|
1110
|
-
}
|
|
1111
|
-
#format(errors) {
|
|
1112
|
-
return this.#prefix + errors.join("\n");
|
|
1113
|
-
}
|
|
1114
|
-
toError(errors) {
|
|
1115
|
-
if (errors.length === 0) {
|
|
1116
|
-
return new Error(this.#prefix + "Unknown validation error.");
|
|
1117
|
-
}
|
|
1118
|
-
return new Error(this.#format(errors));
|
|
1119
|
-
}
|
|
1120
|
-
};
|
|
1659
|
+
|
|
1660
|
+
// ../../lib/contract/src/children/normalize-child-rule.ts
|
|
1121
1661
|
function normalizeCardinality(input, impliesSingleton) {
|
|
1122
1662
|
const min = input?.min ?? 0;
|
|
1123
1663
|
const max = input?.max ?? (impliesSingleton ? 1 : Infinity);
|
|
@@ -1142,6 +1682,8 @@ function normalizeChildRule(rule) {
|
|
|
1142
1682
|
cardinality: normalizeCardinality(rule.cardinality, impliesSingleton)
|
|
1143
1683
|
};
|
|
1144
1684
|
}
|
|
1685
|
+
|
|
1686
|
+
// ../../lib/contract/src/children/rules-matcher.ts
|
|
1145
1687
|
function getChildType(child) {
|
|
1146
1688
|
if (!isObject(child) || !("type" in child)) return void 0;
|
|
1147
1689
|
return child.type;
|
|
@@ -1150,8 +1692,8 @@ function buildPartialIndex(rules) {
|
|
|
1150
1692
|
const typeIndex = /* @__PURE__ */ new Map();
|
|
1151
1693
|
const duplicateTypes = /* @__PURE__ */ new Set();
|
|
1152
1694
|
const untypedIndices = [];
|
|
1153
|
-
|
|
1154
|
-
const t =
|
|
1695
|
+
iterate.forEach(rules, (rule, ri) => {
|
|
1696
|
+
const t = rule.type;
|
|
1155
1697
|
if (t === void 0) {
|
|
1156
1698
|
untypedIndices.push(ri);
|
|
1157
1699
|
} else if (typeIndex.has(t)) {
|
|
@@ -1159,12 +1701,14 @@ function buildPartialIndex(rules) {
|
|
|
1159
1701
|
} else {
|
|
1160
1702
|
typeIndex.set(t, ri);
|
|
1161
1703
|
}
|
|
1162
|
-
}
|
|
1704
|
+
});
|
|
1163
1705
|
if (duplicateTypes.size > 0) {
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1706
|
+
iterate.forEachSet(duplicateTypes, (t) => {
|
|
1707
|
+
typeIndex.delete(t);
|
|
1708
|
+
});
|
|
1709
|
+
iterate.forEach(rules, (rule, ri) => {
|
|
1710
|
+
if (duplicateTypes.has(rule.type)) untypedIndices.push(ri);
|
|
1711
|
+
});
|
|
1168
1712
|
}
|
|
1169
1713
|
return { typeIndex, untypedIndices };
|
|
1170
1714
|
}
|
|
@@ -1183,10 +1727,10 @@ var RuleMatcher = class {
|
|
|
1183
1727
|
const reverse = /* @__PURE__ */ new Map();
|
|
1184
1728
|
const unexpectedIndices = /* @__PURE__ */ new Set();
|
|
1185
1729
|
const ambiguousIndices = /* @__PURE__ */ new Set();
|
|
1186
|
-
|
|
1730
|
+
iterate.forEach(this.#rules, (_, ri) => {
|
|
1187
1731
|
reverse.set(ri, /* @__PURE__ */ new Set());
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1732
|
+
});
|
|
1733
|
+
iterate.forEach(children, (child, ci) => {
|
|
1190
1734
|
const t = getChildType(child);
|
|
1191
1735
|
if (t !== void 0) {
|
|
1192
1736
|
const ri = this.#typeIndex.get(t);
|
|
@@ -1200,8 +1744,8 @@ var RuleMatcher = class {
|
|
|
1200
1744
|
reverse.get(ri).add(ci);
|
|
1201
1745
|
}
|
|
1202
1746
|
}
|
|
1203
|
-
|
|
1204
|
-
if (!this.#rules[ri].match(child))
|
|
1747
|
+
iterate.forEach(this.#untypedIndices, (ri) => {
|
|
1748
|
+
if (!this.#rules[ri].match(child)) return;
|
|
1205
1749
|
let childEntry = forward.get(ci);
|
|
1206
1750
|
if (!childEntry) {
|
|
1207
1751
|
childEntry = /* @__PURE__ */ new Set();
|
|
@@ -1209,33 +1753,35 @@ var RuleMatcher = class {
|
|
|
1209
1753
|
}
|
|
1210
1754
|
childEntry.add(ri);
|
|
1211
1755
|
reverse.get(ri).add(ci);
|
|
1212
|
-
}
|
|
1756
|
+
});
|
|
1213
1757
|
const entry = forward.get(ci);
|
|
1214
1758
|
if (!entry) {
|
|
1215
1759
|
unexpectedIndices.add(ci);
|
|
1216
1760
|
} else if (entry.size > 1) {
|
|
1217
1761
|
ambiguousIndices.add(ci);
|
|
1218
1762
|
}
|
|
1219
|
-
}
|
|
1763
|
+
});
|
|
1220
1764
|
return { matrix: { childToRules: { forward, reverse } }, unexpectedIndices, ambiguousIndices };
|
|
1221
1765
|
}
|
|
1222
1766
|
};
|
|
1223
|
-
|
|
1767
|
+
|
|
1768
|
+
// ../../lib/contract/src/children/rule-validator.ts
|
|
1769
|
+
var RuleValidator = class _RuleValidator extends InvariantBase {
|
|
1224
1770
|
#context;
|
|
1225
|
-
constructor(context,
|
|
1226
|
-
super(
|
|
1771
|
+
constructor(context, diagnostics) {
|
|
1772
|
+
super(diagnostics);
|
|
1227
1773
|
this.#context = context;
|
|
1228
1774
|
}
|
|
1229
1775
|
validate(rules, matrix, childCount) {
|
|
1230
1776
|
const firstIndex = 0;
|
|
1231
1777
|
const lastIndex = childCount - 1;
|
|
1232
|
-
|
|
1778
|
+
iterate.forEach(rules, (rule, ri) => {
|
|
1233
1779
|
const matches = matrix.childToRules.reverse.get(ri);
|
|
1234
1780
|
const matchCount = matches.size;
|
|
1235
1781
|
this.#validateCardinality(rule, matchCount);
|
|
1236
|
-
if (matchCount === 0)
|
|
1782
|
+
if (matchCount === 0) return;
|
|
1237
1783
|
this.#validatePositions(rule, matches, firstIndex, lastIndex);
|
|
1238
|
-
}
|
|
1784
|
+
});
|
|
1239
1785
|
}
|
|
1240
1786
|
#validateCardinality(rule, matchCount) {
|
|
1241
1787
|
const { cardinality, name } = rule;
|
|
@@ -1244,21 +1790,21 @@ var RuleValidator = class _RuleValidator extends StrictBase {
|
|
|
1244
1790
|
}
|
|
1245
1791
|
const { min, max } = cardinality;
|
|
1246
1792
|
if (matchCount < min) {
|
|
1247
|
-
this.violate(
|
|
1793
|
+
this.violate(ContractDiagnostics.cardinalityMin(name, min, this.#context));
|
|
1248
1794
|
return;
|
|
1249
1795
|
}
|
|
1250
1796
|
if (matchCount > max) {
|
|
1251
|
-
this.violate(
|
|
1797
|
+
this.violate(ContractDiagnostics.cardinalityMax(name, max, this.#context));
|
|
1252
1798
|
}
|
|
1253
1799
|
}
|
|
1254
1800
|
#validatePositions(rule, matches, firstIndex, lastIndex) {
|
|
1255
1801
|
const { name, position } = rule;
|
|
1256
|
-
|
|
1802
|
+
iterate.forEachSet(matches, (index) => {
|
|
1257
1803
|
if (_RuleValidator.#isValidPosition(index, position, firstIndex, lastIndex)) {
|
|
1258
|
-
|
|
1804
|
+
return;
|
|
1259
1805
|
}
|
|
1260
|
-
this.violate(
|
|
1261
|
-
}
|
|
1806
|
+
this.violate(ContractDiagnostics.positionViolation(name, position, index, this.#context));
|
|
1807
|
+
});
|
|
1262
1808
|
}
|
|
1263
1809
|
static #isValidPosition(matchIndex, position, firstIndex, lastIndex) {
|
|
1264
1810
|
switch (position) {
|
|
@@ -1273,48 +1819,50 @@ var RuleValidator = class _RuleValidator extends StrictBase {
|
|
|
1273
1819
|
}
|
|
1274
1820
|
}
|
|
1275
1821
|
};
|
|
1276
|
-
|
|
1822
|
+
|
|
1823
|
+
// ../../lib/contract/src/children/children-evaluator.ts
|
|
1824
|
+
var ChildrenEvaluator = class extends InvariantBase {
|
|
1825
|
+
#context;
|
|
1277
1826
|
#rules;
|
|
1278
1827
|
#ruleNames;
|
|
1279
1828
|
#matcher;
|
|
1280
1829
|
#ruleValidator;
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
this.#rules = rules.map((
|
|
1285
|
-
this.#ruleNames = this.#rules.map((
|
|
1286
|
-
|
|
1830
|
+
constructor(rules, diagnostics, context = "Component") {
|
|
1831
|
+
super(diagnostics);
|
|
1832
|
+
this.#context = context;
|
|
1833
|
+
this.#rules = rules.map((r) => normalizeChildRule(r));
|
|
1834
|
+
this.#ruleNames = this.#rules.map((r) => r.name);
|
|
1835
|
+
iterate.forEach(this.#rules, (rule) => {
|
|
1287
1836
|
const { name, position, cardinality } = rule;
|
|
1288
1837
|
if ((position === "first" || position === "last") && (cardinality.kind === "unbounded" || cardinality.max > 1)) {
|
|
1289
1838
|
throw new RangeError(
|
|
1290
1839
|
`ChildrenEvaluator [${context}]: rule "${name}" sets position="${position}" with an unbound or >1 max. position="first|last" implies max=1.`
|
|
1291
1840
|
);
|
|
1292
1841
|
}
|
|
1293
|
-
}
|
|
1842
|
+
});
|
|
1294
1843
|
this.#matcher = new RuleMatcher(this.#rules);
|
|
1295
|
-
this.#ruleValidator = new RuleValidator(context,
|
|
1296
|
-
this.#matchBuilder = new MatchValidationErrorBuilder(context);
|
|
1844
|
+
this.#ruleValidator = new RuleValidator(context, diagnostics);
|
|
1297
1845
|
}
|
|
1298
1846
|
evaluate(children) {
|
|
1299
|
-
if (!this.
|
|
1847
|
+
if (!this.active) return;
|
|
1300
1848
|
const { matrix, unexpectedIndices, ambiguousIndices } = this.#matcher.match(children);
|
|
1301
1849
|
this.#ruleValidator.validate(this.#rules, matrix, children.length);
|
|
1302
1850
|
if (unexpectedIndices.size === 0 && ambiguousIndices.size === 0) return;
|
|
1303
|
-
const errors = [];
|
|
1304
1851
|
const violating = [...unexpectedIndices, ...ambiguousIndices].sort((a, b) => a - b);
|
|
1305
|
-
|
|
1852
|
+
iterate.forEach(violating, (ci) => {
|
|
1306
1853
|
const typeName = getTypeName(children[ci]);
|
|
1307
1854
|
if (unexpectedIndices.has(ci)) {
|
|
1308
|
-
|
|
1855
|
+
this.violate(ContractDiagnostics.unexpectedChild(typeName, ci, this.#context));
|
|
1309
1856
|
} else {
|
|
1310
1857
|
const matches = matrix.childToRules.forward.get(ci);
|
|
1311
1858
|
const names = [...matches].map((ri) => this.#ruleNames[ri] ?? `#${ri}`);
|
|
1312
|
-
|
|
1859
|
+
this.violate(ContractDiagnostics.ambiguousChild(typeName, ci, names, this.#context));
|
|
1313
1860
|
}
|
|
1314
|
-
}
|
|
1315
|
-
this.invariant(errors.length === 0, this.#matchBuilder.toError(errors).message);
|
|
1861
|
+
});
|
|
1316
1862
|
}
|
|
1317
1863
|
};
|
|
1864
|
+
|
|
1865
|
+
// ../../lib/contract/src/props/get-disabled-props.ts
|
|
1318
1866
|
var disabledProps = ({
|
|
1319
1867
|
disabled,
|
|
1320
1868
|
"aria-disabled": ariaDisabled,
|
|
@@ -1326,6 +1874,8 @@ var disabledProps = ({
|
|
|
1326
1874
|
...dataDisabled === void 0 && { "data-disabled": "" }
|
|
1327
1875
|
};
|
|
1328
1876
|
};
|
|
1877
|
+
|
|
1878
|
+
// ../../lib/contract/src/props/get-invalid-props.ts
|
|
1329
1879
|
var invalidProps = ({
|
|
1330
1880
|
invalid,
|
|
1331
1881
|
"aria-invalid": ariaInvalid,
|
|
@@ -1337,6 +1887,8 @@ var invalidProps = ({
|
|
|
1337
1887
|
...dataInvalid === void 0 && { "data-invalid": "" }
|
|
1338
1888
|
};
|
|
1339
1889
|
};
|
|
1890
|
+
|
|
1891
|
+
// ../../lib/contract/src/props/get-readonly-props.ts
|
|
1340
1892
|
var readonlyProps = ({
|
|
1341
1893
|
readOnly,
|
|
1342
1894
|
"aria-readonly": ariaReadonly,
|
|
@@ -1352,6 +1904,8 @@ var readonlyProps = ({
|
|
|
1352
1904
|
}
|
|
1353
1905
|
};
|
|
1354
1906
|
};
|
|
1907
|
+
|
|
1908
|
+
// ../core/src/html/aria-rules.ts
|
|
1355
1909
|
var LANDMARK_TAG_SET = /* @__PURE__ */ new Set(["article", "aside", "footer", "header", "main", "nav"]);
|
|
1356
1910
|
var removeLandmarkRoleOverride = {
|
|
1357
1911
|
kind: "removeRole",
|
|
@@ -1371,154 +1925,29 @@ function landmarkRoleRule({ tag, props, implicitRole }) {
|
|
|
1371
1925
|
fixable: true,
|
|
1372
1926
|
severity: "error",
|
|
1373
1927
|
fix: removeLandmarkRoleOverride,
|
|
1374
|
-
|
|
1928
|
+
diagnostic: HtmlDiagnostics.landmarkRoleOverride(tag, implicitRole, role)
|
|
1375
1929
|
}
|
|
1376
1930
|
];
|
|
1377
1931
|
}
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
return { name, match: metadataMatch };
|
|
1387
|
-
}
|
|
1388
|
-
function firstOptional(name, tag) {
|
|
1389
|
-
return { name, match: isTag(tag), cardinality: { max: 1 }, position: "first" };
|
|
1390
|
-
}
|
|
1391
|
-
function contract(children) {
|
|
1392
|
-
return { strict: "warn", children };
|
|
1393
|
-
}
|
|
1394
|
-
function ariaContract(aria) {
|
|
1395
|
-
return { strict: "warn", aria };
|
|
1396
|
-
}
|
|
1397
|
-
function firstChildContract(name, tag) {
|
|
1398
|
-
return contract([firstOptional(name, tag), { name: "content", match: isOpenContent(tag) }]);
|
|
1399
|
-
}
|
|
1400
|
-
var VOID_TAGS = [
|
|
1401
|
-
"area",
|
|
1402
|
-
"base",
|
|
1403
|
-
"br",
|
|
1404
|
-
"col",
|
|
1405
|
-
"embed",
|
|
1406
|
-
"hr",
|
|
1407
|
-
"img",
|
|
1408
|
-
"input",
|
|
1409
|
-
"link",
|
|
1410
|
-
"meta",
|
|
1411
|
-
"param",
|
|
1412
|
-
"source",
|
|
1413
|
-
"track",
|
|
1414
|
-
"wbr"
|
|
1415
|
-
];
|
|
1416
|
-
var TEXT_ONLY_TAGS = ["option", "script", "style", "textarea", "title"];
|
|
1417
|
-
var LANDMARK_TAGS = ["article", "aside", "footer", "header", "main", "nav"];
|
|
1418
|
-
var listContract = contract([{ name: "list-item", match: isTag("li", ...METADATA_TAGS) }]);
|
|
1419
|
-
var tableContract = contract([
|
|
1420
|
-
firstOptional("caption", "caption"),
|
|
1421
|
-
{ name: "colgroup", match: isTag("colgroup") },
|
|
1422
|
-
{ name: "thead", match: isTag("thead"), cardinality: { max: 1 } },
|
|
1423
|
-
{ name: "tbody", match: isTag("tbody") },
|
|
1424
|
-
{ name: "tfoot", match: isTag("tfoot"), cardinality: { max: 1 } },
|
|
1425
|
-
{ name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
|
|
1426
|
-
]);
|
|
1427
|
-
var tableBodyContract = contract([
|
|
1428
|
-
{ name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
|
|
1429
|
-
]);
|
|
1430
|
-
var tableRowContract = contract([
|
|
1431
|
-
{ name: "table-cell", match: isTag("td", "th", ...METADATA_TAGS) }
|
|
1432
|
-
]);
|
|
1433
|
-
var colgroupContract = contract([{ name: "column", match: isTag("col", "template") }]);
|
|
1434
|
-
var dlContract = contract([
|
|
1435
|
-
{ name: "term", match: isTag("dt") },
|
|
1436
|
-
{ name: "description", match: isTag("dd") },
|
|
1437
|
-
{ name: "group", match: isTag("div") },
|
|
1438
|
-
metadata()
|
|
1439
|
-
]);
|
|
1440
|
-
var selectContract = contract([
|
|
1441
|
-
{ name: "option", match: isTag("option", "optgroup", "hr", ...METADATA_TAGS) }
|
|
1442
|
-
]);
|
|
1443
|
-
var optgroupContract = contract([
|
|
1444
|
-
{ name: "option", match: isTag("option", ...METADATA_TAGS) }
|
|
1445
|
-
]);
|
|
1446
|
-
var datalistContract = contract([
|
|
1447
|
-
{ name: "option", match: isTag("option", ...METADATA_TAGS) }
|
|
1448
|
-
]);
|
|
1449
|
-
var pictureContract = contract([
|
|
1450
|
-
{ name: "source", match: isTag("source", ...METADATA_TAGS) },
|
|
1451
|
-
{ name: "image", match: isTag("img"), cardinality: { min: 1, max: 1 }, position: "last" }
|
|
1452
|
-
]);
|
|
1453
|
-
var figureContract = contract([
|
|
1454
|
-
{ name: "caption", match: isTag("figcaption"), cardinality: { max: 1 } },
|
|
1455
|
-
{ name: "content", match: isOpenContent("figcaption") }
|
|
1456
|
-
]);
|
|
1457
|
-
var detailsContract = firstChildContract("summary", "summary");
|
|
1458
|
-
var fieldsetContract = firstChildContract("legend", "legend");
|
|
1459
|
-
var mediaContract = contract([
|
|
1460
|
-
{ name: "source", match: isTag("source") },
|
|
1461
|
-
{ name: "track", match: isTag("track") },
|
|
1462
|
-
metadata(),
|
|
1463
|
-
{ name: "content", match: isOpenContent("source", "track", ...METADATA_TAGS) }
|
|
1464
|
-
]);
|
|
1465
|
-
var headContract = contract([
|
|
1466
|
-
{
|
|
1467
|
-
name: "metadata",
|
|
1468
|
-
match: isTag("base", "link", "meta", "noscript", "script", "style", "template", "title")
|
|
1469
|
-
}
|
|
1470
|
-
]);
|
|
1471
|
-
var htmlContract = contract([
|
|
1472
|
-
{ name: "head", match: isTag("head"), cardinality: { min: 1, max: 1 }, position: "first" },
|
|
1473
|
-
{ name: "body", match: isTag("body"), cardinality: { min: 1, max: 1 } }
|
|
1474
|
-
]);
|
|
1475
|
-
var voidContract = contract([]);
|
|
1476
|
-
var textOnlyContract = contract([
|
|
1477
|
-
{
|
|
1478
|
-
name: "text",
|
|
1479
|
-
match: (child) => isString(child) || isNumber(child)
|
|
1480
|
-
}
|
|
1481
|
-
]);
|
|
1482
|
-
var landmarkContract = ariaContract([landmarkRoleRule]);
|
|
1483
|
-
var CONTRACT_GROUPS = [
|
|
1484
|
-
[VOID_TAGS, voidContract],
|
|
1485
|
-
[TEXT_ONLY_TAGS, textOnlyContract],
|
|
1486
|
-
[LANDMARK_TAGS, landmarkContract],
|
|
1487
|
-
[["ul", "ol", "menu"], listContract],
|
|
1488
|
-
[["audio", "video"], mediaContract],
|
|
1489
|
-
[["thead", "tbody", "tfoot"], tableBodyContract]
|
|
1490
|
-
];
|
|
1491
|
-
function contractMap(groups) {
|
|
1492
|
-
return Object.fromEntries(
|
|
1493
|
-
groups.flatMap(([tags, enforcement]) => tags.map((tag) => [tag, enforcement]))
|
|
1494
|
-
);
|
|
1495
|
-
}
|
|
1496
|
-
var htmlContracts = {
|
|
1497
|
-
...contractMap(CONTRACT_GROUPS),
|
|
1498
|
-
table: tableContract,
|
|
1499
|
-
tr: tableRowContract,
|
|
1500
|
-
colgroup: colgroupContract,
|
|
1501
|
-
dl: dlContract,
|
|
1502
|
-
select: selectContract,
|
|
1503
|
-
optgroup: optgroupContract,
|
|
1504
|
-
datalist: datalistContract,
|
|
1505
|
-
picture: pictureContract,
|
|
1506
|
-
figure: figureContract,
|
|
1507
|
-
details: detailsContract,
|
|
1508
|
-
fieldset: fieldsetContract,
|
|
1509
|
-
head: headContract,
|
|
1510
|
-
html: htmlContract
|
|
1511
|
-
};
|
|
1512
|
-
function buildEvaluatorMap() {
|
|
1513
|
-
const map = /* @__PURE__ */ new Map();
|
|
1514
|
-
for (const [tag, { children }] of Object.entries(htmlContracts)) {
|
|
1515
|
-
if (children?.length) {
|
|
1516
|
-
map.set(tag, new ChildrenEvaluator(children, "warn", `<${tag}>`));
|
|
1932
|
+
function requireAccessibleName({ tag, props }) {
|
|
1933
|
+
if ("aria-label" in props || "aria-labelledby" in props) return [];
|
|
1934
|
+
return [
|
|
1935
|
+
{
|
|
1936
|
+
valid: false,
|
|
1937
|
+
fixable: false,
|
|
1938
|
+
severity: "warning",
|
|
1939
|
+
diagnostic: AriaDiagnostics.missingAccessibleName(tag)
|
|
1517
1940
|
}
|
|
1518
|
-
|
|
1519
|
-
|
|
1941
|
+
];
|
|
1942
|
+
}
|
|
1943
|
+
var NAMED_LANDMARK_TAGS = /* @__PURE__ */ new Set(["nav", "aside"]);
|
|
1944
|
+
function landmarkNameAdvisory(ctx) {
|
|
1945
|
+
if (!ctx.implicitRole || !NAMED_LANDMARK_TAGS.has(ctx.tag)) return [];
|
|
1946
|
+
return requireAccessibleName(ctx);
|
|
1520
1947
|
}
|
|
1521
|
-
var
|
|
1948
|
+
var HTML_ARIA_RULES = [landmarkRoleRule, landmarkNameAdvisory];
|
|
1949
|
+
|
|
1950
|
+
// ../core/src/html/prop-normalizers.ts
|
|
1522
1951
|
var HTML_FORM_NORMALIZERS = /* @__PURE__ */ new Map([
|
|
1523
1952
|
["button", [disabledProps]],
|
|
1524
1953
|
["input", [disabledProps, readonlyProps, invalidProps]],
|
|
@@ -1531,9 +1960,10 @@ function getHtmlPropNormalizers(tag) {
|
|
|
1531
1960
|
return typeof tag === "string" ? HTML_FORM_NORMALIZERS.get(tag) : void 0;
|
|
1532
1961
|
}
|
|
1533
1962
|
|
|
1534
|
-
//
|
|
1963
|
+
// ../../node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.mjs
|
|
1964
|
+
import { clsx as clsx2 } from "clsx";
|
|
1535
1965
|
var falsyToString = (value) => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
|
|
1536
|
-
var cx =
|
|
1966
|
+
var cx = clsx2;
|
|
1537
1967
|
var cva = (base, config) => (props) => {
|
|
1538
1968
|
var _config_compoundVariants;
|
|
1539
1969
|
if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
|
|
@@ -1572,10 +2002,14 @@ var cva = (base, config) => (props) => {
|
|
|
1572
2002
|
}, []);
|
|
1573
2003
|
return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
|
|
1574
2004
|
};
|
|
2005
|
+
|
|
2006
|
+
// ../../lib/styling/src/cva.ts
|
|
1575
2007
|
function cva2(base, config) {
|
|
1576
2008
|
const fn = cva(base, config);
|
|
1577
2009
|
return (props) => cn(fn(props));
|
|
1578
2010
|
}
|
|
2011
|
+
|
|
2012
|
+
// ../../lib/styling/src/static-class-resolver.ts
|
|
1579
2013
|
var StaticClassResolver = class {
|
|
1580
2014
|
#baseClass;
|
|
1581
2015
|
#cache = /* @__PURE__ */ new Map();
|
|
@@ -1606,6 +2040,8 @@ var StaticClassResolver = class {
|
|
|
1606
2040
|
return result;
|
|
1607
2041
|
}
|
|
1608
2042
|
};
|
|
2043
|
+
|
|
2044
|
+
// ../../lib/styling/src/variant-class-resolver.ts
|
|
1609
2045
|
var VariantClassResolver = class _VariantClassResolver {
|
|
1610
2046
|
#cvaFn;
|
|
1611
2047
|
#recipeMap;
|
|
@@ -1653,15 +2089,15 @@ var VariantClassResolver = class _VariantClassResolver {
|
|
|
1653
2089
|
#createCacheKey(props, recipe) {
|
|
1654
2090
|
if (this.#variantKeys !== null) {
|
|
1655
2091
|
let key2 = recipe;
|
|
1656
|
-
|
|
2092
|
+
iterate.forEachSet(this.#variantKeys, (k) => {
|
|
1657
2093
|
if (k in props) key2 += `|${k}:${_VariantClassResolver.#serializeValue(props[k])}`;
|
|
1658
|
-
}
|
|
2094
|
+
});
|
|
1659
2095
|
return key2;
|
|
1660
2096
|
}
|
|
1661
2097
|
let key = recipe;
|
|
1662
|
-
|
|
2098
|
+
iterate.forEach(Object.keys(props).sort(), (k) => {
|
|
1663
2099
|
key += `|${k}:${_VariantClassResolver.#serializeValue(props[k])}`;
|
|
1664
|
-
}
|
|
2100
|
+
});
|
|
1665
2101
|
return key;
|
|
1666
2102
|
}
|
|
1667
2103
|
static #serializeValue(value) {
|
|
@@ -1672,6 +2108,8 @@ var VariantClassResolver = class _VariantClassResolver {
|
|
|
1672
2108
|
return `x:${String(value)}`;
|
|
1673
2109
|
}
|
|
1674
2110
|
};
|
|
2111
|
+
|
|
2112
|
+
// ../../lib/styling/src/create-class-pipeline.ts
|
|
1675
2113
|
function createClassPipeline(resolved) {
|
|
1676
2114
|
const baseClass = resolved.baseClassName ?? "";
|
|
1677
2115
|
const cvaFn = resolved.variants ? cva2("", {
|
|
@@ -1696,7 +2134,203 @@ function createClassPipeline(resolved) {
|
|
|
1696
2134
|
};
|
|
1697
2135
|
}
|
|
1698
2136
|
|
|
1699
|
-
// ../core/
|
|
2137
|
+
// ../core/src/options/resolve-factory-options.ts
|
|
2138
|
+
var EMPTY_VARIANT_KEYS = /* @__PURE__ */ new Set();
|
|
2139
|
+
function composeNormalizers(normalizers, fn) {
|
|
2140
|
+
if (!normalizers?.length) return fn;
|
|
2141
|
+
return ((props) => {
|
|
2142
|
+
const patched = normalizers.reduce(
|
|
2143
|
+
(acc, normalizer) => ({ ...acc, ...normalizer(acc) }),
|
|
2144
|
+
props
|
|
2145
|
+
);
|
|
2146
|
+
return fn ? fn(patched) : patched;
|
|
2147
|
+
});
|
|
2148
|
+
}
|
|
2149
|
+
function whenDefined(key, value) {
|
|
2150
|
+
return value === void 0 ? {} : { [key]: value };
|
|
2151
|
+
}
|
|
2152
|
+
function resolveFactoryOptions(options = {}) {
|
|
2153
|
+
const { styling, enforcement } = options;
|
|
2154
|
+
const composedNormalizeFn = composeNormalizers(enforcement?.props, options.normalize);
|
|
2155
|
+
const variantKeys = styling?.variants === void 0 ? EMPTY_VARIANT_KEYS : new Set(Object.keys(styling.variants));
|
|
2156
|
+
return Object.freeze({
|
|
2157
|
+
defaultTag: options.tag ?? "div",
|
|
2158
|
+
diagnostics: enforcement?.diagnostics ?? silentDiagnostics,
|
|
2159
|
+
variantKeys,
|
|
2160
|
+
...whenDefined("displayName", options.name),
|
|
2161
|
+
...whenDefined("defaultProps", options.defaults),
|
|
2162
|
+
...whenDefined("baseClassName", styling?.base),
|
|
2163
|
+
...whenDefined("tagMap", styling?.tags),
|
|
2164
|
+
...whenDefined("recipeMap", styling?.presets),
|
|
2165
|
+
...whenDefined("variants", styling?.variants),
|
|
2166
|
+
...whenDefined("defaultVariants", styling?.defaults),
|
|
2167
|
+
...whenDefined("compoundVariants", styling?.compounds),
|
|
2168
|
+
...whenDefined("normalizeFn", composedNormalizeFn),
|
|
2169
|
+
...whenDefined("ariaRules", enforcement?.aria),
|
|
2170
|
+
...whenDefined("childRules", enforcement?.children),
|
|
2171
|
+
...whenDefined("allowedAs", enforcement?.allowedAs),
|
|
2172
|
+
...whenDefined("precomputedClasses", styling?.precomputedClasses)
|
|
2173
|
+
});
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
// ../core/src/options/validate-factory-options.ts
|
|
2177
|
+
function validateFactoryOptions(resolved, diagnostics) {
|
|
2178
|
+
if (!diagnostics.active) return;
|
|
2179
|
+
const name = resolved.displayName ?? "Component";
|
|
2180
|
+
const { variants } = resolved;
|
|
2181
|
+
const checkSelection = (label2, selection) => {
|
|
2182
|
+
iterate.forEachEntry(selection, (dim, value) => {
|
|
2183
|
+
if (value === void 0 || value === null) return;
|
|
2184
|
+
if (!variants || !Object.hasOwn(variants, dim)) {
|
|
2185
|
+
diagnostics.error(ContractDiagnostics.unknownVariantDim(name, label2, dim));
|
|
2186
|
+
return;
|
|
2187
|
+
}
|
|
2188
|
+
const states = variants[dim];
|
|
2189
|
+
const stateKey = String(value);
|
|
2190
|
+
if (!Object.hasOwn(states, stateKey)) {
|
|
2191
|
+
diagnostics.error(
|
|
2192
|
+
ContractDiagnostics.unknownVariantValue(name, label2, dim, stateKey, Object.keys(states))
|
|
2193
|
+
);
|
|
2194
|
+
}
|
|
2195
|
+
});
|
|
2196
|
+
};
|
|
2197
|
+
const { recipeMap } = resolved;
|
|
2198
|
+
if (recipeMap) {
|
|
2199
|
+
iterate.forEachEntry(recipeMap, (recipeKey, selection) => {
|
|
2200
|
+
checkSelection(`preset "${recipeKey}"`, selection);
|
|
2201
|
+
});
|
|
2202
|
+
}
|
|
2203
|
+
if (resolved.defaultVariants) checkSelection("defaults", resolved.defaultVariants);
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
// ../core/src/options/validate-render-props.ts
|
|
2207
|
+
function label(name) {
|
|
2208
|
+
return name ? `[${name}]` : "[createContractComponent]";
|
|
2209
|
+
}
|
|
2210
|
+
function validateRenderProps(diagnostics, options, props, recipeKey) {
|
|
2211
|
+
const { recipeMap, variants, displayName } = options;
|
|
2212
|
+
const tag = label(displayName);
|
|
2213
|
+
if (recipeKey !== void 0 && (!recipeMap || !Object.hasOwn(recipeMap, recipeKey))) {
|
|
2214
|
+
diagnostics.error(ContractDiagnostics.unknownRecipeKey(tag, recipeKey));
|
|
2215
|
+
}
|
|
2216
|
+
if (variants) {
|
|
2217
|
+
iterate.forEachKey(variants, (key) => {
|
|
2218
|
+
if (!Object.hasOwn(props, key)) return;
|
|
2219
|
+
const value = props[key];
|
|
2220
|
+
if (value === void 0 || value === null) return;
|
|
2221
|
+
const dim = variants[key];
|
|
2222
|
+
if (dim && !Object.hasOwn(dim, String(value))) {
|
|
2223
|
+
diagnostics.error(ContractDiagnostics.invalidVariantValue(tag, key, String(value)));
|
|
2224
|
+
}
|
|
2225
|
+
});
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
// ../core/src/factory/plugin-diagnostics.ts
|
|
2230
|
+
var PluginDiagnostics = {
|
|
2231
|
+
invalidShape(received) {
|
|
2232
|
+
const got = received === null ? "null" : typeof received;
|
|
2233
|
+
return {
|
|
2234
|
+
code: "PLUGIN7001" /* PluginInvalidShape */,
|
|
2235
|
+
category: 7 /* Internal */,
|
|
2236
|
+
message: `[praxis-kit] Plugin factory must return an object with a 'pipeline' function. Got: ${got}.`
|
|
2237
|
+
};
|
|
2238
|
+
},
|
|
2239
|
+
pipelineReturnType(received) {
|
|
2240
|
+
const got = received === null ? "null" : Array.isArray(received) ? "array" : typeof received;
|
|
2241
|
+
return {
|
|
2242
|
+
code: "PLUGIN7002" /* PluginPipelineReturnType */,
|
|
2243
|
+
category: 7 /* Internal */,
|
|
2244
|
+
message: `[praxis-kit] Plugin pipeline must return a string. Got: ${got}.`
|
|
2245
|
+
};
|
|
2246
|
+
}
|
|
2247
|
+
};
|
|
2248
|
+
|
|
2249
|
+
// ../core/src/factory/plugin-invariants.ts
|
|
2250
|
+
function assertPluginShape(result) {
|
|
2251
|
+
if (result === null || typeof result !== "object")
|
|
2252
|
+
throwDiagnostics.error(PluginDiagnostics.invalidShape(result));
|
|
2253
|
+
const plugin = result;
|
|
2254
|
+
if (typeof plugin.pipeline !== "function")
|
|
2255
|
+
throwDiagnostics.error(PluginDiagnostics.invalidShape(result));
|
|
2256
|
+
}
|
|
2257
|
+
function guardPipeline(pipeline) {
|
|
2258
|
+
if (process.env.NODE_ENV === "production") return pipeline;
|
|
2259
|
+
return function guardedPipeline(tag, props, className, recipe) {
|
|
2260
|
+
const result = pipeline(tag, props, className, recipe);
|
|
2261
|
+
if (typeof result !== "string")
|
|
2262
|
+
throwDiagnostics.error(PluginDiagnostics.pipelineReturnType(result));
|
|
2263
|
+
return result;
|
|
2264
|
+
};
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
// ../core/src/factory/create-polymorphic.ts
|
|
2268
|
+
var NOOP_CLASS_PIPELINE = (_tag, _props, className) => Array.isArray(className) ? className.join(" ") : className ?? "";
|
|
2269
|
+
function resolveClassPipeline(options, resolved, diagnostics, capabilities) {
|
|
2270
|
+
const factory = options.styling?.plugin;
|
|
2271
|
+
if (!factory) {
|
|
2272
|
+
const createClassPipeline2 = capabilities?.createClassPipeline;
|
|
2273
|
+
const classPipeline2 = createClassPipeline2 ? createClassPipeline2(resolved) : NOOP_CLASS_PIPELINE;
|
|
2274
|
+
return { pluginResult: void 0, classPipeline: classPipeline2 };
|
|
2275
|
+
}
|
|
2276
|
+
const pluginResult = factory(resolved, diagnostics);
|
|
2277
|
+
assertPluginShape(pluginResult);
|
|
2278
|
+
const classPipeline = guardPipeline(pluginResult.pipeline);
|
|
2279
|
+
return { pluginResult, classPipeline };
|
|
2280
|
+
}
|
|
2281
|
+
function createRuntimeMethods(resolved, classPipeline, engine, renderDiagnostics) {
|
|
2282
|
+
return {
|
|
2283
|
+
resolveTag: makeResolveTag(resolved.defaultTag),
|
|
2284
|
+
resolveProps(props) {
|
|
2285
|
+
return mergeProps(resolved.defaultProps, props);
|
|
2286
|
+
},
|
|
2287
|
+
resolveClasses(tag, props, className, recipe) {
|
|
2288
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2289
|
+
validateRenderProps(renderDiagnostics, resolved, props, recipe);
|
|
2290
|
+
}
|
|
2291
|
+
return classPipeline(tag, props, className, recipe);
|
|
2292
|
+
},
|
|
2293
|
+
resolveAria(tag, props) {
|
|
2294
|
+
if (!engine) return { props };
|
|
2295
|
+
const result = engine.validate(tag, props);
|
|
2296
|
+
return { props: result.props };
|
|
2297
|
+
}
|
|
2298
|
+
};
|
|
2299
|
+
}
|
|
2300
|
+
function createRuntimeObject(methods, resolved, pluginResult) {
|
|
2301
|
+
return pluginResult ? { ...methods, options: resolved, hasStyling: true, classPlugin: pluginResult } : { ...methods, options: resolved };
|
|
2302
|
+
}
|
|
2303
|
+
function createPolymorphic(options = {}, capabilities) {
|
|
2304
|
+
const baseResolved = resolveFactoryOptions(options);
|
|
2305
|
+
const resolved = capabilities?.htmlPropNormalizersFn !== void 0 ? Object.freeze({
|
|
2306
|
+
...baseResolved,
|
|
2307
|
+
htmlPropNormalizersFn: capabilities.htmlPropNormalizersFn
|
|
2308
|
+
}) : baseResolved;
|
|
2309
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2310
|
+
validateFactoryOptions(resolved, resolved.diagnostics);
|
|
2311
|
+
}
|
|
2312
|
+
const { pluginResult, classPipeline } = resolveClassPipeline(
|
|
2313
|
+
options,
|
|
2314
|
+
resolved,
|
|
2315
|
+
resolved.diagnostics,
|
|
2316
|
+
capabilities
|
|
2317
|
+
);
|
|
2318
|
+
const allAriaRules = [
|
|
2319
|
+
.../* @__PURE__ */ new Set([...capabilities?.htmlAriaRules ?? [], ...resolved.ariaRules ?? []])
|
|
2320
|
+
];
|
|
2321
|
+
const engine = options.enforcement !== void 0 && capabilities?.AriaEngine ? new capabilities.AriaEngine(
|
|
2322
|
+
resolved.diagnostics,
|
|
2323
|
+
allAriaRules.length ? { rules: allAriaRules } : void 0
|
|
2324
|
+
) : null;
|
|
2325
|
+
const methods = createRuntimeMethods(resolved, classPipeline, engine, resolved.diagnostics);
|
|
2326
|
+
return createRuntimeObject(
|
|
2327
|
+
methods,
|
|
2328
|
+
resolved,
|
|
2329
|
+
pluginResult
|
|
2330
|
+
);
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
// ../core/src/factory/create-polymorphic-full.ts
|
|
1700
2334
|
var FULL_CAPABILITIES = {
|
|
1701
2335
|
createClassPipeline,
|
|
1702
2336
|
AriaEngine: AriaPolicyEngine,
|
|
@@ -1707,6 +2341,11 @@ function createPolymorphic2(options = {}) {
|
|
|
1707
2341
|
return createPolymorphic(options, FULL_CAPABILITIES);
|
|
1708
2342
|
}
|
|
1709
2343
|
|
|
2344
|
+
// ../../lib/adapter-utils/src/define-component.ts
|
|
2345
|
+
function defineContractComponent(options) {
|
|
2346
|
+
return (factory) => factory(options);
|
|
2347
|
+
}
|
|
2348
|
+
|
|
1710
2349
|
// ../../lib/adapter-utils/src/build-core-runtime.ts
|
|
1711
2350
|
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
1712
2351
|
function buildCoreRuntime(normalized) {
|
|
@@ -1716,8 +2355,8 @@ function buildCoreRuntime(normalized) {
|
|
|
1716
2355
|
}
|
|
1717
2356
|
|
|
1718
2357
|
// ../../lib/adapter-utils/src/build-engines.ts
|
|
1719
|
-
function buildEngines(
|
|
1720
|
-
return childRules?.length ? { childrenEvaluator: new ChildrenEvaluator(childRules,
|
|
2358
|
+
function buildEngines(diagnostics, childRules, context) {
|
|
2359
|
+
return childRules?.length ? { childrenEvaluator: new ChildrenEvaluator(childRules, diagnostics, context) } : {};
|
|
1721
2360
|
}
|
|
1722
2361
|
|
|
1723
2362
|
// ../../lib/adapter-utils/src/compose-filter.ts
|
|
@@ -1730,10 +2369,10 @@ function composeFilter(ownedKeys, filterProps) {
|
|
|
1730
2369
|
}
|
|
1731
2370
|
|
|
1732
2371
|
// ../../lib/adapter-utils/src/resolve-adapter-common-options.ts
|
|
1733
|
-
function resolveAdapterCommonOptions(options, defaultName = "PolymorphicComponent",
|
|
2372
|
+
function resolveAdapterCommonOptions(options, defaultName = "PolymorphicComponent", defaultDiagnostics = throwDiagnostics) {
|
|
1734
2373
|
return {
|
|
1735
2374
|
name: options.name ?? defaultName,
|
|
1736
|
-
|
|
2375
|
+
diagnostics: options.enforcement?.diagnostics ?? defaultDiagnostics
|
|
1737
2376
|
};
|
|
1738
2377
|
}
|
|
1739
2378
|
|
|
@@ -1741,7 +2380,7 @@ function resolveAdapterCommonOptions(options, defaultName = "PolymorphicComponen
|
|
|
1741
2380
|
function normalizeOptions(options) {
|
|
1742
2381
|
return {
|
|
1743
2382
|
...options,
|
|
1744
|
-
...resolveAdapterCommonOptions(options, "PolymorphicElement",
|
|
2383
|
+
...resolveAdapterCommonOptions(options, "PolymorphicElement", silentDiagnostics)
|
|
1745
2384
|
};
|
|
1746
2385
|
}
|
|
1747
2386
|
function buildRuntime(options) {
|
|
@@ -1749,7 +2388,7 @@ function buildRuntime(options) {
|
|
|
1749
2388
|
const normalized = normalizeOptions(options);
|
|
1750
2389
|
const { runtime, ownedKeys } = buildCoreRuntime(normalized);
|
|
1751
2390
|
const { childrenEvaluator } = buildEngines(
|
|
1752
|
-
normalized.
|
|
2391
|
+
normalized.diagnostics,
|
|
1753
2392
|
enforcement?.children,
|
|
1754
2393
|
normalized.name
|
|
1755
2394
|
);
|
|
@@ -1771,16 +2410,14 @@ function escapeAttr(value) {
|
|
|
1771
2410
|
}
|
|
1772
2411
|
function buildAttrString(attributes) {
|
|
1773
2412
|
const parts = [];
|
|
1774
|
-
|
|
1775
|
-
if (
|
|
1776
|
-
const value = attributes[key];
|
|
1777
|
-
if (value === false || value === null || value === void 0) continue;
|
|
2413
|
+
iterate.forEachEntry(attributes, (key, value) => {
|
|
2414
|
+
if (value === false || value === null || value === void 0) return;
|
|
1778
2415
|
if (value === true) {
|
|
1779
2416
|
parts.push(key);
|
|
1780
2417
|
} else {
|
|
1781
2418
|
parts.push(`${key}="${escapeAttr(String(value))}"`);
|
|
1782
2419
|
}
|
|
1783
|
-
}
|
|
2420
|
+
});
|
|
1784
2421
|
return parts.length > 0 ? " " + parts.join(" ") : "";
|
|
1785
2422
|
}
|
|
1786
2423
|
function renderToString(component, props = {}, innerHTML = "") {
|
|
@@ -1858,19 +2495,19 @@ function resolveHostState(bundle, props) {
|
|
|
1858
2495
|
}
|
|
1859
2496
|
function applyHostState(host, state, prevPipelineAttrs, incomingProps) {
|
|
1860
2497
|
host.className = state.className;
|
|
1861
|
-
|
|
2498
|
+
iterate.forEachSet(prevPipelineAttrs, (key) => {
|
|
1862
2499
|
if (!Object.hasOwn(state.attributes, key)) {
|
|
1863
2500
|
host.removeAttribute(key);
|
|
1864
2501
|
}
|
|
1865
|
-
}
|
|
2502
|
+
});
|
|
1866
2503
|
prevPipelineAttrs.clear();
|
|
1867
|
-
|
|
1868
|
-
if (!Object.hasOwn(incomingProps, key))
|
|
1869
|
-
if (!key.startsWith("aria-") && key !== "role")
|
|
2504
|
+
iterate.forEachKey(incomingProps, (key) => {
|
|
2505
|
+
if (!Object.hasOwn(incomingProps, key)) return;
|
|
2506
|
+
if (!key.startsWith("aria-") && key !== "role") return;
|
|
1870
2507
|
if (!Object.hasOwn(state.attributes, key)) host.removeAttribute(key);
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
|
-
if (!Object.hasOwn(state.attributes, key))
|
|
2508
|
+
});
|
|
2509
|
+
iterate.forEachKey(state.attributes, (key) => {
|
|
2510
|
+
if (!Object.hasOwn(state.attributes, key)) return;
|
|
1874
2511
|
const value = state.attributes[key];
|
|
1875
2512
|
if (value === void 0 || value === null || value === false) {
|
|
1876
2513
|
host.removeAttribute(key);
|
|
@@ -1881,7 +2518,7 @@ function applyHostState(host, state, prevPipelineAttrs, incomingProps) {
|
|
|
1881
2518
|
host.setAttribute(key, String(value));
|
|
1882
2519
|
prevPipelineAttrs.add(key);
|
|
1883
2520
|
}
|
|
1884
|
-
}
|
|
2521
|
+
});
|
|
1885
2522
|
}
|
|
1886
2523
|
function createContractComponent(options) {
|
|
1887
2524
|
const bundle = buildRuntime(options);
|
|
@@ -1902,12 +2539,12 @@ function createContractComponent(options) {
|
|
|
1902
2539
|
// attribute so _applyPraxis can read it without a circular class→pipeline→class loop.
|
|
1903
2540
|
praxisClass: { type: String, attribute: "praxis-class" }
|
|
1904
2541
|
};
|
|
1905
|
-
|
|
2542
|
+
iterate.forEach(variantKeys, (key) => {
|
|
1906
2543
|
staticProps[key] = { type: String, attribute: key };
|
|
1907
|
-
}
|
|
1908
|
-
|
|
2544
|
+
});
|
|
2545
|
+
iterate.forEach(pluginKeys, (key) => {
|
|
1909
2546
|
staticProps[key] = { type: String, attribute: key };
|
|
1910
|
-
}
|
|
2547
|
+
});
|
|
1911
2548
|
class PolymorphicLitElement extends LitElement {
|
|
1912
2549
|
// Tracks keys set by the pipeline last render so stale attrs are removed.
|
|
1913
2550
|
_pipelineAttrs = /* @__PURE__ */ new Set();
|
|
@@ -1949,16 +2586,16 @@ function createContractComponent(options) {
|
|
|
1949
2586
|
_applyPraxis() {
|
|
1950
2587
|
const self = this._self;
|
|
1951
2588
|
const props = {};
|
|
1952
|
-
|
|
2589
|
+
iterate.forEach(iterate.items(this.attributes), (attr) => {
|
|
1953
2590
|
if (attr.name !== "class") props[attr.name] = attr.value;
|
|
1954
|
-
}
|
|
2591
|
+
});
|
|
1955
2592
|
props["as"] = self.as;
|
|
1956
2593
|
props["recipe"] = self.recipe;
|
|
1957
2594
|
props["className"] = self.praxisClass;
|
|
1958
|
-
|
|
2595
|
+
iterate.forEach(variantKeys, (key) => {
|
|
1959
2596
|
const val = self[key];
|
|
1960
2597
|
if (val != null) props[key] = val;
|
|
1961
|
-
}
|
|
2598
|
+
});
|
|
1962
2599
|
applyHostState(this, resolveHostState(looseBundle, props), this._pipelineAttrs, props);
|
|
1963
2600
|
}
|
|
1964
2601
|
render() {
|