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/vue/index.js
CHANGED
|
@@ -1,375 +1,212 @@
|
|
|
1
1
|
// ../../adapters/vue/src/create-contract-component.ts
|
|
2
|
-
import { computed, defineComponent as defineComponent2 } from "vue";
|
|
2
|
+
import { cloneVNode, computed, defineComponent as defineComponent2 } from "vue";
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
|
|
4
|
+
// ../../lib/adapter-utils/src/invariant.ts
|
|
5
|
+
function panic(message) {
|
|
6
|
+
throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
function invariant(condition, message) {
|
|
9
|
+
if (!condition) panic(message);
|
|
10
|
+
}
|
|
6
11
|
|
|
7
|
-
// ../../
|
|
12
|
+
// ../../lib/adapter-utils/src/apply-display-name.ts
|
|
8
13
|
function applyDisplayName(component, name) {
|
|
9
14
|
Object.assign(component, { displayName: name ?? "PolymorphicComponent" });
|
|
10
15
|
}
|
|
11
16
|
|
|
12
|
-
// ../../lib/
|
|
13
|
-
function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (!Object.hasOwn(props, k)) continue;
|
|
17
|
-
if (filterProps(k, variantKeys)) continue;
|
|
18
|
-
out[k] = props[k];
|
|
19
|
-
}
|
|
20
|
-
return out;
|
|
17
|
+
// ../../lib/primitive/src/utils/is-object.ts
|
|
18
|
+
function isObject(value, excludeArrays = false) {
|
|
19
|
+
if (value === null || typeof value !== "object") return false;
|
|
20
|
+
return excludeArrays ? !Array.isArray(value) : true;
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
function isString(value) {
|
|
23
|
+
return typeof value === "string";
|
|
24
|
+
}
|
|
25
|
+
function isNumber(value) {
|
|
26
|
+
return typeof value === "number";
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
//
|
|
29
|
-
function
|
|
30
|
-
return
|
|
31
|
-
return as ?? defaultTag;
|
|
32
|
-
};
|
|
29
|
+
// ../../lib/primitive/src/merge/predicates.ts
|
|
30
|
+
function isFunction(value) {
|
|
31
|
+
return typeof value === "function";
|
|
33
32
|
}
|
|
33
|
+
|
|
34
|
+
// ../../lib/primitive/src/utils/assert-never.ts
|
|
34
35
|
function assertNever(value) {
|
|
35
36
|
throw new Error(`Unexpected value: ${String(value)}`);
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
48
|
-
return n;
|
|
49
|
-
}
|
|
50
|
-
function cn(...inputs) {
|
|
51
|
-
return clsx(...inputs);
|
|
52
|
-
}
|
|
53
|
-
function mergeProps(defaultProps, props) {
|
|
54
|
-
return {
|
|
55
|
-
...defaultProps ?? {},
|
|
56
|
-
...props
|
|
57
|
-
};
|
|
38
|
+
|
|
39
|
+
// ../../lib/primitive/src/utils/iterate.ts
|
|
40
|
+
function find(iterable, callback) {
|
|
41
|
+
for (const value of iterable) {
|
|
42
|
+
const result = callback(value);
|
|
43
|
+
if (result != null) {
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
58
48
|
}
|
|
59
|
-
function
|
|
60
|
-
|
|
49
|
+
function some(iterable, predicate) {
|
|
50
|
+
for (const value of iterable) {
|
|
51
|
+
if (predicate(value)) return true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
61
54
|
}
|
|
62
|
-
function
|
|
63
|
-
|
|
55
|
+
function every(iterable, predicate) {
|
|
56
|
+
let index = 0;
|
|
57
|
+
for (const value of iterable) {
|
|
58
|
+
if (!predicate(value, index++)) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
64
63
|
}
|
|
65
|
-
function
|
|
66
|
-
|
|
64
|
+
function* filter(iterable, predicate) {
|
|
65
|
+
let index = 0;
|
|
66
|
+
for (const value of iterable) {
|
|
67
|
+
if (predicate(value, index++)) {
|
|
68
|
+
yield value;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
67
71
|
}
|
|
68
|
-
function
|
|
69
|
-
|
|
72
|
+
function* map(iterable, callback) {
|
|
73
|
+
let index = 0;
|
|
74
|
+
for (const value of iterable) {
|
|
75
|
+
yield callback(value, index++);
|
|
76
|
+
}
|
|
70
77
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
(acc, normalizer) => ({ ...acc, ...normalizer(acc) }),
|
|
77
|
-
props
|
|
78
|
-
);
|
|
79
|
-
return fn ? fn(patched) : patched;
|
|
80
|
-
});
|
|
78
|
+
function forEach(iterable, callback) {
|
|
79
|
+
let index = 0;
|
|
80
|
+
for (const value of iterable) {
|
|
81
|
+
callback(value, index++);
|
|
82
|
+
}
|
|
81
83
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return Object.freeze({
|
|
90
|
-
defaultTag: options.tag ?? "div",
|
|
91
|
-
strict: enforcement?.strict ?? false,
|
|
92
|
-
variantKeys,
|
|
93
|
-
...whenDefined("displayName", options.name),
|
|
94
|
-
...whenDefined("defaultProps", options.defaults),
|
|
95
|
-
...whenDefined("baseClassName", styling?.base),
|
|
96
|
-
...whenDefined("tagMap", styling?.tags),
|
|
97
|
-
...whenDefined("recipeMap", styling?.presets),
|
|
98
|
-
...whenDefined("variants", styling?.variants),
|
|
99
|
-
...whenDefined("defaultVariants", styling?.defaults),
|
|
100
|
-
...whenDefined("compoundVariants", styling?.compounds),
|
|
101
|
-
...whenDefined("normalizeFn", composedNormalizeFn),
|
|
102
|
-
...whenDefined("ariaRules", enforcement?.aria),
|
|
103
|
-
...whenDefined("childRules", enforcement?.children),
|
|
104
|
-
...whenDefined("allowedAs", enforcement?.allowedAs),
|
|
105
|
-
...whenDefined("precomputedClasses", styling?.precomputedClasses)
|
|
106
|
-
});
|
|
84
|
+
function reduce(iterable, initial, callback) {
|
|
85
|
+
let accumulator = initial;
|
|
86
|
+
let index = 0;
|
|
87
|
+
for (const value of iterable) {
|
|
88
|
+
accumulator = callback(accumulator, value, index++);
|
|
89
|
+
}
|
|
90
|
+
return accumulator;
|
|
107
91
|
}
|
|
108
|
-
function
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const { strict } = resolved;
|
|
116
|
-
if (strict === false) return;
|
|
117
|
-
const name = resolved.displayName ?? "Component";
|
|
118
|
-
const { variants } = resolved;
|
|
119
|
-
const checkSelection = (label2, selection) => {
|
|
120
|
-
const record = selection;
|
|
121
|
-
for (const dim in record) {
|
|
122
|
-
const value = record[dim];
|
|
123
|
-
if (value === void 0 || value === null) continue;
|
|
124
|
-
if (!variants || !Object.hasOwn(variants, dim)) {
|
|
125
|
-
report(strict, `${name}: ${label2} references unknown variant "${dim}".`);
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
const states = variants[dim];
|
|
129
|
-
const stateKey = String(value);
|
|
130
|
-
if (!Object.hasOwn(states, stateKey)) {
|
|
131
|
-
report(
|
|
132
|
-
strict,
|
|
133
|
-
`${name}: ${label2} sets "${dim}" to unknown value "${stateKey}" (valid: ${Object.keys(states).join(", ")}).`
|
|
134
|
-
);
|
|
135
|
-
}
|
|
92
|
+
function collect(iterable, callback) {
|
|
93
|
+
const result = {};
|
|
94
|
+
let index = 0;
|
|
95
|
+
for (const value of iterable) {
|
|
96
|
+
const entry = callback(value, index++);
|
|
97
|
+
if (entry === null) {
|
|
98
|
+
return null;
|
|
136
99
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
100
|
+
result[entry[0]] = entry[1];
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
function findLast(value, callback) {
|
|
105
|
+
for (let index = value.length - 1; index >= 0; index--) {
|
|
106
|
+
const result = callback(value[index], index);
|
|
107
|
+
if (result != null) {
|
|
108
|
+
return result;
|
|
142
109
|
}
|
|
143
110
|
}
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const messages = [...pendingAsyncWarns];
|
|
152
|
-
pendingAsyncWarns.clear();
|
|
153
|
-
for (const msg of messages) {
|
|
154
|
-
console.warn(msg);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
function report2(strict, message) {
|
|
158
|
-
if (!strict) return;
|
|
159
|
-
const mode = strict === true ? "throw" : strict;
|
|
160
|
-
if (mode === "throw") throw new Error(message);
|
|
161
|
-
if (mode === "async-warn") {
|
|
162
|
-
if (pendingAsyncWarns.has(message)) return;
|
|
163
|
-
pendingAsyncWarns.add(message);
|
|
164
|
-
if (!asyncWarnScheduled) {
|
|
165
|
-
asyncWarnScheduled = true;
|
|
166
|
-
queueMicrotask(flushAsyncWarns);
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
function* items(collection) {
|
|
114
|
+
for (let i = 0; i < collection.length; i++) {
|
|
115
|
+
const item = collection.item(i);
|
|
116
|
+
if (item !== null) {
|
|
117
|
+
yield item;
|
|
167
118
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const { strict, recipeMap, variants, displayName } = options;
|
|
179
|
-
if (!strict) return;
|
|
180
|
-
const tag = label(displayName);
|
|
181
|
-
if (recipeKey !== void 0 && (!recipeMap || !Object.hasOwn(recipeMap, recipeKey))) {
|
|
182
|
-
report2(strict, `${tag} Unknown recipeKey "${recipeKey}" \u2014 no preset with that name exists.`);
|
|
183
|
-
}
|
|
184
|
-
if (variants) {
|
|
185
|
-
for (const key in variants) {
|
|
186
|
-
if (!Object.hasOwn(props, key)) continue;
|
|
187
|
-
const value = props[key];
|
|
188
|
-
if (value === void 0 || value === null) continue;
|
|
189
|
-
const dim = variants[key];
|
|
190
|
-
if (dim && !Object.hasOwn(dim, String(value))) {
|
|
191
|
-
report2(
|
|
192
|
-
strict,
|
|
193
|
-
`${tag} Variant "${key}=${String(value)}" is not a defined value for the "${key}" dimension.`
|
|
194
|
-
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function nodeList(list) {
|
|
122
|
+
return {
|
|
123
|
+
*[Symbol.iterator]() {
|
|
124
|
+
for (let i = 0; i < list.length; i++) {
|
|
125
|
+
const node = list.item(i);
|
|
126
|
+
if (node !== null) {
|
|
127
|
+
yield node;
|
|
128
|
+
}
|
|
195
129
|
}
|
|
196
130
|
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function mapEntries(m) {
|
|
134
|
+
return m.entries();
|
|
135
|
+
}
|
|
136
|
+
function set(s) {
|
|
137
|
+
return s.values();
|
|
138
|
+
}
|
|
139
|
+
function hasOwn(object, key) {
|
|
140
|
+
return Object.hasOwn(object, key);
|
|
141
|
+
}
|
|
142
|
+
function* entries(object) {
|
|
143
|
+
for (const key in object) {
|
|
144
|
+
if (!hasOwn(object, key)) continue;
|
|
145
|
+
yield [key, object[key]];
|
|
197
146
|
}
|
|
198
147
|
}
|
|
199
|
-
function
|
|
200
|
-
|
|
148
|
+
function* keys(object) {
|
|
149
|
+
for (const [key] of entries(object)) {
|
|
150
|
+
yield key;
|
|
151
|
+
}
|
|
201
152
|
}
|
|
202
|
-
function
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
153
|
+
function* values(object) {
|
|
154
|
+
for (const [, value] of entries(object)) {
|
|
155
|
+
yield value;
|
|
156
|
+
}
|
|
206
157
|
}
|
|
207
|
-
function
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (typeof plugin.pipeline !== "function")
|
|
214
|
-
panic(
|
|
215
|
-
`[praxis-kit] Plugin factory return value is missing a 'pipeline' function. Got pipeline: ${typeof plugin.pipeline}.`
|
|
216
|
-
);
|
|
158
|
+
function mapValues(object, callback) {
|
|
159
|
+
const result = {};
|
|
160
|
+
for (const [key, value] of entries(object)) {
|
|
161
|
+
result[key] = callback(value, key);
|
|
162
|
+
}
|
|
163
|
+
return result;
|
|
217
164
|
}
|
|
218
|
-
function
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (typeof result !== "string")
|
|
223
|
-
panic(`[praxis-kit] Plugin pipeline must return a string. Got: ${describe(result)}.`);
|
|
224
|
-
return result;
|
|
225
|
-
};
|
|
165
|
+
function forEachEntry(object, callback) {
|
|
166
|
+
for (const [key, value] of entries(object)) {
|
|
167
|
+
callback(key, value);
|
|
168
|
+
}
|
|
226
169
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (!factory) {
|
|
231
|
-
const createClassPipeline2 = capabilities?.createClassPipeline;
|
|
232
|
-
const classPipeline2 = createClassPipeline2 ? createClassPipeline2(resolved) : NOOP_CLASS_PIPELINE;
|
|
233
|
-
return { pluginResult: void 0, classPipeline: classPipeline2 };
|
|
170
|
+
function forEachKey(object, callback) {
|
|
171
|
+
for (const key of keys(object)) {
|
|
172
|
+
callback(key);
|
|
234
173
|
}
|
|
235
|
-
const pluginResult = factory(resolved, strict);
|
|
236
|
-
assertPluginShape(pluginResult);
|
|
237
|
-
const classPipeline = guardPipeline(pluginResult.pipeline);
|
|
238
|
-
return { pluginResult, classPipeline };
|
|
239
174
|
}
|
|
240
|
-
function
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return mergeProps(resolved.defaultProps, props);
|
|
245
|
-
},
|
|
246
|
-
resolveClasses(tag, props, className, recipe) {
|
|
247
|
-
if (process.env.NODE_ENV !== "production") {
|
|
248
|
-
validateRenderProps(resolved, props, recipe);
|
|
249
|
-
}
|
|
250
|
-
return classPipeline(tag, props, className, recipe);
|
|
251
|
-
},
|
|
252
|
-
resolveAria(tag, props) {
|
|
253
|
-
if (!engine) return { props };
|
|
254
|
-
const result = engine.validate(tag, props);
|
|
255
|
-
return { props: result.props };
|
|
256
|
-
}
|
|
257
|
-
};
|
|
175
|
+
function forEachValue(object, callback) {
|
|
176
|
+
for (const value of values(object)) {
|
|
177
|
+
callback(value);
|
|
178
|
+
}
|
|
258
179
|
}
|
|
259
|
-
function
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const baseResolved = resolveFactoryOptions(options);
|
|
264
|
-
const resolved = capabilities?.htmlPropNormalizersFn !== void 0 ? Object.freeze({
|
|
265
|
-
...baseResolved,
|
|
266
|
-
htmlPropNormalizersFn: capabilities.htmlPropNormalizersFn
|
|
267
|
-
}) : baseResolved;
|
|
268
|
-
if (process.env.NODE_ENV !== "production") validateFactoryOptions(resolved);
|
|
269
|
-
const { pluginResult, classPipeline } = resolveClassPipeline(
|
|
270
|
-
options,
|
|
271
|
-
resolved,
|
|
272
|
-
resolved.strict,
|
|
273
|
-
capabilities
|
|
274
|
-
);
|
|
275
|
-
const allAriaRules = [
|
|
276
|
-
.../* @__PURE__ */ new Set([...capabilities?.htmlAriaRules ?? [], ...resolved.ariaRules ?? []])
|
|
277
|
-
];
|
|
278
|
-
const engine = options.enforcement !== void 0 && capabilities?.AriaEngine ? new capabilities.AriaEngine(
|
|
279
|
-
resolved.strict,
|
|
280
|
-
allAriaRules.length ? { rules: allAriaRules } : void 0
|
|
281
|
-
) : null;
|
|
282
|
-
const methods = createRuntimeMethods(resolved, classPipeline, engine);
|
|
283
|
-
return createRuntimeObject(
|
|
284
|
-
methods,
|
|
285
|
-
resolved,
|
|
286
|
-
pluginResult
|
|
287
|
-
);
|
|
180
|
+
function forEachSet(s, callback) {
|
|
181
|
+
for (const value of s) {
|
|
182
|
+
callback(value);
|
|
183
|
+
}
|
|
288
184
|
}
|
|
289
|
-
var
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
"grid",
|
|
315
|
-
"gridcell",
|
|
316
|
-
"group",
|
|
317
|
-
"heading",
|
|
318
|
-
"img",
|
|
319
|
-
"insertion",
|
|
320
|
-
"link",
|
|
321
|
-
"list",
|
|
322
|
-
"listbox",
|
|
323
|
-
"listitem",
|
|
324
|
-
"log",
|
|
325
|
-
"main",
|
|
326
|
-
"marquee",
|
|
327
|
-
"math",
|
|
328
|
-
"menu",
|
|
329
|
-
"menubar",
|
|
330
|
-
"menuitem",
|
|
331
|
-
"menuitemcheckbox",
|
|
332
|
-
"menuitemradio",
|
|
333
|
-
"meter",
|
|
334
|
-
"navigation",
|
|
335
|
-
"none",
|
|
336
|
-
"note",
|
|
337
|
-
"option",
|
|
338
|
-
"paragraph",
|
|
339
|
-
"presentation",
|
|
340
|
-
"progressbar",
|
|
341
|
-
"radio",
|
|
342
|
-
"radiogroup",
|
|
343
|
-
"region",
|
|
344
|
-
"row",
|
|
345
|
-
"rowgroup",
|
|
346
|
-
"rowheader",
|
|
347
|
-
"scrollbar",
|
|
348
|
-
"search",
|
|
349
|
-
"searchbox",
|
|
350
|
-
"separator",
|
|
351
|
-
"slider",
|
|
352
|
-
"spinbutton",
|
|
353
|
-
"status",
|
|
354
|
-
"strong",
|
|
355
|
-
"subscript",
|
|
356
|
-
"superscript",
|
|
357
|
-
"switch",
|
|
358
|
-
"tab",
|
|
359
|
-
"table",
|
|
360
|
-
"tablist",
|
|
361
|
-
"tabpanel",
|
|
362
|
-
"term",
|
|
363
|
-
"textbox",
|
|
364
|
-
"time",
|
|
365
|
-
"timer",
|
|
366
|
-
"toolbar",
|
|
367
|
-
"tooltip",
|
|
368
|
-
"tree",
|
|
369
|
-
"treegrid",
|
|
370
|
-
"treeitem"
|
|
371
|
-
];
|
|
372
|
-
var KNOWN_ARIA_ROLES_SET = new Set(KNOWN_ARIA_ROLES);
|
|
185
|
+
var iterate = Object.freeze({
|
|
186
|
+
entries,
|
|
187
|
+
filter,
|
|
188
|
+
find,
|
|
189
|
+
findLast,
|
|
190
|
+
forEach,
|
|
191
|
+
forEachEntry,
|
|
192
|
+
forEachKey,
|
|
193
|
+
forEachSet,
|
|
194
|
+
forEachValue,
|
|
195
|
+
items,
|
|
196
|
+
keys,
|
|
197
|
+
map,
|
|
198
|
+
mapEntries,
|
|
199
|
+
mapValues,
|
|
200
|
+
nodeList,
|
|
201
|
+
reduce,
|
|
202
|
+
collect,
|
|
203
|
+
set,
|
|
204
|
+
some,
|
|
205
|
+
every,
|
|
206
|
+
values
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// ../../lib/primitive/src/constants/aria/global-aria-attributes.ts
|
|
373
210
|
var GLOBAL_ARIA_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
374
211
|
"aria-atomic",
|
|
375
212
|
"aria-busy",
|
|
@@ -389,29 +226,59 @@ var GLOBAL_ARIA_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
|
389
226
|
"aria-relevant",
|
|
390
227
|
"aria-roledescription"
|
|
391
228
|
]);
|
|
229
|
+
|
|
230
|
+
// ../../lib/primitive/src/constants/aria/implicit-role-record.ts
|
|
392
231
|
var IMPLICIT_ROLE_RECORD = {
|
|
232
|
+
// Landmarks
|
|
393
233
|
article: "article",
|
|
394
234
|
aside: "complementary",
|
|
395
235
|
footer: "contentinfo",
|
|
396
236
|
header: "banner",
|
|
397
237
|
main: "main",
|
|
398
238
|
nav: "navigation",
|
|
399
|
-
|
|
239
|
+
// Interactive
|
|
400
240
|
a: "link",
|
|
241
|
+
button: "button",
|
|
401
242
|
select: "listbox",
|
|
243
|
+
textarea: "textbox",
|
|
244
|
+
// Headings
|
|
402
245
|
h1: "heading",
|
|
403
246
|
h2: "heading",
|
|
404
247
|
h3: "heading",
|
|
405
248
|
h4: "heading",
|
|
406
249
|
h5: "heading",
|
|
407
250
|
h6: "heading",
|
|
251
|
+
// Lists
|
|
408
252
|
ul: "list",
|
|
409
253
|
ol: "list",
|
|
410
254
|
li: "listitem",
|
|
255
|
+
// Tables
|
|
411
256
|
table: "table",
|
|
412
257
|
tr: "row",
|
|
413
258
|
td: "cell",
|
|
414
|
-
th: "columnheader"
|
|
259
|
+
th: "columnheader",
|
|
260
|
+
// Structural / semantic
|
|
261
|
+
dialog: "dialog",
|
|
262
|
+
fieldset: "group",
|
|
263
|
+
figure: "figure",
|
|
264
|
+
meter: "meter",
|
|
265
|
+
output: "status",
|
|
266
|
+
progress: "progressbar"
|
|
267
|
+
};
|
|
268
|
+
var INPUT_TYPE_ROLE_MAP = {
|
|
269
|
+
checkbox: "checkbox",
|
|
270
|
+
radio: "radio",
|
|
271
|
+
range: "slider",
|
|
272
|
+
number: "spinbutton",
|
|
273
|
+
search: "searchbox",
|
|
274
|
+
text: "textbox",
|
|
275
|
+
email: "textbox",
|
|
276
|
+
tel: "textbox",
|
|
277
|
+
url: "textbox",
|
|
278
|
+
button: "button",
|
|
279
|
+
submit: "button",
|
|
280
|
+
reset: "button",
|
|
281
|
+
image: "button"
|
|
415
282
|
};
|
|
416
283
|
var STRONG_ROLES = [
|
|
417
284
|
"main",
|
|
@@ -423,6 +290,8 @@ var STRONG_ROLES = [
|
|
|
423
290
|
var STANDALONE_ROLES = ["article"];
|
|
424
291
|
var STRONG_ROLES_SET = new Set(STRONG_ROLES);
|
|
425
292
|
var STANDALONE_ROLES_SET = new Set(STANDALONE_ROLES);
|
|
293
|
+
|
|
294
|
+
// ../../lib/primitive/src/constants/aria/role-restricted-attributes.ts
|
|
426
295
|
var ROLE_RESTRICTED_ATTRIBUTES = /* @__PURE__ */ new Map([
|
|
427
296
|
[
|
|
428
297
|
"aria-activedescendant",
|
|
@@ -572,9 +441,18 @@ var ROLE_RESTRICTED_ATTRIBUTES = /* @__PURE__ */ new Map([
|
|
|
572
441
|
/* @__PURE__ */ new Set(["meter", "progressbar", "scrollbar", "separator", "slider", "spinbutton"])
|
|
573
442
|
]
|
|
574
443
|
]);
|
|
444
|
+
|
|
445
|
+
// ../../lib/primitive/src/guards/foundational/is-defined.ts
|
|
575
446
|
function isUndefined(value) {
|
|
576
447
|
return value === void 0;
|
|
577
448
|
}
|
|
449
|
+
|
|
450
|
+
// ../../lib/primitive/src/guards/foundational/is-null.ts
|
|
451
|
+
function isNull(value) {
|
|
452
|
+
return value === null;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// ../../lib/primitive/src/guards/aria/is-aria-attribute.ts
|
|
578
456
|
function isGlobalAriaAttribute(attr) {
|
|
579
457
|
return GLOBAL_ARIA_ATTRIBUTES.has(attr);
|
|
580
458
|
}
|
|
@@ -584,6 +462,8 @@ function isAriaAttributeValidForRole(attr, role) {
|
|
|
584
462
|
if (isUndefined(role)) return false;
|
|
585
463
|
return allowedRoles.has(role);
|
|
586
464
|
}
|
|
465
|
+
|
|
466
|
+
// ../../lib/primitive/src/guards/aria/is-aria-role.ts
|
|
587
467
|
function isStrongImplicitRole(tag) {
|
|
588
468
|
if (!(tag in IMPLICIT_ROLE_RECORD)) return false;
|
|
589
469
|
return STRONG_ROLES_SET.has(IMPLICIT_ROLE_RECORD[tag]);
|
|
@@ -592,40 +472,22 @@ function isStandaloneTag(tag) {
|
|
|
592
472
|
if (!(tag in IMPLICIT_ROLE_RECORD)) return false;
|
|
593
473
|
return STANDALONE_ROLES_SET.has(IMPLICIT_ROLE_RECORD[tag]);
|
|
594
474
|
}
|
|
595
|
-
function
|
|
596
|
-
|
|
475
|
+
function getInputImplicitRole(type) {
|
|
476
|
+
if (type == null || !(type in INPUT_TYPE_ROLE_MAP)) return void 0;
|
|
477
|
+
return INPUT_TYPE_ROLE_MAP[type];
|
|
597
478
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
footer: "contentinfo",
|
|
604
|
-
header: "banner",
|
|
605
|
-
main: "main",
|
|
606
|
-
nav: "navigation",
|
|
607
|
-
button: "button",
|
|
608
|
-
a: "link",
|
|
609
|
-
select: "listbox",
|
|
610
|
-
h1: "heading",
|
|
611
|
-
h2: "heading",
|
|
612
|
-
h3: "heading",
|
|
613
|
-
h4: "heading",
|
|
614
|
-
h5: "heading",
|
|
615
|
-
h6: "heading",
|
|
616
|
-
ul: "list",
|
|
617
|
-
ol: "list",
|
|
618
|
-
li: "listitem",
|
|
619
|
-
table: "table",
|
|
620
|
-
tr: "row",
|
|
621
|
-
td: "cell",
|
|
622
|
-
th: "columnheader"
|
|
623
|
-
};
|
|
624
|
-
function getImplicitRole(tag) {
|
|
625
|
-
if (tag in IMPLICIT_ROLE_RECORD2) return IMPLICIT_ROLE_RECORD2[tag];
|
|
479
|
+
function getConditionalImplicitRole(tag, ariaLabel, ariaLabelledBy) {
|
|
480
|
+
const isNamed = typeof ariaLabel === "string" || typeof ariaLabelledBy === "string";
|
|
481
|
+
if (!isNamed) return void 0;
|
|
482
|
+
if (tag === "section") return "region";
|
|
483
|
+
if (tag === "form") return "form";
|
|
626
484
|
return void 0;
|
|
627
485
|
}
|
|
628
|
-
|
|
486
|
+
|
|
487
|
+
// ../../lib/primitive/src/guards/children/component-id.ts
|
|
488
|
+
var COMPONENT_DEFAULT_TAG = /* @__PURE__ */ Symbol.for("praxis.component-default-tag");
|
|
489
|
+
|
|
490
|
+
// ../../lib/primitive/src/guards/children/is-tag.ts
|
|
629
491
|
function getAsProp(child) {
|
|
630
492
|
if (!isObject(child) || !("props" in child)) return void 0;
|
|
631
493
|
const props = child.props;
|
|
@@ -638,7 +500,7 @@ function getTag(child) {
|
|
|
638
500
|
const t = child.type;
|
|
639
501
|
if (isString(t)) return t;
|
|
640
502
|
if (typeof t === "function" || isObject(t)) {
|
|
641
|
-
const defaultTag = t[
|
|
503
|
+
const defaultTag = t[COMPONENT_DEFAULT_TAG];
|
|
642
504
|
if (!isString(defaultTag)) return void 0;
|
|
643
505
|
return getAsProp(child) ?? defaultTag;
|
|
644
506
|
}
|
|
@@ -646,65 +508,543 @@ function getTag(child) {
|
|
|
646
508
|
}
|
|
647
509
|
function isTag(...args) {
|
|
648
510
|
if (isString(args[0])) {
|
|
649
|
-
const
|
|
511
|
+
const set3 = new Set(args);
|
|
650
512
|
return (child2) => {
|
|
651
513
|
const tag2 = getTag(child2);
|
|
652
|
-
return tag2 !== void 0 &&
|
|
514
|
+
return tag2 !== void 0 && set3.has(tag2);
|
|
653
515
|
};
|
|
654
516
|
}
|
|
655
517
|
const [child, ...tags] = args;
|
|
656
|
-
const
|
|
518
|
+
const set2 = new Set(tags);
|
|
657
519
|
const tag = getTag(child);
|
|
658
|
-
return tag !== void 0 &&
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
function
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
function scheduleAsyncWarn(message) {
|
|
671
|
-
if (pendingAsyncWarns2.has(message)) return;
|
|
672
|
-
pendingAsyncWarns2.add(message);
|
|
673
|
-
if (!asyncWarnScheduled2) {
|
|
674
|
-
asyncWarnScheduled2 = true;
|
|
675
|
-
queueMicrotask(flushAsyncWarns2);
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
var StrictBase = class {
|
|
679
|
-
strict;
|
|
680
|
-
constructor(strict) {
|
|
681
|
-
this.strict = strict;
|
|
682
|
-
}
|
|
683
|
-
violate(message) {
|
|
684
|
-
if (this.strict === true || this.strict === "throw") {
|
|
685
|
-
throw new Error(message);
|
|
686
|
-
}
|
|
687
|
-
this.warn(message);
|
|
520
|
+
return tag !== void 0 && set2.has(tag);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// ../../lib/contract/src/aria/aria-role-policy.ts
|
|
524
|
+
function getImplicitRole(tag, props) {
|
|
525
|
+
if (tag in IMPLICIT_ROLE_RECORD) return IMPLICIT_ROLE_RECORD[tag];
|
|
526
|
+
if (tag === "input") return getInputImplicitRole(props?.type);
|
|
527
|
+
if (tag === "img") return props?.alt === "" ? "none" : "img";
|
|
528
|
+
if (tag === "section" || tag === "form") {
|
|
529
|
+
return getConditionalImplicitRole(tag, props?.["aria-label"], props?.["aria-labelledby"]);
|
|
688
530
|
}
|
|
689
|
-
|
|
531
|
+
return void 0;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// ../../lib/contract/src/strict/invariant-base.ts
|
|
535
|
+
var InvariantBase = class {
|
|
536
|
+
diagnostics;
|
|
537
|
+
constructor(diagnostics) {
|
|
538
|
+
this.diagnostics = diagnostics;
|
|
539
|
+
}
|
|
540
|
+
get active() {
|
|
541
|
+
return this.diagnostics.active;
|
|
542
|
+
}
|
|
543
|
+
violate(input) {
|
|
544
|
+
this.diagnostics.error(input);
|
|
545
|
+
}
|
|
546
|
+
// Always caps at warn — never throws. ARIA 'warning' violations route here
|
|
690
547
|
// so they surface even in strict='throw' mode without aborting a render.
|
|
691
|
-
warn(
|
|
692
|
-
|
|
693
|
-
if (this.strict === "async-warn") {
|
|
694
|
-
scheduleAsyncWarn(message);
|
|
695
|
-
return;
|
|
696
|
-
}
|
|
697
|
-
console.warn(message);
|
|
548
|
+
warn(input) {
|
|
549
|
+
this.diagnostics.warn(input);
|
|
698
550
|
}
|
|
699
|
-
invariant(condition,
|
|
700
|
-
if (!condition)
|
|
701
|
-
this.violate(message);
|
|
702
|
-
}
|
|
551
|
+
invariant(condition, input) {
|
|
552
|
+
if (!condition) this.violate(input);
|
|
703
553
|
}
|
|
704
554
|
};
|
|
705
|
-
|
|
706
|
-
|
|
555
|
+
|
|
556
|
+
// ../../lib/diagnostics/src/category.ts
|
|
557
|
+
var DiagnosticCategory = /* @__PURE__ */ ((DiagnosticCategory2) => {
|
|
558
|
+
DiagnosticCategory2[DiagnosticCategory2["Contract"] = 0] = "Contract";
|
|
559
|
+
DiagnosticCategory2[DiagnosticCategory2["HTML"] = 1] = "HTML";
|
|
560
|
+
DiagnosticCategory2[DiagnosticCategory2["ARIA"] = 2] = "ARIA";
|
|
561
|
+
DiagnosticCategory2[DiagnosticCategory2["Composition"] = 3] = "Composition";
|
|
562
|
+
DiagnosticCategory2[DiagnosticCategory2["Rendering"] = 4] = "Rendering";
|
|
563
|
+
DiagnosticCategory2[DiagnosticCategory2["Accessibility"] = 5] = "Accessibility";
|
|
564
|
+
DiagnosticCategory2[DiagnosticCategory2["Performance"] = 6] = "Performance";
|
|
565
|
+
DiagnosticCategory2[DiagnosticCategory2["Internal"] = 7] = "Internal";
|
|
566
|
+
DiagnosticCategory2[DiagnosticCategory2["Deprecation"] = 8] = "Deprecation";
|
|
567
|
+
DiagnosticCategory2[DiagnosticCategory2["Lint"] = 9] = "Lint";
|
|
568
|
+
return DiagnosticCategory2;
|
|
569
|
+
})(DiagnosticCategory || {});
|
|
570
|
+
|
|
571
|
+
// ../../lib/diagnostics/src/error.ts
|
|
572
|
+
var PraxisError = class extends Error {
|
|
573
|
+
diagnostic;
|
|
574
|
+
constructor(diagnostic) {
|
|
575
|
+
super(diagnostic.message);
|
|
576
|
+
this.name = "PraxisError";
|
|
577
|
+
this.diagnostic = diagnostic;
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
// ../../lib/diagnostics/src/severity.ts
|
|
582
|
+
var Severity = /* @__PURE__ */ ((Severity2) => {
|
|
583
|
+
Severity2[Severity2["Debug"] = 0] = "Debug";
|
|
584
|
+
Severity2[Severity2["Info"] = 1] = "Info";
|
|
585
|
+
Severity2[Severity2["Warning"] = 2] = "Warning";
|
|
586
|
+
Severity2[Severity2["Error"] = 3] = "Error";
|
|
587
|
+
Severity2[Severity2["Fatal"] = 4] = "Fatal";
|
|
588
|
+
return Severity2;
|
|
589
|
+
})(Severity || {});
|
|
590
|
+
|
|
591
|
+
// ../../lib/diagnostics/src/policy.ts
|
|
592
|
+
var DefaultPolicy = class {
|
|
593
|
+
reportThreshold;
|
|
594
|
+
throwThreshold;
|
|
595
|
+
constructor({
|
|
596
|
+
reportThreshold = 1 /* Info */,
|
|
597
|
+
throwThreshold = 4 /* Fatal */
|
|
598
|
+
} = {}) {
|
|
599
|
+
this.reportThreshold = reportThreshold;
|
|
600
|
+
this.throwThreshold = throwThreshold;
|
|
601
|
+
}
|
|
602
|
+
resolve(diagnostic) {
|
|
603
|
+
if (diagnostic.severity >= this.throwThreshold) return 2 /* Throw */;
|
|
604
|
+
if (diagnostic.severity >= this.reportThreshold) return 1 /* Report */;
|
|
605
|
+
return 0 /* Ignore */;
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
// ../../lib/diagnostics/src/diagnostics.ts
|
|
610
|
+
var Diagnostics = class {
|
|
611
|
+
reporter;
|
|
612
|
+
policy;
|
|
613
|
+
// Pre-computed at construction time: true if Warning-level diagnostics are not ignored.
|
|
614
|
+
active;
|
|
615
|
+
constructor(reporter, policy = new DefaultPolicy()) {
|
|
616
|
+
this.reporter = reporter;
|
|
617
|
+
this.policy = policy;
|
|
618
|
+
this.active = policy.resolve({ severity: 2 /* Warning */ }) !== 0 /* Ignore */;
|
|
619
|
+
}
|
|
620
|
+
report(diagnostic) {
|
|
621
|
+
const enforcement = this.policy.resolve(diagnostic);
|
|
622
|
+
if (enforcement === 0 /* Ignore */) return diagnostic;
|
|
623
|
+
if (enforcement === 2 /* Throw */) throw new PraxisError(diagnostic);
|
|
624
|
+
this.reporter.report(diagnostic);
|
|
625
|
+
return diagnostic;
|
|
626
|
+
}
|
|
627
|
+
warn(input) {
|
|
628
|
+
return this.report({ ...input, severity: 2 /* Warning */ });
|
|
629
|
+
}
|
|
630
|
+
error(input) {
|
|
631
|
+
return this.report({ ...input, severity: 3 /* Error */ });
|
|
632
|
+
}
|
|
633
|
+
info(input) {
|
|
634
|
+
return this.report({ ...input, severity: 1 /* Info */ });
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
// ../../lib/diagnostics/src/formatter.ts
|
|
639
|
+
function formatDiagnostic(diagnostic) {
|
|
640
|
+
const level = Severity[diagnostic.severity];
|
|
641
|
+
const category = DiagnosticCategory[diagnostic.category];
|
|
642
|
+
const prefix = category !== void 0 ? `[${category}] ` : "";
|
|
643
|
+
return `${level} ${diagnostic.code}: ${prefix}${diagnostic.message}`;
|
|
707
644
|
}
|
|
645
|
+
|
|
646
|
+
// ../../lib/diagnostics/src/console-reporter.ts
|
|
647
|
+
var ConsoleReporter = class {
|
|
648
|
+
report(diagnostic) {
|
|
649
|
+
const message = formatDiagnostic(diagnostic);
|
|
650
|
+
switch (diagnostic.severity) {
|
|
651
|
+
case 0 /* Debug */:
|
|
652
|
+
console.debug(message);
|
|
653
|
+
break;
|
|
654
|
+
case 1 /* Info */:
|
|
655
|
+
console.info(message);
|
|
656
|
+
break;
|
|
657
|
+
case 2 /* Warning */:
|
|
658
|
+
console.warn(message);
|
|
659
|
+
break;
|
|
660
|
+
case 3 /* Error */:
|
|
661
|
+
case 4 /* Fatal */:
|
|
662
|
+
console.error(message);
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
// ../../lib/diagnostics/src/null-reporter.ts
|
|
669
|
+
var nullReporter = {
|
|
670
|
+
report() {
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
|
|
674
|
+
// ../../lib/diagnostics/src/presets.ts
|
|
675
|
+
var ignoreAllPolicy = {
|
|
676
|
+
resolve(_) {
|
|
677
|
+
return 0 /* Ignore */;
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
var warnOnlyReporter = {
|
|
681
|
+
report(diagnostic) {
|
|
682
|
+
console.warn(formatDiagnostic(diagnostic));
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
var silentDiagnostics = new Diagnostics(nullReporter, ignoreAllPolicy);
|
|
686
|
+
var warnDiagnostics = new Diagnostics(
|
|
687
|
+
warnOnlyReporter,
|
|
688
|
+
new DefaultPolicy({ reportThreshold: 2 /* Warning */, throwThreshold: 4 /* Fatal */ })
|
|
689
|
+
);
|
|
690
|
+
var throwDiagnostics = new Diagnostics(
|
|
691
|
+
new ConsoleReporter(),
|
|
692
|
+
new DefaultPolicy({ reportThreshold: 2 /* Warning */, throwThreshold: 3 /* Error */ })
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
// ../../lib/contract/src/diagnostics/aria.ts
|
|
696
|
+
var AriaDiagnostics = {
|
|
697
|
+
/** Generic bridge for violations produced by external AriaRule functions. */
|
|
698
|
+
fromViolation(v) {
|
|
699
|
+
return {
|
|
700
|
+
code: "ARIA2002" /* AriaViolation */,
|
|
701
|
+
category: 2 /* ARIA */,
|
|
702
|
+
message: v.message
|
|
703
|
+
};
|
|
704
|
+
},
|
|
705
|
+
attributeInvalid(key, role) {
|
|
706
|
+
return {
|
|
707
|
+
code: "ARIA2003" /* AriaAttributeInvalid */,
|
|
708
|
+
category: 2 /* ARIA */,
|
|
709
|
+
message: `"${key}" is not valid on role="${role}". It will be removed.`,
|
|
710
|
+
rationale: "Invalid ARIA attributes are ignored by assistive technology and may trigger accessibility-tree warnings in browser devtools.",
|
|
711
|
+
suggestions: [
|
|
712
|
+
{
|
|
713
|
+
title: "Remove the attribute",
|
|
714
|
+
description: `"${key}" is not in the allowed attribute set for role="${role}".`
|
|
715
|
+
}
|
|
716
|
+
]
|
|
717
|
+
};
|
|
718
|
+
},
|
|
719
|
+
missingLiveRegion(role, impliedLive) {
|
|
720
|
+
return {
|
|
721
|
+
code: "ARIA2004" /* AriaMissingLiveRegion */,
|
|
722
|
+
category: 2 /* ARIA */,
|
|
723
|
+
message: `role="${role}" implies aria-live="${impliedLive}" but it is missing. It has been injected.`,
|
|
724
|
+
rationale: "Live-region roles announce dynamic content changes to screen readers. Without aria-live the politeness level is unspecified and announcements may be silent.",
|
|
725
|
+
suggestions: [
|
|
726
|
+
{
|
|
727
|
+
title: `Add aria-live="${impliedLive}"`,
|
|
728
|
+
description: `role="${role}" conventionally implies aria-live="${impliedLive}".`,
|
|
729
|
+
fix: `aria-live="${impliedLive}"`
|
|
730
|
+
}
|
|
731
|
+
]
|
|
732
|
+
};
|
|
733
|
+
},
|
|
734
|
+
missingAtomic(role) {
|
|
735
|
+
return {
|
|
736
|
+
code: "ARIA2005" /* AriaMissingAtomic */,
|
|
737
|
+
category: 2 /* ARIA */,
|
|
738
|
+
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.`,
|
|
739
|
+
rationale: "aria-atomic controls whether assistive technology announces the entire live region or only the changed nodes. Omitting it leaves the behaviour browser-defined."
|
|
740
|
+
};
|
|
741
|
+
},
|
|
742
|
+
relevantInvalidTokens(invalid) {
|
|
743
|
+
const quoted = invalid.map((t) => `"${t}"`).join(", ");
|
|
744
|
+
return {
|
|
745
|
+
code: "ARIA2006" /* AriaRelevantInvalidToken */,
|
|
746
|
+
category: 2 /* ARIA */,
|
|
747
|
+
message: `aria-relevant contains invalid token(s): ${quoted}. Valid tokens are: additions, removals, text, all.`,
|
|
748
|
+
rationale: "aria-relevant accepts a space-separated list of change types. Unrecognised tokens are silently ignored by assistive technology, making the attribute ineffective.",
|
|
749
|
+
suggestions: [
|
|
750
|
+
{
|
|
751
|
+
title: "Use only valid tokens",
|
|
752
|
+
description: "Valid values are: additions, removals, text, all (or a space-separated combination)."
|
|
753
|
+
}
|
|
754
|
+
]
|
|
755
|
+
};
|
|
756
|
+
},
|
|
757
|
+
relevantSuperseded() {
|
|
758
|
+
return {
|
|
759
|
+
code: "ARIA2007" /* AriaRelevantSuperseded */,
|
|
760
|
+
category: 2 /* ARIA */,
|
|
761
|
+
message: 'aria-relevant includes "all" alongside other tokens. "all" supersedes additions, removals, and text \u2014 use aria-relevant="all" alone.',
|
|
762
|
+
rationale: '"all" is equivalent to "additions removals text". Combining it with other tokens is redundant and may confuse readers of the markup.',
|
|
763
|
+
suggestions: [
|
|
764
|
+
{
|
|
765
|
+
title: 'Use aria-relevant="all"',
|
|
766
|
+
fix: 'aria-relevant="all"'
|
|
767
|
+
}
|
|
768
|
+
]
|
|
769
|
+
};
|
|
770
|
+
},
|
|
771
|
+
missingAccessibleName(tag) {
|
|
772
|
+
return {
|
|
773
|
+
code: "ARIA2009" /* AriaMissingAccessibleName */,
|
|
774
|
+
category: 2 /* ARIA */,
|
|
775
|
+
message: `<${tag}> has no accessible name. Add aria-label or aria-labelledby.`,
|
|
776
|
+
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.",
|
|
777
|
+
suggestions: [
|
|
778
|
+
{
|
|
779
|
+
title: "Add aria-label",
|
|
780
|
+
description: `Add aria-label="\u2026" directly to the <${tag}> element.`
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
title: "Add aria-labelledby",
|
|
784
|
+
description: "Point aria-labelledby at the id of an existing heading or label element."
|
|
785
|
+
}
|
|
786
|
+
]
|
|
787
|
+
};
|
|
788
|
+
},
|
|
789
|
+
attributeOnPresentational(attr, tag) {
|
|
790
|
+
return {
|
|
791
|
+
code: "ARIA2010" /* AriaAttributeOnPresentational */,
|
|
792
|
+
category: 2 /* ARIA */,
|
|
793
|
+
message: `"${attr}" is not allowed on a presentational <${tag}>. Presentational elements are invisible to assistive technology.`,
|
|
794
|
+
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.',
|
|
795
|
+
suggestions: [
|
|
796
|
+
{
|
|
797
|
+
title: "Remove the attribute",
|
|
798
|
+
description: `"${attr}" has no effect when the element has role="none" or role="presentation".`
|
|
799
|
+
}
|
|
800
|
+
]
|
|
801
|
+
};
|
|
802
|
+
},
|
|
803
|
+
ariaHiddenOnFocusable(tag) {
|
|
804
|
+
return {
|
|
805
|
+
code: "ARIA2011" /* AriaHiddenOnFocusable */,
|
|
806
|
+
category: 2 /* ARIA */,
|
|
807
|
+
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.`,
|
|
808
|
+
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.',
|
|
809
|
+
suggestions: [
|
|
810
|
+
{
|
|
811
|
+
title: "Remove aria-hidden",
|
|
812
|
+
description: "If the element should be hidden from all users, use the HTML hidden attribute or CSS display:none instead."
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
title: "Make the element non-focusable",
|
|
816
|
+
description: 'If the element is intentionally decorative, add tabindex="-1" and disable it so it is not reachable by keyboard.'
|
|
817
|
+
}
|
|
818
|
+
]
|
|
819
|
+
};
|
|
820
|
+
},
|
|
821
|
+
invalidAttributeValue(attr, value, expected) {
|
|
822
|
+
const got = value === null ? "null" : value === void 0 ? "undefined" : typeof value === "string" ? `"${value}"` : String(value);
|
|
823
|
+
return {
|
|
824
|
+
code: "ARIA2013" /* AriaInvalidAttributeValue */,
|
|
825
|
+
category: 2 /* ARIA */,
|
|
826
|
+
message: `"${attr}" has an invalid value (${got}). Expected: ${expected}.`,
|
|
827
|
+
rationale: "ARIA attributes with invalid values are silently ignored by assistive technology, making the markup semantically inert.",
|
|
828
|
+
suggestions: [
|
|
829
|
+
{
|
|
830
|
+
title: `Use a valid value for ${attr}`,
|
|
831
|
+
description: `Valid values are: ${expected}.`
|
|
832
|
+
}
|
|
833
|
+
]
|
|
834
|
+
};
|
|
835
|
+
},
|
|
836
|
+
redundantAriaLevel(tag, level) {
|
|
837
|
+
return {
|
|
838
|
+
code: "ARIA2014" /* AriaRedundantLevelAttribute */,
|
|
839
|
+
category: 2 /* ARIA */,
|
|
840
|
+
message: `aria-level="${level}" is redundant on <${tag}>: the element already has an implicit heading level of ${level}. Remove the attribute.`,
|
|
841
|
+
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>).',
|
|
842
|
+
suggestions: [
|
|
843
|
+
{
|
|
844
|
+
title: "Remove aria-level",
|
|
845
|
+
description: `<${tag}> already implies aria-level="${level}".`
|
|
846
|
+
}
|
|
847
|
+
]
|
|
848
|
+
};
|
|
849
|
+
},
|
|
850
|
+
requiredProperty(attr, role) {
|
|
851
|
+
return {
|
|
852
|
+
code: "ARIA2012" /* AriaRequiredProperty */,
|
|
853
|
+
category: 2 /* ARIA */,
|
|
854
|
+
message: `"${attr}" is required for role="${role}" but is missing.`,
|
|
855
|
+
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.`,
|
|
856
|
+
suggestions: [
|
|
857
|
+
{
|
|
858
|
+
title: `Add ${attr}`,
|
|
859
|
+
description: `role="${role}" requires "${attr}" to be present.`
|
|
860
|
+
}
|
|
861
|
+
]
|
|
862
|
+
};
|
|
863
|
+
},
|
|
864
|
+
invalidRole(role, tag) {
|
|
865
|
+
return {
|
|
866
|
+
code: "ARIA2008" /* AriaInvalidRole */,
|
|
867
|
+
category: 2 /* ARIA */,
|
|
868
|
+
message: `Invalid role "${role ?? ""}" on <${tag}>.`,
|
|
869
|
+
rationale: "An unrecognised or misapplied ARIA role is ignored by assistive technology and may degrade the accessibility of the element."
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
|
|
874
|
+
// ../../lib/contract/src/diagnostics/contract.ts
|
|
875
|
+
var ContractDiagnostics = {
|
|
876
|
+
unexpectedChild(typeName, index, context) {
|
|
877
|
+
return {
|
|
878
|
+
code: "COMP1004" /* UnexpectedChild */,
|
|
879
|
+
category: 0 /* Contract */,
|
|
880
|
+
component: context,
|
|
881
|
+
message: `${context}: unexpected child "${typeName}" at index ${index}.`
|
|
882
|
+
};
|
|
883
|
+
},
|
|
884
|
+
ambiguousChild(typeName, index, ruleNames, context) {
|
|
885
|
+
const quoted = ruleNames.map((n) => `"${n}"`).join(" and ");
|
|
886
|
+
return {
|
|
887
|
+
code: "COMP1005" /* AmbiguousChild */,
|
|
888
|
+
category: 0 /* Contract */,
|
|
889
|
+
component: context,
|
|
890
|
+
message: `${context}: child "${typeName}" at index ${index} matches multiple child rules: ${quoted}.`
|
|
891
|
+
};
|
|
892
|
+
},
|
|
893
|
+
cardinalityMin(ruleName, min, context) {
|
|
894
|
+
return {
|
|
895
|
+
code: "COMP1006" /* CardinalityMin */,
|
|
896
|
+
category: 0 /* Contract */,
|
|
897
|
+
component: context,
|
|
898
|
+
message: `${context}: "${ruleName}" requires at least ${min}.`
|
|
899
|
+
};
|
|
900
|
+
},
|
|
901
|
+
cardinalityMax(ruleName, max, context) {
|
|
902
|
+
return {
|
|
903
|
+
code: "COMP1007" /* CardinalityMax */,
|
|
904
|
+
category: 0 /* Contract */,
|
|
905
|
+
component: context,
|
|
906
|
+
message: `${context}: "${ruleName}" allows at most ${max}.`
|
|
907
|
+
};
|
|
908
|
+
},
|
|
909
|
+
positionViolation(ruleName, position, index, context) {
|
|
910
|
+
return {
|
|
911
|
+
code: "COMP1008" /* PositionViolation */,
|
|
912
|
+
category: 0 /* Contract */,
|
|
913
|
+
component: context,
|
|
914
|
+
message: `${context}: "${ruleName}" must be ${position}, got index ${index}`
|
|
915
|
+
};
|
|
916
|
+
},
|
|
917
|
+
unknownVariantDim(component, label, dim) {
|
|
918
|
+
return {
|
|
919
|
+
code: "COMP1010" /* ContractUnknownVariantDim */,
|
|
920
|
+
category: 0 /* Contract */,
|
|
921
|
+
message: `${component}: ${label} references unknown variant "${dim}".`
|
|
922
|
+
};
|
|
923
|
+
},
|
|
924
|
+
unknownVariantValue(component, label, dim, value, valid) {
|
|
925
|
+
return {
|
|
926
|
+
code: "COMP1011" /* ContractUnknownVariantValue */,
|
|
927
|
+
category: 0 /* Contract */,
|
|
928
|
+
message: `${component}: ${label} sets "${dim}" to unknown value "${value}" (valid: ${valid.join(", ")}).`
|
|
929
|
+
};
|
|
930
|
+
},
|
|
931
|
+
unknownRecipeKey(component, key) {
|
|
932
|
+
return {
|
|
933
|
+
code: "COMP1012" /* ContractUnknownRecipeKey */,
|
|
934
|
+
category: 0 /* Contract */,
|
|
935
|
+
message: `${component} Unknown recipeKey "${key}" \u2014 no preset with that name exists.`
|
|
936
|
+
};
|
|
937
|
+
},
|
|
938
|
+
invalidVariantValue(component, key, value) {
|
|
939
|
+
return {
|
|
940
|
+
code: "COMP1013" /* ContractInvalidVariantValue */,
|
|
941
|
+
category: 0 /* Contract */,
|
|
942
|
+
message: `${component} Variant "${key}=${value}" is not a defined value for the "${key}" dimension.`
|
|
943
|
+
};
|
|
944
|
+
},
|
|
945
|
+
allowedAsViolation(tag, allowedAs, component) {
|
|
946
|
+
const allowed = allowedAs.map((t) => `"${String(t)}"`).join(", ");
|
|
947
|
+
return {
|
|
948
|
+
code: "COMP1009" /* AllowedAsViolation */,
|
|
949
|
+
category: 0 /* Contract */,
|
|
950
|
+
component,
|
|
951
|
+
message: `<${component}>: "as" prop received "${tag}" but only [${allowed}] are allowed.`
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
};
|
|
955
|
+
|
|
956
|
+
// ../../lib/contract/src/diagnostics/html.ts
|
|
957
|
+
var HtmlDiagnostics = {
|
|
958
|
+
emptyRole(tag) {
|
|
959
|
+
return {
|
|
960
|
+
code: "HTML3002" /* HtmlEmptyRole */,
|
|
961
|
+
category: 1 /* HTML */,
|
|
962
|
+
message: `<${tag}> has an explicit empty role="". Omit the attribute instead.`
|
|
963
|
+
};
|
|
964
|
+
},
|
|
965
|
+
implicitRoleRedundant(tag, implicitRole) {
|
|
966
|
+
return {
|
|
967
|
+
code: "HTML3003" /* HtmlImplicitRoleRedundant */,
|
|
968
|
+
category: 1 /* HTML */,
|
|
969
|
+
message: `<${tag}> already has implicit role="${implicitRole}". Avoid redundant role assignment.`
|
|
970
|
+
};
|
|
971
|
+
},
|
|
972
|
+
implicitRoleOverride(tag, implicitRole, role) {
|
|
973
|
+
return {
|
|
974
|
+
code: "HTML3004" /* HtmlImplicitRoleOverride */,
|
|
975
|
+
category: 1 /* HTML */,
|
|
976
|
+
message: `<${tag}> should not override its implicit role="${implicitRole}" with role="${role}".`
|
|
977
|
+
};
|
|
978
|
+
},
|
|
979
|
+
standaloneRegionOverride(tag, implicitRole) {
|
|
980
|
+
return {
|
|
981
|
+
code: "HTML3005" /* HtmlStandaloneRegionOverride */,
|
|
982
|
+
category: 1 /* HTML */,
|
|
983
|
+
message: `<${tag}> is a self-contained element with implicit role="${implicitRole}". Assigning role="region" has been removed.`
|
|
984
|
+
};
|
|
985
|
+
},
|
|
986
|
+
landmarkRoleOverride(tag, implicitRole, role) {
|
|
987
|
+
return {
|
|
988
|
+
code: "HTML3006" /* HtmlLandmarkRoleOverride */,
|
|
989
|
+
category: 1 /* HTML */,
|
|
990
|
+
message: `<${tag}> has a fixed landmark role="${implicitRole}". role="${role}" overrides it and confuses assistive technology. The override has been removed.`
|
|
991
|
+
};
|
|
992
|
+
},
|
|
993
|
+
invalidChild(child, parent, allowed) {
|
|
994
|
+
return {
|
|
995
|
+
code: "HTML3007" /* HtmlInvalidChild */,
|
|
996
|
+
category: 1 /* HTML */,
|
|
997
|
+
message: `<${child}> is not a valid direct child of <${parent}>. Allowed: ${allowed}.`
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
|
|
1002
|
+
// ../../lib/contract/src/diagnostics/slot.ts
|
|
1003
|
+
var SlotDiagnostics = {
|
|
1004
|
+
exclusive(name) {
|
|
1005
|
+
return {
|
|
1006
|
+
code: "SLOT1001" /* SlotExclusive */,
|
|
1007
|
+
category: 0 /* Contract */,
|
|
1008
|
+
component: name,
|
|
1009
|
+
message: `${name}: "as" and "asChild" are mutually exclusive`
|
|
1010
|
+
};
|
|
1011
|
+
},
|
|
1012
|
+
singleChildRequired(name, elementTerm) {
|
|
1013
|
+
return {
|
|
1014
|
+
code: "SLOT1002" /* SlotSingleChild */,
|
|
1015
|
+
category: 0 /* Contract */,
|
|
1016
|
+
component: name,
|
|
1017
|
+
message: `${name}: asChild requires a ${elementTerm} child`
|
|
1018
|
+
};
|
|
1019
|
+
},
|
|
1020
|
+
singleChildExceeded(name, elementTerm, count) {
|
|
1021
|
+
return {
|
|
1022
|
+
code: "SLOT1002" /* SlotSingleChild */,
|
|
1023
|
+
category: 0 /* Contract */,
|
|
1024
|
+
component: name,
|
|
1025
|
+
message: `${name}: asChild requires exactly one ${elementTerm} child, got ${count}`
|
|
1026
|
+
};
|
|
1027
|
+
},
|
|
1028
|
+
discardedChildren(name, elementTerm, count) {
|
|
1029
|
+
const suffix = count === 1 ? "" : "ren";
|
|
1030
|
+
return {
|
|
1031
|
+
code: "SLOT1003" /* SlotDiscardedChildren */,
|
|
1032
|
+
category: 0 /* Contract */,
|
|
1033
|
+
component: name,
|
|
1034
|
+
message: `${name}: asChild discarded ${count} non-element child${suffix} \u2014 only ${elementTerm}s are valid asChild children.`
|
|
1035
|
+
};
|
|
1036
|
+
},
|
|
1037
|
+
renderFnRequired(name, received) {
|
|
1038
|
+
return {
|
|
1039
|
+
code: "SLOT1004" /* SlotRenderFn */,
|
|
1040
|
+
category: 0 /* Contract */,
|
|
1041
|
+
component: name,
|
|
1042
|
+
message: `${name}: asChild requires a render function as children, got ${received}`
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
|
|
1047
|
+
// ../../lib/contract/src/aria/polymorphic-validator.ts
|
|
708
1048
|
var VALID = [{ valid: true }];
|
|
709
1049
|
function isIntrinsicTag(tag) {
|
|
710
1050
|
return isString(tag);
|
|
@@ -713,26 +1053,28 @@ function omitProp(obj, key) {
|
|
|
713
1053
|
const { [key]: _, ...rest } = obj;
|
|
714
1054
|
return rest;
|
|
715
1055
|
}
|
|
716
|
-
var AriaPolicyEngine = class _AriaPolicyEngine extends
|
|
1056
|
+
var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
717
1057
|
#extraRules;
|
|
718
1058
|
#planCache = /* @__PURE__ */ new Map();
|
|
719
1059
|
static #MAX_CACHE = 100;
|
|
720
1060
|
// Memoized AriaFix objects keyed by attribute name — the ARIA attribute set is
|
|
721
1061
|
// finite so this Map is bounded and avoids recreating closures on every cache miss.
|
|
722
1062
|
static #removeAttributeFixCache = /* @__PURE__ */ new Map();
|
|
723
|
-
constructor(
|
|
724
|
-
super(
|
|
1063
|
+
constructor(diagnostics, options) {
|
|
1064
|
+
super(diagnostics);
|
|
725
1065
|
this.#extraRules = options?.rules ?? [];
|
|
726
1066
|
}
|
|
727
1067
|
static #normalizeEmptyRole(tag, props) {
|
|
728
1068
|
if (props.role !== "") return { normalized: false };
|
|
1069
|
+
const d = HtmlDiagnostics.emptyRole(tag);
|
|
729
1070
|
return {
|
|
730
1071
|
normalized: true,
|
|
731
1072
|
result: {
|
|
732
1073
|
props: omitProp(props, "role"),
|
|
733
1074
|
violations: [
|
|
734
1075
|
{
|
|
735
|
-
message:
|
|
1076
|
+
message: d.message,
|
|
1077
|
+
diagnostic: d,
|
|
736
1078
|
tag,
|
|
737
1079
|
role: "",
|
|
738
1080
|
attribute: void 0,
|
|
@@ -745,10 +1087,9 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
745
1087
|
}
|
|
746
1088
|
static #deriveContext(tag, props) {
|
|
747
1089
|
if (!isIntrinsicTag(tag)) return { proceed: false, result: { props, violations: [] } };
|
|
748
|
-
const implicitRole = getImplicitRole(tag);
|
|
749
|
-
const
|
|
750
|
-
if (!
|
|
751
|
-
return { proceed: false, result: { props, violations: [] } };
|
|
1090
|
+
const implicitRole = getImplicitRole(tag, props);
|
|
1091
|
+
const hasRole2 = implicitRole != null || isString(props.role) && props.role.length > 0;
|
|
1092
|
+
if (!hasRole2) return { proceed: false, result: { props, violations: [] } };
|
|
752
1093
|
const normalized = _AriaPolicyEngine.#normalizeEmptyRole(tag, props);
|
|
753
1094
|
if (normalized.normalized) return { proceed: false, result: normalized.result };
|
|
754
1095
|
const effectiveRole = props.role ?? implicitRole;
|
|
@@ -763,25 +1104,36 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
763
1104
|
static #runRules(rules, context) {
|
|
764
1105
|
const violations = [];
|
|
765
1106
|
const fixes = [];
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
if (
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
1107
|
+
iterate.forEach(rules, (rule) => {
|
|
1108
|
+
iterate.forEach(rule(context), (result) => {
|
|
1109
|
+
if (result.valid) return;
|
|
1110
|
+
const {
|
|
1111
|
+
tag,
|
|
1112
|
+
props: { role }
|
|
1113
|
+
} = context;
|
|
1114
|
+
const { message, attribute, severity } = result;
|
|
1115
|
+
const resolvedMessage = message ?? result.diagnostic?.message;
|
|
1116
|
+
const fallbackDiag = resolvedMessage == null ? AriaDiagnostics.invalidRole(role, tag) : void 0;
|
|
1117
|
+
violations.push({
|
|
1118
|
+
message: resolvedMessage ?? fallbackDiag.message,
|
|
1119
|
+
tag,
|
|
1120
|
+
role,
|
|
1121
|
+
attribute,
|
|
1122
|
+
severity,
|
|
1123
|
+
phase: "evaluate",
|
|
1124
|
+
...result.diagnostic != null && { diagnostic: result.diagnostic },
|
|
1125
|
+
...fallbackDiag != null && { diagnostic: fallbackDiag }
|
|
1126
|
+
});
|
|
1127
|
+
if (result.fixable) fixes.push(result.fix);
|
|
1128
|
+
});
|
|
1129
|
+
});
|
|
781
1130
|
return { violations, fixes };
|
|
782
1131
|
}
|
|
783
1132
|
static #getRules(context) {
|
|
784
|
-
|
|
1133
|
+
if (_AriaPolicyEngine.#hasRole(context.props) || context.effectiveRole != null && _AriaPolicyEngine.#LIVE_REGION_ROLES.has(context.effectiveRole)) {
|
|
1134
|
+
return _AriaPolicyEngine.#pipeline;
|
|
1135
|
+
}
|
|
1136
|
+
return _AriaPolicyEngine.#implicitOnlyRules;
|
|
785
1137
|
}
|
|
786
1138
|
static evaluate(tag, props) {
|
|
787
1139
|
const derived = _AriaPolicyEngine.#deriveContext(tag, props);
|
|
@@ -806,10 +1158,11 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
806
1158
|
return { props: next, violations };
|
|
807
1159
|
}
|
|
808
1160
|
report(violations) {
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
1161
|
+
iterate.forEach(violations, (v) => {
|
|
1162
|
+
const d = v.diagnostic ?? AriaDiagnostics.fromViolation(v);
|
|
1163
|
+
if (v.severity === "error") this.violate(d);
|
|
1164
|
+
else this.warn(d);
|
|
1165
|
+
});
|
|
813
1166
|
}
|
|
814
1167
|
// Cache key covers only the aria-relevant subset of props (tag + role + aria-* attrs).
|
|
815
1168
|
// Non-aria props (className, onClick, etc.) do not affect ARIA decisions and are excluded
|
|
@@ -821,27 +1174,26 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
821
1174
|
if (!isIntrinsicTag(tag)) return null;
|
|
822
1175
|
const parts = [tag];
|
|
823
1176
|
if (typeof props.role === "string") parts.push(`role:${props.role}`);
|
|
1177
|
+
if (tag === "input" && typeof props.type === "string") parts.push(`type:${props.type}`);
|
|
1178
|
+
if (tag === "img") parts.push(`alt:${props.alt === "" ? "empty" : "present"}`);
|
|
824
1179
|
const ariaEntries = [];
|
|
825
|
-
|
|
826
|
-
if (!
|
|
827
|
-
|
|
828
|
-
if (!isString(v) && !isNumber(v) && typeof v !== "boolean") continue;
|
|
1180
|
+
iterate.forEachEntry(props, (k, v) => {
|
|
1181
|
+
if (!k.startsWith("aria-")) return;
|
|
1182
|
+
if (!isString(v) && !isNumber(v) && typeof v !== "boolean") return;
|
|
829
1183
|
ariaEntries.push(`${k}:${String(v)}`);
|
|
830
|
-
}
|
|
1184
|
+
});
|
|
831
1185
|
if (ariaEntries.length > 0) parts.push(...ariaEntries.sort());
|
|
832
1186
|
return parts.join("|");
|
|
833
1187
|
}
|
|
834
1188
|
static #computePlan(inputProps, resultProps) {
|
|
835
1189
|
const removals = /* @__PURE__ */ new Set();
|
|
836
1190
|
const updates = {};
|
|
837
|
-
|
|
838
|
-
if (
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
if (!Object.hasOwn(resultProps, key)) continue;
|
|
842
|
-
const resultVal = resultProps[key];
|
|
1191
|
+
iterate.forEachKey(inputProps, (key) => {
|
|
1192
|
+
if (!(key in resultProps)) removals.add(key);
|
|
1193
|
+
});
|
|
1194
|
+
iterate.forEachEntry(resultProps, (key, resultVal) => {
|
|
843
1195
|
if (inputProps[key] !== resultVal) updates[key] = resultVal;
|
|
844
|
-
}
|
|
1196
|
+
});
|
|
845
1197
|
return { removals, updates };
|
|
846
1198
|
}
|
|
847
1199
|
static #applyPlan(props, removals, updates) {
|
|
@@ -849,15 +1201,15 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
849
1201
|
const hasUpdates = Object.keys(updates).length > 0;
|
|
850
1202
|
if (!hasRemovals && !hasUpdates) return props;
|
|
851
1203
|
const next = {};
|
|
852
|
-
|
|
853
|
-
if (
|
|
854
|
-
}
|
|
1204
|
+
iterate.forEachEntry(props, (k, v) => {
|
|
1205
|
+
if (!removals.has(k)) next[k] = v;
|
|
1206
|
+
});
|
|
855
1207
|
Object.assign(next, updates);
|
|
856
1208
|
return next;
|
|
857
1209
|
}
|
|
858
1210
|
validate(tag, props) {
|
|
859
1211
|
const key = _AriaPolicyEngine.#createPlanKey(tag, props);
|
|
860
|
-
if (!
|
|
1212
|
+
if (!isNull(key)) {
|
|
861
1213
|
const cached = this.#planCache.get(key);
|
|
862
1214
|
if (cached !== void 0) {
|
|
863
1215
|
this.#planCache.delete(key);
|
|
@@ -871,7 +1223,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
871
1223
|
}
|
|
872
1224
|
const result = this.#extraRules.length ? _AriaPolicyEngine.#evaluateWithRules(tag, props, this.#extraRules) : _AriaPolicyEngine.evaluate(tag, props);
|
|
873
1225
|
if (result.violations.length > 0) this.report(result.violations);
|
|
874
|
-
if (!
|
|
1226
|
+
if (!isNull(key)) {
|
|
875
1227
|
const { removals, updates } = _AriaPolicyEngine.#computePlan(
|
|
876
1228
|
props,
|
|
877
1229
|
result.props
|
|
@@ -892,12 +1244,12 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
892
1244
|
if (fixes.length === 0) return props;
|
|
893
1245
|
const sorted = [...fixes].sort((a, b) => (a.priority ?? Infinity) - (b.priority ?? Infinity));
|
|
894
1246
|
let next = props;
|
|
895
|
-
|
|
1247
|
+
iterate.forEach(sorted, ({ apply }) => {
|
|
896
1248
|
const effectiveRole = next.role ?? implicitRole;
|
|
897
1249
|
const fixContext = { tag, implicitRole, effectiveRole, props: next };
|
|
898
1250
|
const fixResult = apply(fixContext);
|
|
899
1251
|
if (fixResult.applied) next = fixResult.next;
|
|
900
|
-
}
|
|
1252
|
+
});
|
|
901
1253
|
return next;
|
|
902
1254
|
}
|
|
903
1255
|
static #removeRole = {
|
|
@@ -925,10 +1277,26 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
925
1277
|
_AriaPolicyEngine.#checkInvalidRoleOverride,
|
|
926
1278
|
_AriaPolicyEngine.#checkRedundantRole,
|
|
927
1279
|
_AriaPolicyEngine.#checkStandaloneRegion,
|
|
1280
|
+
_AriaPolicyEngine.#checkAriaAttributeValues,
|
|
928
1281
|
_AriaPolicyEngine.#checkInvalidAriaAttributes,
|
|
1282
|
+
_AriaPolicyEngine.#checkRequiredAriaProperties,
|
|
1283
|
+
_AriaPolicyEngine.#checkNameRequiredRoles,
|
|
1284
|
+
_AriaPolicyEngine.#checkRedundantAriaLevel,
|
|
929
1285
|
_AriaPolicyEngine.#checkMissingLiveRegion,
|
|
930
1286
|
_AriaPolicyEngine.#checkMissingAtomic,
|
|
931
|
-
_AriaPolicyEngine.#checkInvalidAriaRelevant
|
|
1287
|
+
_AriaPolicyEngine.#checkInvalidAriaRelevant,
|
|
1288
|
+
_AriaPolicyEngine.#checkAriaHiddenOnFocusable,
|
|
1289
|
+
_AriaPolicyEngine.#checkPresentationalAriaAttributes
|
|
1290
|
+
];
|
|
1291
|
+
// Rules for elements with an implicit role but no explicit role (not a live region).
|
|
1292
|
+
static #implicitOnlyRules = [
|
|
1293
|
+
_AriaPolicyEngine.#checkAriaAttributeValues,
|
|
1294
|
+
_AriaPolicyEngine.#checkInvalidAriaAttributes,
|
|
1295
|
+
_AriaPolicyEngine.#checkRequiredAriaProperties,
|
|
1296
|
+
_AriaPolicyEngine.#checkNameRequiredRoles,
|
|
1297
|
+
_AriaPolicyEngine.#checkRedundantAriaLevel,
|
|
1298
|
+
_AriaPolicyEngine.#checkAriaHiddenOnFocusable,
|
|
1299
|
+
_AriaPolicyEngine.#checkPresentationalAriaAttributes
|
|
932
1300
|
];
|
|
933
1301
|
static #checkInvalidRoleOverride({
|
|
934
1302
|
tag,
|
|
@@ -944,7 +1312,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
944
1312
|
fixable: true,
|
|
945
1313
|
severity: "error",
|
|
946
1314
|
fix: _AriaPolicyEngine.#removeRole,
|
|
947
|
-
|
|
1315
|
+
diagnostic: HtmlDiagnostics.implicitRoleOverride(tag, implicitRole, role)
|
|
948
1316
|
}
|
|
949
1317
|
];
|
|
950
1318
|
}
|
|
@@ -956,47 +1324,304 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
956
1324
|
return [
|
|
957
1325
|
{
|
|
958
1326
|
valid: false,
|
|
959
|
-
fixable: true,
|
|
1327
|
+
fixable: true,
|
|
1328
|
+
severity: "warning",
|
|
1329
|
+
fix: _AriaPolicyEngine.#removeRole,
|
|
1330
|
+
diagnostic: HtmlDiagnostics.implicitRoleRedundant(tag, implicitRole)
|
|
1331
|
+
}
|
|
1332
|
+
];
|
|
1333
|
+
}
|
|
1334
|
+
static #checkStandaloneRegion({ tag, props, implicitRole }) {
|
|
1335
|
+
const role = props.role;
|
|
1336
|
+
if (role !== "region") return VALID;
|
|
1337
|
+
if (!isStandaloneTag(tag)) return VALID;
|
|
1338
|
+
return [
|
|
1339
|
+
{
|
|
1340
|
+
valid: false,
|
|
1341
|
+
fixable: true,
|
|
1342
|
+
severity: "error",
|
|
1343
|
+
fix: _AriaPolicyEngine.#removeRole,
|
|
1344
|
+
diagnostic: HtmlDiagnostics.standaloneRegionOverride(tag, implicitRole ?? tag)
|
|
1345
|
+
}
|
|
1346
|
+
];
|
|
1347
|
+
}
|
|
1348
|
+
static #checkInvalidAriaAttributes({
|
|
1349
|
+
tag,
|
|
1350
|
+
props,
|
|
1351
|
+
effectiveRole
|
|
1352
|
+
}) {
|
|
1353
|
+
if (effectiveRole === "none" || effectiveRole === "presentation") return VALID;
|
|
1354
|
+
const results = [];
|
|
1355
|
+
iterate.forEachEntry(props, (key) => {
|
|
1356
|
+
if (!key.startsWith("aria-")) return;
|
|
1357
|
+
if (isGlobalAriaAttribute(key)) return;
|
|
1358
|
+
if (isAriaAttributeValidForRole(key, effectiveRole)) return;
|
|
1359
|
+
results.push({
|
|
1360
|
+
valid: false,
|
|
1361
|
+
severity: "warning",
|
|
1362
|
+
fixable: true,
|
|
1363
|
+
attribute: key,
|
|
1364
|
+
diagnostic: AriaDiagnostics.attributeInvalid(key, effectiveRole ?? tag),
|
|
1365
|
+
fix: _AriaPolicyEngine.#makeRemoveAttributeFix(key)
|
|
1366
|
+
});
|
|
1367
|
+
});
|
|
1368
|
+
return results;
|
|
1369
|
+
}
|
|
1370
|
+
// ─── ARIA attribute value validation ──────────────────────────────────────
|
|
1371
|
+
// Accepted value shapes for typed ARIA attributes.
|
|
1372
|
+
// Attributes not in this map are unconstrained (arbitrary string values permitted).
|
|
1373
|
+
static #ARIA_VALUE_TYPES = /* @__PURE__ */ new Map([
|
|
1374
|
+
// Boolean (true | false)
|
|
1375
|
+
["aria-atomic", { kind: "boolean" }],
|
|
1376
|
+
["aria-busy", { kind: "boolean" }],
|
|
1377
|
+
["aria-disabled", { kind: "boolean" }],
|
|
1378
|
+
["aria-expanded", { kind: "boolean" }],
|
|
1379
|
+
["aria-hidden", { kind: "boolean" }],
|
|
1380
|
+
["aria-modal", { kind: "boolean" }],
|
|
1381
|
+
["aria-multiline", { kind: "boolean" }],
|
|
1382
|
+
["aria-multiselectable", { kind: "boolean" }],
|
|
1383
|
+
["aria-readonly", { kind: "boolean" }],
|
|
1384
|
+
["aria-required", { kind: "boolean" }],
|
|
1385
|
+
["aria-selected", { kind: "boolean" }],
|
|
1386
|
+
// Tristate (true | false | mixed)
|
|
1387
|
+
["aria-checked", { kind: "tristate" }],
|
|
1388
|
+
["aria-pressed", { kind: "tristate" }],
|
|
1389
|
+
// Numeric (any finite number)
|
|
1390
|
+
["aria-valuenow", { kind: "number" }],
|
|
1391
|
+
["aria-valuemin", { kind: "number" }],
|
|
1392
|
+
["aria-valuemax", { kind: "number" }],
|
|
1393
|
+
// Integer with optional range
|
|
1394
|
+
["aria-level", { kind: "integer", min: 1, max: 6 }],
|
|
1395
|
+
["aria-posinset", { kind: "integer", min: 1 }],
|
|
1396
|
+
["aria-setsize", { kind: "integer", min: -1 }],
|
|
1397
|
+
["aria-rowcount", { kind: "integer", min: -1 }],
|
|
1398
|
+
["aria-colcount", { kind: "integer", min: -1 }],
|
|
1399
|
+
["aria-rowindex", { kind: "integer", min: 1 }],
|
|
1400
|
+
["aria-colindex", { kind: "integer", min: 1 }],
|
|
1401
|
+
["aria-rowspan", { kind: "integer", min: 0 }],
|
|
1402
|
+
["aria-colspan", { kind: "integer", min: 0 }],
|
|
1403
|
+
// Enum (specific allowed tokens)
|
|
1404
|
+
["aria-autocomplete", { kind: "enum", values: /* @__PURE__ */ new Set(["inline", "list", "both", "none"]) }],
|
|
1405
|
+
[
|
|
1406
|
+
"aria-current",
|
|
1407
|
+
{
|
|
1408
|
+
kind: "enum",
|
|
1409
|
+
values: /* @__PURE__ */ new Set(["page", "step", "location", "date", "time", "true", "false"])
|
|
1410
|
+
}
|
|
1411
|
+
],
|
|
1412
|
+
[
|
|
1413
|
+
"aria-haspopup",
|
|
1414
|
+
{
|
|
1415
|
+
kind: "enum",
|
|
1416
|
+
values: /* @__PURE__ */ new Set(["false", "true", "menu", "listbox", "tree", "grid", "dialog"])
|
|
1417
|
+
}
|
|
1418
|
+
],
|
|
1419
|
+
["aria-invalid", { kind: "enum", values: /* @__PURE__ */ new Set(["grammar", "false", "spelling", "true"]) }],
|
|
1420
|
+
["aria-live", { kind: "enum", values: /* @__PURE__ */ new Set(["assertive", "off", "polite"]) }],
|
|
1421
|
+
[
|
|
1422
|
+
"aria-orientation",
|
|
1423
|
+
{ kind: "enum", values: /* @__PURE__ */ new Set(["horizontal", "vertical", "undefined"]) }
|
|
1424
|
+
],
|
|
1425
|
+
["aria-sort", { kind: "enum", values: /* @__PURE__ */ new Set(["ascending", "descending", "none", "other"]) }]
|
|
1426
|
+
]);
|
|
1427
|
+
static #isValidAriaValue(value, type) {
|
|
1428
|
+
switch (type.kind) {
|
|
1429
|
+
case "boolean":
|
|
1430
|
+
return value === "true" || value === "false" || value === true || value === false;
|
|
1431
|
+
case "tristate":
|
|
1432
|
+
return value === "true" || value === "false" || value === "mixed" || value === true || value === false;
|
|
1433
|
+
case "number": {
|
|
1434
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
1435
|
+
if (typeof value !== "string") return false;
|
|
1436
|
+
const n = parseFloat(value);
|
|
1437
|
+
return Number.isFinite(n);
|
|
1438
|
+
}
|
|
1439
|
+
case "integer": {
|
|
1440
|
+
const n = typeof value === "number" ? value : typeof value === "string" ? parseInt(value, 10) : NaN;
|
|
1441
|
+
if (!Number.isFinite(n) || !Number.isInteger(n)) return false;
|
|
1442
|
+
if (type.min !== void 0 && n < type.min) return false;
|
|
1443
|
+
if (type.max !== void 0 && n > type.max) return false;
|
|
1444
|
+
return true;
|
|
1445
|
+
}
|
|
1446
|
+
case "enum":
|
|
1447
|
+
return typeof value === "string" && type.values.has(value);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
static #describeExpected(type) {
|
|
1451
|
+
switch (type.kind) {
|
|
1452
|
+
case "boolean":
|
|
1453
|
+
return '"true" or "false"';
|
|
1454
|
+
case "tristate":
|
|
1455
|
+
return '"true", "false", or "mixed"';
|
|
1456
|
+
case "number":
|
|
1457
|
+
return "a finite number";
|
|
1458
|
+
case "integer": {
|
|
1459
|
+
const parts = ["an integer"];
|
|
1460
|
+
if (type.min !== void 0 && type.max !== void 0)
|
|
1461
|
+
parts.push(`between ${type.min} and ${type.max}`);
|
|
1462
|
+
else if (type.min !== void 0) parts.push(`\u2265 ${type.min}`);
|
|
1463
|
+
else if (type.max !== void 0) parts.push(`\u2264 ${type.max}`);
|
|
1464
|
+
return parts.join(" ");
|
|
1465
|
+
}
|
|
1466
|
+
case "enum":
|
|
1467
|
+
return [...type.values].map((v) => `"${v}"`).join(", ");
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
static #checkAriaAttributeValues({ props, effectiveRole }) {
|
|
1471
|
+
if (effectiveRole === "none" || effectiveRole === "presentation") return VALID;
|
|
1472
|
+
const results = [];
|
|
1473
|
+
iterate.forEachEntry(props, (key, value) => {
|
|
1474
|
+
if (!key.startsWith("aria-")) return;
|
|
1475
|
+
const type = _AriaPolicyEngine.#ARIA_VALUE_TYPES.get(key);
|
|
1476
|
+
if (type == null) return;
|
|
1477
|
+
if (_AriaPolicyEngine.#isValidAriaValue(value, type)) return;
|
|
1478
|
+
results.push({
|
|
1479
|
+
valid: false,
|
|
1480
|
+
fixable: true,
|
|
1481
|
+
severity: "warning",
|
|
1482
|
+
attribute: key,
|
|
1483
|
+
diagnostic: AriaDiagnostics.invalidAttributeValue(
|
|
1484
|
+
key,
|
|
1485
|
+
value,
|
|
1486
|
+
_AriaPolicyEngine.#describeExpected(type)
|
|
1487
|
+
),
|
|
1488
|
+
fix: _AriaPolicyEngine.#makeRemoveAttributeFix(key)
|
|
1489
|
+
});
|
|
1490
|
+
});
|
|
1491
|
+
return results;
|
|
1492
|
+
}
|
|
1493
|
+
// ─── Heading implicit level ────────────────────────────────────────────────
|
|
1494
|
+
static #HEADING_IMPLICIT_LEVELS = /* @__PURE__ */ new Map([
|
|
1495
|
+
["h1", 1],
|
|
1496
|
+
["h2", 2],
|
|
1497
|
+
["h3", 3],
|
|
1498
|
+
["h4", 4],
|
|
1499
|
+
["h5", 5],
|
|
1500
|
+
["h6", 6]
|
|
1501
|
+
]);
|
|
1502
|
+
static #checkRedundantAriaLevel({
|
|
1503
|
+
tag,
|
|
1504
|
+
props,
|
|
1505
|
+
effectiveRole
|
|
1506
|
+
}) {
|
|
1507
|
+
if (effectiveRole === "none" || effectiveRole === "presentation") return VALID;
|
|
1508
|
+
const implicitLevel = _AriaPolicyEngine.#HEADING_IMPLICIT_LEVELS.get(tag);
|
|
1509
|
+
if (implicitLevel == null) return VALID;
|
|
1510
|
+
const raw = props["aria-level"];
|
|
1511
|
+
if (raw == null) return VALID;
|
|
1512
|
+
const n = typeof raw === "number" ? raw : typeof raw === "string" ? parseInt(raw, 10) : NaN;
|
|
1513
|
+
if (!Number.isFinite(n) || n !== implicitLevel) return VALID;
|
|
1514
|
+
return [
|
|
1515
|
+
{
|
|
1516
|
+
valid: false,
|
|
1517
|
+
fixable: true,
|
|
1518
|
+
severity: "warning",
|
|
1519
|
+
attribute: "aria-level",
|
|
1520
|
+
diagnostic: AriaDiagnostics.redundantAriaLevel(tag, implicitLevel),
|
|
1521
|
+
fix: _AriaPolicyEngine.#makeRemoveAttributeFix("aria-level")
|
|
1522
|
+
}
|
|
1523
|
+
];
|
|
1524
|
+
}
|
|
1525
|
+
// ─── Name-required roles ───────────────────────────────────────────────────
|
|
1526
|
+
// Roles that always require an accessible name per WAI-ARIA APG.
|
|
1527
|
+
// Dialog and landmark names are enforced via contracts (ariaContract) rather than
|
|
1528
|
+
// the built-in pipeline so consumers can opt in; img is built in because role=img
|
|
1529
|
+
// on any element (including bare <img>) is definitionally useless without a name.
|
|
1530
|
+
static #NAME_REQUIRED_ROLES = /* @__PURE__ */ new Set(["img"]);
|
|
1531
|
+
static #checkNameRequiredRoles({
|
|
1532
|
+
tag,
|
|
1533
|
+
props,
|
|
1534
|
+
effectiveRole
|
|
1535
|
+
}) {
|
|
1536
|
+
if (!effectiveRole || !_AriaPolicyEngine.#NAME_REQUIRED_ROLES.has(effectiveRole)) return VALID;
|
|
1537
|
+
if ("aria-label" in props || "aria-labelledby" in props) return VALID;
|
|
1538
|
+
if (tag === "img" && typeof props.alt === "string" && props.alt.length > 0) return VALID;
|
|
1539
|
+
return [
|
|
1540
|
+
{
|
|
1541
|
+
valid: false,
|
|
1542
|
+
fixable: false,
|
|
960
1543
|
severity: "warning",
|
|
961
|
-
|
|
962
|
-
message: `<${tag}> already has implicit role="${implicitRole}". Avoid redundant role assignment.`
|
|
1544
|
+
diagnostic: AriaDiagnostics.missingAccessibleName(tag)
|
|
963
1545
|
}
|
|
964
1546
|
];
|
|
965
1547
|
}
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1548
|
+
// WAI-ARIA 1.2 required states and properties, keyed by role.
|
|
1549
|
+
// Source: https://www.w3.org/TR/wai-aria-1.2/#requiredState
|
|
1550
|
+
static #REQUIRED_PROPERTIES = /* @__PURE__ */ new Map([
|
|
1551
|
+
["combobox", ["aria-expanded"]],
|
|
1552
|
+
["option", ["aria-selected"]],
|
|
1553
|
+
["slider", ["aria-valuenow"]],
|
|
1554
|
+
["scrollbar", ["aria-controls", "aria-valuenow"]],
|
|
1555
|
+
["spinbutton", ["aria-valuenow"]]
|
|
1556
|
+
]);
|
|
1557
|
+
static #checkRequiredAriaProperties({
|
|
1558
|
+
props,
|
|
1559
|
+
effectiveRole
|
|
1560
|
+
}) {
|
|
1561
|
+
if (!effectiveRole) return VALID;
|
|
1562
|
+
const required = _AriaPolicyEngine.#REQUIRED_PROPERTIES.get(effectiveRole);
|
|
1563
|
+
if (required == null) return VALID;
|
|
1564
|
+
const results = [];
|
|
1565
|
+
iterate.forEach(required, (attr) => {
|
|
1566
|
+
if (attr in props) return;
|
|
1567
|
+
results.push({
|
|
1568
|
+
valid: false,
|
|
1569
|
+
fixable: false,
|
|
1570
|
+
severity: "warning",
|
|
1571
|
+
attribute: attr,
|
|
1572
|
+
diagnostic: AriaDiagnostics.requiredProperty(attr, effectiveRole)
|
|
1573
|
+
});
|
|
1574
|
+
});
|
|
1575
|
+
return results;
|
|
1576
|
+
}
|
|
1577
|
+
// Natively interactive HTML elements — always keyboard-reachable unless explicitly disabled.
|
|
1578
|
+
static #INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
|
|
1579
|
+
"a",
|
|
1580
|
+
"button",
|
|
1581
|
+
"input",
|
|
1582
|
+
"select",
|
|
1583
|
+
"textarea"
|
|
1584
|
+
]);
|
|
1585
|
+
// WAI-ARIA 1.2 §6.6: aria-hidden="true" must not be placed on focusable elements.
|
|
1586
|
+
static #checkAriaHiddenOnFocusable({ tag, props }) {
|
|
1587
|
+
if (props["aria-hidden"] !== "true" && props["aria-hidden"] !== true) return VALID;
|
|
1588
|
+
const isInteractive = _AriaPolicyEngine.#INTERACTIVE_TAGS.has(tag);
|
|
1589
|
+
if (!isInteractive) {
|
|
1590
|
+
const tabindex = props.tabindex;
|
|
1591
|
+
const n = typeof tabindex === "number" ? tabindex : typeof tabindex === "string" ? parseInt(tabindex, 10) : NaN;
|
|
1592
|
+
if (!Number.isFinite(n) || n < 0) return VALID;
|
|
1593
|
+
}
|
|
970
1594
|
return [
|
|
971
1595
|
{
|
|
972
1596
|
valid: false,
|
|
973
|
-
fixable:
|
|
1597
|
+
fixable: false,
|
|
974
1598
|
severity: "error",
|
|
975
|
-
|
|
976
|
-
|
|
1599
|
+
attribute: "aria-hidden",
|
|
1600
|
+
diagnostic: AriaDiagnostics.ariaHiddenOnFocusable(tag)
|
|
977
1601
|
}
|
|
978
1602
|
];
|
|
979
1603
|
}
|
|
980
|
-
|
|
1604
|
+
// Presentational elements (role=none/presentation, including <img alt="">) are removed
|
|
1605
|
+
// from the accessibility tree — ARIA attributes on them are meaningless and misleading.
|
|
1606
|
+
static #checkPresentationalAriaAttributes({
|
|
981
1607
|
tag,
|
|
982
1608
|
props,
|
|
983
1609
|
effectiveRole
|
|
984
1610
|
}) {
|
|
1611
|
+
if (effectiveRole !== "none" && effectiveRole !== "presentation") return VALID;
|
|
985
1612
|
const results = [];
|
|
986
|
-
|
|
987
|
-
if (!
|
|
988
|
-
if (
|
|
989
|
-
if (isGlobalAriaAttribute(key)) continue;
|
|
990
|
-
if (isAriaAttributeValidForRole(key, effectiveRole)) continue;
|
|
1613
|
+
iterate.forEachEntry(props, (key) => {
|
|
1614
|
+
if (!key.startsWith("aria-")) return;
|
|
1615
|
+
if (key === "aria-hidden") return;
|
|
991
1616
|
results.push({
|
|
992
1617
|
valid: false,
|
|
993
|
-
severity: "warning",
|
|
994
1618
|
fixable: true,
|
|
1619
|
+
severity: "warning",
|
|
995
1620
|
attribute: key,
|
|
996
|
-
|
|
1621
|
+
diagnostic: AriaDiagnostics.attributeOnPresentational(key, tag),
|
|
997
1622
|
fix: _AriaPolicyEngine.#makeRemoveAttributeFix(key)
|
|
998
1623
|
});
|
|
999
|
-
}
|
|
1624
|
+
});
|
|
1000
1625
|
return results;
|
|
1001
1626
|
}
|
|
1002
1627
|
// WAI-ARIA live region roles and their implied aria-live politeness values.
|
|
@@ -1025,7 +1650,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
1025
1650
|
fixable: true,
|
|
1026
1651
|
severity: "warning",
|
|
1027
1652
|
fix: injectLive,
|
|
1028
|
-
|
|
1653
|
+
diagnostic: AriaDiagnostics.missingLiveRegion(effectiveRole, impliedLive)
|
|
1029
1654
|
}
|
|
1030
1655
|
];
|
|
1031
1656
|
}
|
|
@@ -1037,7 +1662,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
1037
1662
|
valid: false,
|
|
1038
1663
|
fixable: false,
|
|
1039
1664
|
severity: "warning",
|
|
1040
|
-
|
|
1665
|
+
diagnostic: AriaDiagnostics.missingAtomic(effectiveRole)
|
|
1041
1666
|
}
|
|
1042
1667
|
];
|
|
1043
1668
|
}
|
|
@@ -1066,7 +1691,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
1066
1691
|
fixable: true,
|
|
1067
1692
|
severity: "warning",
|
|
1068
1693
|
attribute: "aria-relevant",
|
|
1069
|
-
|
|
1694
|
+
diagnostic: AriaDiagnostics.relevantInvalidTokens(invalid),
|
|
1070
1695
|
fix: _AriaPolicyEngine.#makeRemoveAttributeFix("aria-relevant")
|
|
1071
1696
|
}
|
|
1072
1697
|
];
|
|
@@ -1078,7 +1703,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
1078
1703
|
fixable: true,
|
|
1079
1704
|
severity: "warning",
|
|
1080
1705
|
attribute: "aria-relevant",
|
|
1081
|
-
|
|
1706
|
+
diagnostic: AriaDiagnostics.relevantSuperseded(),
|
|
1082
1707
|
fix: _AriaPolicyEngine.#normalizeRelevantAllFix
|
|
1083
1708
|
}
|
|
1084
1709
|
];
|
|
@@ -1086,6 +1711,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends StrictBase {
|
|
|
1086
1711
|
return VALID;
|
|
1087
1712
|
}
|
|
1088
1713
|
};
|
|
1714
|
+
|
|
1715
|
+
// ../../lib/contract/src/children/get-type-name.ts
|
|
1089
1716
|
function getTypeName(value) {
|
|
1090
1717
|
if (value === null) return "null";
|
|
1091
1718
|
if (value === void 0) return "undefined";
|
|
@@ -1096,39 +1723,8 @@ function getTypeName(value) {
|
|
|
1096
1723
|
const name = value.constructor?.name;
|
|
1097
1724
|
return typeof name === "string" && name !== "Object" ? name : "object";
|
|
1098
1725
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
constructor(ctx = "") {
|
|
1102
|
-
this.#prefix = ctx ? `${ctx}:
|
|
1103
|
-
` : "";
|
|
1104
|
-
}
|
|
1105
|
-
#template(typeName, index, prefix = "", suffix = "") {
|
|
1106
|
-
const leadingStr = prefix ? `${prefix} ` : "";
|
|
1107
|
-
const followingStr = suffix ? ` ${suffix}` : "";
|
|
1108
|
-
return `${leadingStr}child "${typeName}" at index ${index}${followingStr}.`;
|
|
1109
|
-
}
|
|
1110
|
-
unexpectedChild(typeName, index) {
|
|
1111
|
-
return this.#template(typeName, index, "unexpected");
|
|
1112
|
-
}
|
|
1113
|
-
multipleMatches(typeName, index, ruleNames) {
|
|
1114
|
-
const quoted = ruleNames.map((n) => `"${n}"`);
|
|
1115
|
-
return this.#template(
|
|
1116
|
-
typeName,
|
|
1117
|
-
index,
|
|
1118
|
-
"",
|
|
1119
|
-
`matches multiple child rules: ${quoted.join(" and ")}`
|
|
1120
|
-
);
|
|
1121
|
-
}
|
|
1122
|
-
#format(errors) {
|
|
1123
|
-
return this.#prefix + errors.join("\n");
|
|
1124
|
-
}
|
|
1125
|
-
toError(errors) {
|
|
1126
|
-
if (errors.length === 0) {
|
|
1127
|
-
return new Error(this.#prefix + "Unknown validation error.");
|
|
1128
|
-
}
|
|
1129
|
-
return new Error(this.#format(errors));
|
|
1130
|
-
}
|
|
1131
|
-
};
|
|
1726
|
+
|
|
1727
|
+
// ../../lib/contract/src/children/normalize-child-rule.ts
|
|
1132
1728
|
function normalizeCardinality(input, impliesSingleton) {
|
|
1133
1729
|
const min = input?.min ?? 0;
|
|
1134
1730
|
const max = input?.max ?? (impliesSingleton ? 1 : Infinity);
|
|
@@ -1153,6 +1749,8 @@ function normalizeChildRule(rule) {
|
|
|
1153
1749
|
cardinality: normalizeCardinality(rule.cardinality, impliesSingleton)
|
|
1154
1750
|
};
|
|
1155
1751
|
}
|
|
1752
|
+
|
|
1753
|
+
// ../../lib/contract/src/children/rules-matcher.ts
|
|
1156
1754
|
function getChildType(child) {
|
|
1157
1755
|
if (!isObject(child) || !("type" in child)) return void 0;
|
|
1158
1756
|
return child.type;
|
|
@@ -1161,8 +1759,8 @@ function buildPartialIndex(rules) {
|
|
|
1161
1759
|
const typeIndex = /* @__PURE__ */ new Map();
|
|
1162
1760
|
const duplicateTypes = /* @__PURE__ */ new Set();
|
|
1163
1761
|
const untypedIndices = [];
|
|
1164
|
-
|
|
1165
|
-
const t =
|
|
1762
|
+
iterate.forEach(rules, (rule, ri) => {
|
|
1763
|
+
const t = rule.type;
|
|
1166
1764
|
if (t === void 0) {
|
|
1167
1765
|
untypedIndices.push(ri);
|
|
1168
1766
|
} else if (typeIndex.has(t)) {
|
|
@@ -1170,12 +1768,14 @@ function buildPartialIndex(rules) {
|
|
|
1170
1768
|
} else {
|
|
1171
1769
|
typeIndex.set(t, ri);
|
|
1172
1770
|
}
|
|
1173
|
-
}
|
|
1771
|
+
});
|
|
1174
1772
|
if (duplicateTypes.size > 0) {
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1773
|
+
iterate.forEachSet(duplicateTypes, (t) => {
|
|
1774
|
+
typeIndex.delete(t);
|
|
1775
|
+
});
|
|
1776
|
+
iterate.forEach(rules, (rule, ri) => {
|
|
1777
|
+
if (duplicateTypes.has(rule.type)) untypedIndices.push(ri);
|
|
1778
|
+
});
|
|
1179
1779
|
}
|
|
1180
1780
|
return { typeIndex, untypedIndices };
|
|
1181
1781
|
}
|
|
@@ -1194,10 +1794,10 @@ var RuleMatcher = class {
|
|
|
1194
1794
|
const reverse = /* @__PURE__ */ new Map();
|
|
1195
1795
|
const unexpectedIndices = /* @__PURE__ */ new Set();
|
|
1196
1796
|
const ambiguousIndices = /* @__PURE__ */ new Set();
|
|
1197
|
-
|
|
1797
|
+
iterate.forEach(this.#rules, (_, ri) => {
|
|
1198
1798
|
reverse.set(ri, /* @__PURE__ */ new Set());
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1799
|
+
});
|
|
1800
|
+
iterate.forEach(children, (child, ci) => {
|
|
1201
1801
|
const t = getChildType(child);
|
|
1202
1802
|
if (t !== void 0) {
|
|
1203
1803
|
const ri = this.#typeIndex.get(t);
|
|
@@ -1211,8 +1811,8 @@ var RuleMatcher = class {
|
|
|
1211
1811
|
reverse.get(ri).add(ci);
|
|
1212
1812
|
}
|
|
1213
1813
|
}
|
|
1214
|
-
|
|
1215
|
-
if (!this.#rules[ri].match(child))
|
|
1814
|
+
iterate.forEach(this.#untypedIndices, (ri) => {
|
|
1815
|
+
if (!this.#rules[ri].match(child)) return;
|
|
1216
1816
|
let childEntry = forward.get(ci);
|
|
1217
1817
|
if (!childEntry) {
|
|
1218
1818
|
childEntry = /* @__PURE__ */ new Set();
|
|
@@ -1220,33 +1820,35 @@ var RuleMatcher = class {
|
|
|
1220
1820
|
}
|
|
1221
1821
|
childEntry.add(ri);
|
|
1222
1822
|
reverse.get(ri).add(ci);
|
|
1223
|
-
}
|
|
1823
|
+
});
|
|
1224
1824
|
const entry = forward.get(ci);
|
|
1225
1825
|
if (!entry) {
|
|
1226
1826
|
unexpectedIndices.add(ci);
|
|
1227
1827
|
} else if (entry.size > 1) {
|
|
1228
1828
|
ambiguousIndices.add(ci);
|
|
1229
1829
|
}
|
|
1230
|
-
}
|
|
1830
|
+
});
|
|
1231
1831
|
return { matrix: { childToRules: { forward, reverse } }, unexpectedIndices, ambiguousIndices };
|
|
1232
1832
|
}
|
|
1233
1833
|
};
|
|
1234
|
-
|
|
1834
|
+
|
|
1835
|
+
// ../../lib/contract/src/children/rule-validator.ts
|
|
1836
|
+
var RuleValidator = class _RuleValidator extends InvariantBase {
|
|
1235
1837
|
#context;
|
|
1236
|
-
constructor(context,
|
|
1237
|
-
super(
|
|
1838
|
+
constructor(context, diagnostics) {
|
|
1839
|
+
super(diagnostics);
|
|
1238
1840
|
this.#context = context;
|
|
1239
1841
|
}
|
|
1240
1842
|
validate(rules, matrix, childCount) {
|
|
1241
1843
|
const firstIndex = 0;
|
|
1242
1844
|
const lastIndex = childCount - 1;
|
|
1243
|
-
|
|
1845
|
+
iterate.forEach(rules, (rule, ri) => {
|
|
1244
1846
|
const matches = matrix.childToRules.reverse.get(ri);
|
|
1245
1847
|
const matchCount = matches.size;
|
|
1246
1848
|
this.#validateCardinality(rule, matchCount);
|
|
1247
|
-
if (matchCount === 0)
|
|
1849
|
+
if (matchCount === 0) return;
|
|
1248
1850
|
this.#validatePositions(rule, matches, firstIndex, lastIndex);
|
|
1249
|
-
}
|
|
1851
|
+
});
|
|
1250
1852
|
}
|
|
1251
1853
|
#validateCardinality(rule, matchCount) {
|
|
1252
1854
|
const { cardinality, name } = rule;
|
|
@@ -1255,21 +1857,21 @@ var RuleValidator = class _RuleValidator extends StrictBase {
|
|
|
1255
1857
|
}
|
|
1256
1858
|
const { min, max } = cardinality;
|
|
1257
1859
|
if (matchCount < min) {
|
|
1258
|
-
this.violate(
|
|
1860
|
+
this.violate(ContractDiagnostics.cardinalityMin(name, min, this.#context));
|
|
1259
1861
|
return;
|
|
1260
1862
|
}
|
|
1261
1863
|
if (matchCount > max) {
|
|
1262
|
-
this.violate(
|
|
1864
|
+
this.violate(ContractDiagnostics.cardinalityMax(name, max, this.#context));
|
|
1263
1865
|
}
|
|
1264
1866
|
}
|
|
1265
1867
|
#validatePositions(rule, matches, firstIndex, lastIndex) {
|
|
1266
1868
|
const { name, position } = rule;
|
|
1267
|
-
|
|
1869
|
+
iterate.forEachSet(matches, (index) => {
|
|
1268
1870
|
if (_RuleValidator.#isValidPosition(index, position, firstIndex, lastIndex)) {
|
|
1269
|
-
|
|
1871
|
+
return;
|
|
1270
1872
|
}
|
|
1271
|
-
this.violate(
|
|
1272
|
-
}
|
|
1873
|
+
this.violate(ContractDiagnostics.positionViolation(name, position, index, this.#context));
|
|
1874
|
+
});
|
|
1273
1875
|
}
|
|
1274
1876
|
static #isValidPosition(matchIndex, position, firstIndex, lastIndex) {
|
|
1275
1877
|
switch (position) {
|
|
@@ -1284,48 +1886,50 @@ var RuleValidator = class _RuleValidator extends StrictBase {
|
|
|
1284
1886
|
}
|
|
1285
1887
|
}
|
|
1286
1888
|
};
|
|
1287
|
-
|
|
1889
|
+
|
|
1890
|
+
// ../../lib/contract/src/children/children-evaluator.ts
|
|
1891
|
+
var ChildrenEvaluator = class extends InvariantBase {
|
|
1892
|
+
#context;
|
|
1288
1893
|
#rules;
|
|
1289
1894
|
#ruleNames;
|
|
1290
1895
|
#matcher;
|
|
1291
1896
|
#ruleValidator;
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
this.#rules = rules.map((
|
|
1296
|
-
this.#ruleNames = this.#rules.map((
|
|
1297
|
-
|
|
1897
|
+
constructor(rules, diagnostics, context = "Component") {
|
|
1898
|
+
super(diagnostics);
|
|
1899
|
+
this.#context = context;
|
|
1900
|
+
this.#rules = rules.map((r) => normalizeChildRule(r));
|
|
1901
|
+
this.#ruleNames = this.#rules.map((r) => r.name);
|
|
1902
|
+
iterate.forEach(this.#rules, (rule) => {
|
|
1298
1903
|
const { name, position, cardinality } = rule;
|
|
1299
1904
|
if ((position === "first" || position === "last") && (cardinality.kind === "unbounded" || cardinality.max > 1)) {
|
|
1300
1905
|
throw new RangeError(
|
|
1301
1906
|
`ChildrenEvaluator [${context}]: rule "${name}" sets position="${position}" with an unbound or >1 max. position="first|last" implies max=1.`
|
|
1302
1907
|
);
|
|
1303
1908
|
}
|
|
1304
|
-
}
|
|
1909
|
+
});
|
|
1305
1910
|
this.#matcher = new RuleMatcher(this.#rules);
|
|
1306
|
-
this.#ruleValidator = new RuleValidator(context,
|
|
1307
|
-
this.#matchBuilder = new MatchValidationErrorBuilder(context);
|
|
1911
|
+
this.#ruleValidator = new RuleValidator(context, diagnostics);
|
|
1308
1912
|
}
|
|
1309
1913
|
evaluate(children) {
|
|
1310
|
-
if (!this.
|
|
1914
|
+
if (!this.active) return;
|
|
1311
1915
|
const { matrix, unexpectedIndices, ambiguousIndices } = this.#matcher.match(children);
|
|
1312
1916
|
this.#ruleValidator.validate(this.#rules, matrix, children.length);
|
|
1313
1917
|
if (unexpectedIndices.size === 0 && ambiguousIndices.size === 0) return;
|
|
1314
|
-
const errors = [];
|
|
1315
1918
|
const violating = [...unexpectedIndices, ...ambiguousIndices].sort((a, b) => a - b);
|
|
1316
|
-
|
|
1919
|
+
iterate.forEach(violating, (ci) => {
|
|
1317
1920
|
const typeName = getTypeName(children[ci]);
|
|
1318
1921
|
if (unexpectedIndices.has(ci)) {
|
|
1319
|
-
|
|
1922
|
+
this.violate(ContractDiagnostics.unexpectedChild(typeName, ci, this.#context));
|
|
1320
1923
|
} else {
|
|
1321
1924
|
const matches = matrix.childToRules.forward.get(ci);
|
|
1322
1925
|
const names = [...matches].map((ri) => this.#ruleNames[ri] ?? `#${ri}`);
|
|
1323
|
-
|
|
1926
|
+
this.violate(ContractDiagnostics.ambiguousChild(typeName, ci, names, this.#context));
|
|
1324
1927
|
}
|
|
1325
|
-
}
|
|
1326
|
-
this.invariant(errors.length === 0, this.#matchBuilder.toError(errors).message);
|
|
1928
|
+
});
|
|
1327
1929
|
}
|
|
1328
1930
|
};
|
|
1931
|
+
|
|
1932
|
+
// ../../lib/contract/src/props/get-disabled-props.ts
|
|
1329
1933
|
var disabledProps = ({
|
|
1330
1934
|
disabled,
|
|
1331
1935
|
"aria-disabled": ariaDisabled,
|
|
@@ -1337,6 +1941,8 @@ var disabledProps = ({
|
|
|
1337
1941
|
...dataDisabled === void 0 && { "data-disabled": "" }
|
|
1338
1942
|
};
|
|
1339
1943
|
};
|
|
1944
|
+
|
|
1945
|
+
// ../../lib/contract/src/props/get-invalid-props.ts
|
|
1340
1946
|
var invalidProps = ({
|
|
1341
1947
|
invalid,
|
|
1342
1948
|
"aria-invalid": ariaInvalid,
|
|
@@ -1348,6 +1954,8 @@ var invalidProps = ({
|
|
|
1348
1954
|
...dataInvalid === void 0 && { "data-invalid": "" }
|
|
1349
1955
|
};
|
|
1350
1956
|
};
|
|
1957
|
+
|
|
1958
|
+
// ../../lib/contract/src/props/get-readonly-props.ts
|
|
1351
1959
|
var readonlyProps = ({
|
|
1352
1960
|
readOnly,
|
|
1353
1961
|
"aria-readonly": ariaReadonly,
|
|
@@ -1363,6 +1971,8 @@ var readonlyProps = ({
|
|
|
1363
1971
|
}
|
|
1364
1972
|
};
|
|
1365
1973
|
};
|
|
1974
|
+
|
|
1975
|
+
// ../core/src/html/aria-rules.ts
|
|
1366
1976
|
var LANDMARK_TAG_SET = /* @__PURE__ */ new Set(["article", "aside", "footer", "header", "main", "nav"]);
|
|
1367
1977
|
var removeLandmarkRoleOverride = {
|
|
1368
1978
|
kind: "removeRole",
|
|
@@ -1382,14 +1992,31 @@ function landmarkRoleRule({ tag, props, implicitRole }) {
|
|
|
1382
1992
|
fixable: true,
|
|
1383
1993
|
severity: "error",
|
|
1384
1994
|
fix: removeLandmarkRoleOverride,
|
|
1385
|
-
|
|
1995
|
+
diagnostic: HtmlDiagnostics.landmarkRoleOverride(tag, implicitRole, role)
|
|
1996
|
+
}
|
|
1997
|
+
];
|
|
1998
|
+
}
|
|
1999
|
+
function requireAccessibleName({ tag, props }) {
|
|
2000
|
+
if ("aria-label" in props || "aria-labelledby" in props) return [];
|
|
2001
|
+
return [
|
|
2002
|
+
{
|
|
2003
|
+
valid: false,
|
|
2004
|
+
fixable: false,
|
|
2005
|
+
severity: "warning",
|
|
2006
|
+
diagnostic: AriaDiagnostics.missingAccessibleName(tag)
|
|
1386
2007
|
}
|
|
1387
2008
|
];
|
|
1388
2009
|
}
|
|
1389
|
-
var
|
|
2010
|
+
var NAMED_LANDMARK_TAGS = /* @__PURE__ */ new Set(["nav", "aside"]);
|
|
2011
|
+
function landmarkNameAdvisory(ctx) {
|
|
2012
|
+
if (!ctx.implicitRole || !NAMED_LANDMARK_TAGS.has(ctx.tag)) return [];
|
|
2013
|
+
return requireAccessibleName(ctx);
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
// ../core/src/html/contracts.ts
|
|
1390
2017
|
function isOpenContent(...blockedTags) {
|
|
1391
|
-
const
|
|
1392
|
-
return (child) => isObject(child) && "type" in child && (!isString(child.type) || !
|
|
2018
|
+
const set2 = new Set(blockedTags);
|
|
2019
|
+
return (child) => isObject(child) && "type" in child && (!isString(child.type) || !set2.has(child.type));
|
|
1393
2020
|
}
|
|
1394
2021
|
var METADATA_TAGS = ["script", "template"];
|
|
1395
2022
|
var metadataMatch = isTag(...METADATA_TAGS);
|
|
@@ -1400,10 +2027,10 @@ function firstOptional(name, tag) {
|
|
|
1400
2027
|
return { name, match: isTag(tag), cardinality: { max: 1 }, position: "first" };
|
|
1401
2028
|
}
|
|
1402
2029
|
function contract(children) {
|
|
1403
|
-
return {
|
|
2030
|
+
return { diagnostics: warnDiagnostics, children };
|
|
1404
2031
|
}
|
|
1405
2032
|
function ariaContract(aria) {
|
|
1406
|
-
return {
|
|
2033
|
+
return { diagnostics: warnDiagnostics, aria };
|
|
1407
2034
|
}
|
|
1408
2035
|
function firstChildContract(name, tag) {
|
|
1409
2036
|
return contract([firstOptional(name, tag), { name: "content", match: isOpenContent(tag) }]);
|
|
@@ -1490,7 +2117,15 @@ var textOnlyContract = contract([
|
|
|
1490
2117
|
match: (child) => isString(child) || isNumber(child)
|
|
1491
2118
|
}
|
|
1492
2119
|
]);
|
|
1493
|
-
var landmarkContract = ariaContract([landmarkRoleRule]);
|
|
2120
|
+
var landmarkContract = ariaContract([landmarkRoleRule, landmarkNameAdvisory]);
|
|
2121
|
+
var dialogContract = ariaContract([requireAccessibleName]);
|
|
2122
|
+
var menuContract = ariaContract([requireAccessibleName]);
|
|
2123
|
+
var menubarContract = ariaContract([requireAccessibleName]);
|
|
2124
|
+
var treeContract = ariaContract([requireAccessibleName]);
|
|
2125
|
+
var gridContract = ariaContract([requireAccessibleName]);
|
|
2126
|
+
var listboxContract = ariaContract([requireAccessibleName]);
|
|
2127
|
+
var tablistContract = ariaContract([requireAccessibleName]);
|
|
2128
|
+
var radiogroupContract = ariaContract([requireAccessibleName]);
|
|
1494
2129
|
var CONTRACT_GROUPS = [
|
|
1495
2130
|
[VOID_TAGS, voidContract],
|
|
1496
2131
|
[TEXT_ONLY_TAGS, textOnlyContract],
|
|
@@ -1517,19 +2152,28 @@ var htmlContracts = {
|
|
|
1517
2152
|
figure: figureContract,
|
|
1518
2153
|
details: detailsContract,
|
|
1519
2154
|
fieldset: fieldsetContract,
|
|
2155
|
+
dialog: dialogContract,
|
|
1520
2156
|
head: headContract,
|
|
1521
2157
|
html: htmlContract
|
|
1522
2158
|
};
|
|
2159
|
+
|
|
2160
|
+
// ../core/src/html/evaluators.ts
|
|
2161
|
+
var htmlDiagnostics = warnDiagnostics;
|
|
1523
2162
|
function buildEvaluatorMap() {
|
|
1524
|
-
const
|
|
1525
|
-
|
|
2163
|
+
const map2 = /* @__PURE__ */ new Map();
|
|
2164
|
+
iterate.forEachEntry(htmlContracts, (tag, { children }) => {
|
|
1526
2165
|
if (children?.length) {
|
|
1527
|
-
|
|
2166
|
+
map2.set(tag, new ChildrenEvaluator(children, htmlDiagnostics, `<${tag}>`));
|
|
1528
2167
|
}
|
|
1529
|
-
}
|
|
1530
|
-
return
|
|
2168
|
+
});
|
|
2169
|
+
return map2;
|
|
1531
2170
|
}
|
|
1532
2171
|
var HTML_EVALUATORS = buildEvaluatorMap();
|
|
2172
|
+
function getHtmlChildrenEvaluator(tag) {
|
|
2173
|
+
return typeof tag === "string" ? HTML_EVALUATORS.get(tag) : void 0;
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
// ../core/src/html/prop-normalizers.ts
|
|
1533
2177
|
var HTML_FORM_NORMALIZERS = /* @__PURE__ */ new Map([
|
|
1534
2178
|
["button", [disabledProps]],
|
|
1535
2179
|
["input", [disabledProps, readonlyProps, invalidProps]],
|
|
@@ -1542,436 +2186,567 @@ function getHtmlPropNormalizers(tag) {
|
|
|
1542
2186
|
return typeof tag === "string" ? HTML_FORM_NORMALIZERS.get(tag) : void 0;
|
|
1543
2187
|
}
|
|
1544
2188
|
|
|
1545
|
-
//
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
return Array.isArray(value) ? value.includes({
|
|
1572
|
-
...defaultVariants,
|
|
1573
|
-
...propsWithoutUndefined
|
|
1574
|
-
}[key]) : {
|
|
1575
|
-
...defaultVariants,
|
|
1576
|
-
...propsWithoutUndefined
|
|
1577
|
-
}[key] === value;
|
|
1578
|
-
}) ? [
|
|
1579
|
-
...acc,
|
|
1580
|
-
cvClass,
|
|
1581
|
-
cvClassName
|
|
1582
|
-
] : acc;
|
|
1583
|
-
}, []);
|
|
1584
|
-
return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
|
|
1585
|
-
};
|
|
1586
|
-
function cva2(base, config) {
|
|
1587
|
-
const fn = cva(base, config);
|
|
1588
|
-
return (props) => cn(fn(props));
|
|
1589
|
-
}
|
|
1590
|
-
var StaticClassResolver = class {
|
|
1591
|
-
#baseClass;
|
|
1592
|
-
#cache = /* @__PURE__ */ new Map();
|
|
1593
|
-
#resolveTag;
|
|
1594
|
-
constructor(baseClass, tagMap) {
|
|
1595
|
-
this.#baseClass = Array.isArray(baseClass) ? baseClass.join(" ") : baseClass;
|
|
1596
|
-
this.#resolveTag = tagMap ? (tag) => {
|
|
1597
|
-
const extra = tagMap[tag];
|
|
1598
|
-
if (!extra) return this.#baseClass;
|
|
1599
|
-
const extraStr = Array.isArray(extra) ? extra.join(" ") : extra;
|
|
1600
|
-
return `${this.#baseClass} ${extraStr}`;
|
|
1601
|
-
} : () => this.#baseClass;
|
|
1602
|
-
}
|
|
1603
|
-
resolve(tag, skipTagMap = false) {
|
|
1604
|
-
if (typeof tag !== "string" || skipTagMap) return this.#baseClass;
|
|
1605
|
-
const cached = this.#cache.get(tag);
|
|
1606
|
-
if (cached !== void 0) {
|
|
1607
|
-
this.#cache.delete(tag);
|
|
1608
|
-
this.#cache.set(tag, cached);
|
|
1609
|
-
return cached;
|
|
1610
|
-
}
|
|
1611
|
-
const result = this.#resolveTag(tag);
|
|
1612
|
-
this.#cache.set(tag, result);
|
|
1613
|
-
if (this.#cache.size > 200) {
|
|
1614
|
-
const lru = this.#cache.keys().next().value;
|
|
1615
|
-
if (lru !== void 0) this.#cache.delete(lru);
|
|
1616
|
-
}
|
|
1617
|
-
return result;
|
|
1618
|
-
}
|
|
1619
|
-
};
|
|
1620
|
-
var VariantClassResolver = class _VariantClassResolver {
|
|
1621
|
-
#cvaFn;
|
|
1622
|
-
#recipeMap;
|
|
1623
|
-
#variantKeys;
|
|
1624
|
-
#precomputedClasses;
|
|
1625
|
-
#cache = /* @__PURE__ */ new Map();
|
|
1626
|
-
constructor(cvaFn, recipeMap, variantKeys, precomputedClasses) {
|
|
1627
|
-
this.#cvaFn = cvaFn ?? null;
|
|
1628
|
-
this.#recipeMap = Object.freeze(recipeMap ?? {});
|
|
1629
|
-
this.#variantKeys = variantKeys ?? null;
|
|
1630
|
-
this.#precomputedClasses = precomputedClasses ?? null;
|
|
1631
|
-
}
|
|
1632
|
-
resolve({ props, recipe }) {
|
|
1633
|
-
const normalizedKey = recipe ?? "__none__";
|
|
1634
|
-
const cacheKey = this.#createCacheKey(props, normalizedKey);
|
|
1635
|
-
if (this.#precomputedClasses !== null) {
|
|
1636
|
-
const precomputed = this.#precomputedClasses[cacheKey];
|
|
1637
|
-
if (precomputed !== void 0) return precomputed;
|
|
1638
|
-
}
|
|
1639
|
-
const cached = this.#cache.get(cacheKey);
|
|
1640
|
-
if (cached !== void 0) {
|
|
1641
|
-
this.#cache.delete(cacheKey);
|
|
1642
|
-
this.#cache.set(cacheKey, cached);
|
|
1643
|
-
return cached;
|
|
1644
|
-
}
|
|
1645
|
-
const result = this.#compute(props, recipe);
|
|
1646
|
-
this.#cache.set(cacheKey, result);
|
|
1647
|
-
if (this.#cache.size > 1e3) {
|
|
1648
|
-
const lru = this.#cache.keys().next().value;
|
|
1649
|
-
if (lru !== void 0) this.#cache.delete(lru);
|
|
1650
|
-
}
|
|
1651
|
-
return result;
|
|
1652
|
-
}
|
|
1653
|
-
#compute(props, recipe) {
|
|
1654
|
-
if (!this.#cvaFn) return "";
|
|
1655
|
-
if (!recipe) return this.#cvaFn(props);
|
|
1656
|
-
const preset = this.#recipeMap[recipe];
|
|
1657
|
-
if (!preset) return this.#cvaFn(props);
|
|
1658
|
-
return this.#cvaFn({ ...preset, ...props });
|
|
1659
|
-
}
|
|
1660
|
-
// When variantKeys is provided, only those keys are included in the cache key — non-variant
|
|
1661
|
-
// props (className, id, etc.) produce identical CVA output and must not fragment the cache.
|
|
1662
|
-
// Iterating #variantKeys directly (fixed Set insertion order) avoids Object.keys + filter + sort.
|
|
1663
|
-
// String is built incrementally to avoid a parts[] array allocation on every render.
|
|
1664
|
-
#createCacheKey(props, recipe) {
|
|
1665
|
-
if (this.#variantKeys !== null) {
|
|
1666
|
-
let key2 = recipe;
|
|
1667
|
-
for (const k of this.#variantKeys) {
|
|
1668
|
-
if (k in props) key2 += `|${k}:${_VariantClassResolver.#serializeValue(props[k])}`;
|
|
1669
|
-
}
|
|
1670
|
-
return key2;
|
|
1671
|
-
}
|
|
1672
|
-
let key = recipe;
|
|
1673
|
-
for (const k of Object.keys(props).sort()) {
|
|
1674
|
-
key += `|${k}:${_VariantClassResolver.#serializeValue(props[k])}`;
|
|
2189
|
+
// ../../lib/styling/src/variant-pass/compile-variant-lookup.ts
|
|
2190
|
+
function buildPrecomputedKey(props) {
|
|
2191
|
+
return Object.entries(props).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}:${v}`).join("|");
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
// ../../lib/styling/src/variant-pass/variant-pass.ts
|
|
2195
|
+
function createVariantPass(activeProps, config) {
|
|
2196
|
+
return {
|
|
2197
|
+
name: "variant",
|
|
2198
|
+
execute() {
|
|
2199
|
+
const preset = typeof activeProps["preset"] === "string" ? activeProps["preset"] : void 0;
|
|
2200
|
+
const presetDefaults = preset !== void 0 && config.presets?.[preset] !== void 0 ? config.presets[preset] : {};
|
|
2201
|
+
const resolved = {
|
|
2202
|
+
...config.defaults,
|
|
2203
|
+
...presetDefaults,
|
|
2204
|
+
...activeProps
|
|
2205
|
+
};
|
|
2206
|
+
const classes = [];
|
|
2207
|
+
iterate.forEachEntry(config.variants, (key, valueMap) => {
|
|
2208
|
+
const active = resolved[key];
|
|
2209
|
+
if (typeof active === "string") {
|
|
2210
|
+
const cls = valueMap[active];
|
|
2211
|
+
if (cls !== void 0) classes.push(cls);
|
|
2212
|
+
}
|
|
2213
|
+
});
|
|
2214
|
+
return { context: { classes } };
|
|
1675
2215
|
}
|
|
1676
|
-
return key;
|
|
1677
|
-
}
|
|
1678
|
-
static #serializeValue(value) {
|
|
1679
|
-
if (value === void 0) return "u";
|
|
1680
|
-
if (value === null) return "n";
|
|
1681
|
-
if (typeof value === "boolean") return `b:${value}`;
|
|
1682
|
-
if (typeof value === "string") return `s:${value}`;
|
|
1683
|
-
return `x:${String(value)}`;
|
|
1684
|
-
}
|
|
1685
|
-
};
|
|
1686
|
-
function createClassPipeline(resolved) {
|
|
1687
|
-
const baseClass = resolved.baseClassName ?? "";
|
|
1688
|
-
const cvaFn = resolved.variants ? cva2("", {
|
|
1689
|
-
variants: resolved.variants,
|
|
1690
|
-
defaultVariants: resolved.defaultVariants,
|
|
1691
|
-
compoundVariants: resolved.compoundVariants
|
|
1692
|
-
}) : null;
|
|
1693
|
-
const variantKeys = resolved.variants ? new Set(Object.keys(resolved.variants)) : void 0;
|
|
1694
|
-
const staticResolver = new StaticClassResolver(baseClass, resolved.tagMap);
|
|
1695
|
-
const variantResolver = new VariantClassResolver(
|
|
1696
|
-
cvaFn,
|
|
1697
|
-
resolved.recipeMap,
|
|
1698
|
-
variantKeys,
|
|
1699
|
-
resolved.precomputedClasses
|
|
1700
|
-
);
|
|
1701
|
-
return function resolveClasses(tag, props, className, recipe) {
|
|
1702
|
-
const staticClasses = staticResolver.resolve(tag, recipe !== void 0);
|
|
1703
|
-
const variantClasses = variantResolver.resolve({ props, recipe });
|
|
1704
|
-
if (!className)
|
|
1705
|
-
return staticClasses && variantClasses ? `${staticClasses} ${variantClasses}` : staticClasses || variantClasses;
|
|
1706
|
-
return cn(staticClasses, variantClasses, className);
|
|
1707
2216
|
};
|
|
1708
2217
|
}
|
|
1709
2218
|
|
|
1710
|
-
// ../core/
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
};
|
|
1717
|
-
function createPolymorphic2(options = {}) {
|
|
1718
|
-
return createPolymorphic(options, FULL_CAPABILITIES);
|
|
2219
|
+
// ../core/src/resolver/resolver.ts
|
|
2220
|
+
function enforceAllowedAs(tag, allowedAs, diagnostics, displayName) {
|
|
2221
|
+
if (allowedAs.includes(tag)) return;
|
|
2222
|
+
if (!diagnostics) return;
|
|
2223
|
+
const component = displayName ?? String(tag);
|
|
2224
|
+
diagnostics.error(ContractDiagnostics.allowedAsViolation(String(tag), allowedAs, component));
|
|
1719
2225
|
}
|
|
1720
2226
|
|
|
1721
|
-
// ../../lib/adapter-utils/src/
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
return { runtime, ownedKeys };
|
|
2227
|
+
// ../../lib/adapter-utils/src/apply-prop-normalizers.ts
|
|
2228
|
+
function applyPropNormalizers(tag, props, additional) {
|
|
2229
|
+
const normalizers = [...getHtmlPropNormalizers(tag) ?? [], ...additional ?? []];
|
|
2230
|
+
if (normalizers.length === 0) return props;
|
|
2231
|
+
return normalizers.reduce((acc, fn) => ({ ...acc, ...fn(acc) }), props);
|
|
1727
2232
|
}
|
|
1728
2233
|
|
|
1729
|
-
// ../../lib/adapter-utils/src/
|
|
1730
|
-
function
|
|
1731
|
-
return
|
|
2234
|
+
// ../../lib/adapter-utils/src/define-component.ts
|
|
2235
|
+
function defineContractComponent(options) {
|
|
2236
|
+
return (factory) => factory(options);
|
|
1732
2237
|
}
|
|
1733
2238
|
|
|
1734
|
-
// ../../lib/adapter-utils/src/
|
|
1735
|
-
function
|
|
1736
|
-
|
|
1737
|
-
if (!filterProps) {
|
|
1738
|
-
return defaultFilter;
|
|
1739
|
-
}
|
|
1740
|
-
return (key, variantKeys) => defaultFilter(key, variantKeys) || filterProps(key, variantKeys);
|
|
2239
|
+
// ../../lib/adapter-utils/src/build-engines.ts
|
|
2240
|
+
function buildEngines(diagnostics, childRules, context) {
|
|
2241
|
+
return childRules?.length ? { childrenEvaluator: new ChildrenEvaluator(childRules, diagnostics, context) } : {};
|
|
1741
2242
|
}
|
|
1742
2243
|
|
|
1743
2244
|
// ../../lib/adapter-utils/src/resolve-adapter-common-options.ts
|
|
1744
|
-
function resolveAdapterCommonOptions(options, defaultName = "PolymorphicComponent",
|
|
2245
|
+
function resolveAdapterCommonOptions(options, defaultName = "PolymorphicComponent", defaultDiagnostics = throwDiagnostics) {
|
|
1745
2246
|
return {
|
|
1746
2247
|
name: options.name ?? defaultName,
|
|
1747
|
-
|
|
2248
|
+
diagnostics: options.enforcement?.diagnostics ?? defaultDiagnostics
|
|
1748
2249
|
};
|
|
1749
2250
|
}
|
|
1750
2251
|
|
|
1751
2252
|
// ../../lib/adapter-utils/src/slot-validator.ts
|
|
1752
|
-
var SlotValidator = class extends
|
|
2253
|
+
var SlotValidator = class extends InvariantBase {
|
|
1753
2254
|
#name;
|
|
1754
2255
|
#elementTerm;
|
|
1755
|
-
constructor(name,
|
|
1756
|
-
super(
|
|
2256
|
+
constructor(name, diagnostics, elementTerm) {
|
|
2257
|
+
super(diagnostics);
|
|
1757
2258
|
this.#name = name;
|
|
1758
2259
|
this.#elementTerm = elementTerm;
|
|
1759
2260
|
}
|
|
1760
2261
|
assertExclusive() {
|
|
1761
|
-
this.violate(
|
|
2262
|
+
this.violate(SlotDiagnostics.exclusive(this.#name));
|
|
1762
2263
|
}
|
|
1763
2264
|
warnDiscardedChildren(count) {
|
|
1764
|
-
|
|
1765
|
-
this.warn(
|
|
1766
|
-
`${this.#name}: asChild discarded ${count} non-element child${suffix} \u2014 only ${this.#elementTerm}s are valid asChild children.`
|
|
1767
|
-
);
|
|
2265
|
+
this.warn(SlotDiagnostics.discardedChildren(this.#name, this.#elementTerm, count));
|
|
1768
2266
|
}
|
|
1769
2267
|
assertSingleChild(count) {
|
|
1770
|
-
|
|
1771
|
-
|
|
2268
|
+
this.violate(
|
|
2269
|
+
count === 0 ? SlotDiagnostics.singleChildRequired(this.#name, this.#elementTerm) : SlotDiagnostics.singleChildExceeded(this.#name, this.#elementTerm, count)
|
|
2270
|
+
);
|
|
1772
2271
|
}
|
|
1773
2272
|
};
|
|
1774
2273
|
|
|
1775
|
-
// ../../
|
|
1776
|
-
function
|
|
1777
|
-
|
|
2274
|
+
// ../../lib/adapter-utils/src/build-definition.ts
|
|
2275
|
+
function buildDefinition(name, tag) {
|
|
2276
|
+
return {
|
|
2277
|
+
identity: {
|
|
2278
|
+
id: name,
|
|
2279
|
+
name,
|
|
2280
|
+
tag
|
|
2281
|
+
},
|
|
2282
|
+
capabilities: {},
|
|
2283
|
+
metadata: {},
|
|
2284
|
+
diagnostics: []
|
|
2285
|
+
};
|
|
1778
2286
|
}
|
|
1779
|
-
|
|
1780
|
-
|
|
2287
|
+
|
|
2288
|
+
// ../../lib/adapter-utils/src/build-variant-config.ts
|
|
2289
|
+
function flattenClassName(cls) {
|
|
2290
|
+
return Array.isArray(cls) ? cls.join(" ") : cls;
|
|
2291
|
+
}
|
|
2292
|
+
function mapVariantRecord(source, mapper) {
|
|
2293
|
+
return iterate.mapValues(
|
|
2294
|
+
source,
|
|
2295
|
+
(inner) => iterate.mapValues(inner, mapper)
|
|
2296
|
+
);
|
|
2297
|
+
}
|
|
2298
|
+
function buildVariantConfig(variants, presets, defaults, compounds) {
|
|
2299
|
+
return {
|
|
2300
|
+
variants: mapVariantRecord(variants ?? {}, flattenClassName),
|
|
2301
|
+
...presets !== void 0 && Object.keys(presets).length > 0 && { presets },
|
|
2302
|
+
...defaults !== void 0 && Object.keys(defaults).length > 0 && { defaults },
|
|
2303
|
+
...compounds !== void 0 && compounds.length > 0 && {
|
|
2304
|
+
compounds
|
|
2305
|
+
}
|
|
2306
|
+
};
|
|
1781
2307
|
}
|
|
1782
2308
|
|
|
1783
|
-
// ../../
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
2309
|
+
// ../../runtime/core/src/apply-attributes.ts
|
|
2310
|
+
function applyAttributes(nodeId, incoming, decoration, removedKeys) {
|
|
2311
|
+
const existing = decoration[nodeId] ?? {};
|
|
2312
|
+
const next = { ...existing.attributes };
|
|
2313
|
+
if (removedKeys !== void 0) {
|
|
2314
|
+
iterate.forEachSet(removedKeys, (key) => {
|
|
2315
|
+
delete next[key];
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
Object.assign(next, incoming);
|
|
2319
|
+
const { attributes: _dropped, ...rest } = existing;
|
|
2320
|
+
const nextDecoration = Object.keys(next).length > 0 ? { ...rest, attributes: next } : rest;
|
|
2321
|
+
return { ...decoration, [nodeId]: nextDecoration };
|
|
2322
|
+
}
|
|
1789
2323
|
|
|
1790
|
-
// ../../
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
return () => h(Fragment, null, slots.default?.());
|
|
1796
|
-
}
|
|
1797
|
-
});
|
|
2324
|
+
// ../../runtime/core/src/get-active-props.ts
|
|
2325
|
+
function getActiveProps(nodeId, decoration) {
|
|
2326
|
+
const dec = decoration[nodeId];
|
|
2327
|
+
return { ...dec?.attributes ?? {}, ...dec?.variants ?? {} };
|
|
2328
|
+
}
|
|
1798
2329
|
|
|
1799
|
-
// ../../
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
return vnode.type === Slottable;
|
|
2330
|
+
// ../../runtime/core/src/render-component.ts
|
|
2331
|
+
function renderComponent(definition, tree, render, backend) {
|
|
2332
|
+
return backend.render({ definition, tree, render });
|
|
1803
2333
|
}
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
if (
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
2334
|
+
|
|
2335
|
+
// ../../runtime/core/src/build-tree-context.ts
|
|
2336
|
+
function buildNode(input, slotAssignments, seenIds, diagnostics) {
|
|
2337
|
+
if (seenIds.has(input.id)) {
|
|
2338
|
+
diagnostics.push({
|
|
2339
|
+
code: "duplicate-node-id",
|
|
2340
|
+
message: `Duplicate node id "${input.id}"`,
|
|
2341
|
+
severity: "error"
|
|
2342
|
+
});
|
|
2343
|
+
} else {
|
|
2344
|
+
seenIds.add(input.id);
|
|
2345
|
+
}
|
|
2346
|
+
if (input.slot !== void 0) {
|
|
2347
|
+
slotAssignments.set(input.id, input.slot);
|
|
2348
|
+
}
|
|
2349
|
+
const children = Object.freeze(
|
|
2350
|
+
(input.children ?? []).map((child) => buildNode(child, slotAssignments, seenIds, diagnostics))
|
|
1815
2351
|
);
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
return {
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
2352
|
+
if (input.kind === "native") {
|
|
2353
|
+
return Object.freeze({ kind: "native", id: input.id, tag: input.tag, children });
|
|
2354
|
+
}
|
|
2355
|
+
return Object.freeze({ kind: "component", id: input.id, children });
|
|
2356
|
+
}
|
|
2357
|
+
function buildTreeContext(root) {
|
|
2358
|
+
const slotAssignments = /* @__PURE__ */ new Map();
|
|
2359
|
+
const diagnostics = [];
|
|
2360
|
+
const rootNode = buildNode(root, slotAssignments, /* @__PURE__ */ new Set(), diagnostics);
|
|
2361
|
+
return Object.freeze({ root: rootNode, slotAssignments, diagnostics });
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
// ../../runtime/core/src/build-render-context.ts
|
|
2365
|
+
function buildRenderContext(decoration = {}) {
|
|
2366
|
+
return { decoration: new Map(Object.entries(decoration)) };
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
// ../../lib/adapter-utils/src/resolve-compounds.ts
|
|
2370
|
+
function matchesCompound(active, compound) {
|
|
2371
|
+
const { class: _, ...conditions } = compound;
|
|
2372
|
+
return Object.entries(conditions).every(([key, expected]) => {
|
|
2373
|
+
const actual = active[key];
|
|
2374
|
+
return Array.isArray(expected) ? expected.includes(actual) : actual === expected;
|
|
2375
|
+
});
|
|
2376
|
+
}
|
|
2377
|
+
function resolveCompounds(active, compounds) {
|
|
2378
|
+
if (!compounds?.length) return [];
|
|
2379
|
+
const out = [];
|
|
2380
|
+
iterate.forEach(compounds, (compound) => {
|
|
2381
|
+
if (matchesCompound(active, compound)) {
|
|
2382
|
+
out.push(flattenClassName(compound.class));
|
|
1824
2383
|
}
|
|
1825
|
-
};
|
|
2384
|
+
});
|
|
2385
|
+
return out;
|
|
1826
2386
|
}
|
|
1827
2387
|
|
|
1828
|
-
// ../../
|
|
1829
|
-
function
|
|
1830
|
-
|
|
2388
|
+
// ../../lib/adapter-utils/src/resolve-classes.ts
|
|
2389
|
+
function resolveClasses(decoration, variantConfig, variantDefaults, recipe, compounds, variantLookup) {
|
|
2390
|
+
const active = getActiveProps("root", decoration);
|
|
2391
|
+
if (variantLookup !== void 0 && recipe === void 0) {
|
|
2392
|
+
const activeVariants = {};
|
|
2393
|
+
iterate.forEachKey(variantConfig.variants, (key) => {
|
|
2394
|
+
const value = active[key];
|
|
2395
|
+
if (typeof value === "string") activeVariants[key] = value;
|
|
2396
|
+
});
|
|
2397
|
+
const lookupKey = buildPrecomputedKey(activeVariants);
|
|
2398
|
+
const precomputedValue = variantLookup[lookupKey];
|
|
2399
|
+
if (precomputedValue !== void 0) {
|
|
2400
|
+
return {
|
|
2401
|
+
variantClasses: precomputedValue !== "" ? [precomputedValue] : [],
|
|
2402
|
+
compoundClasses: []
|
|
2403
|
+
};
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
const passInput = recipe !== void 0 ? { ...active, preset: recipe } : active;
|
|
2407
|
+
const { context } = createVariantPass(passInput, variantConfig).execute({ classes: [] });
|
|
2408
|
+
const variantClasses = context.classes;
|
|
2409
|
+
const presetOverrides = recipe !== void 0 ? variantConfig.presets?.[recipe] ?? {} : {};
|
|
2410
|
+
const resolvedValues = {
|
|
2411
|
+
...variantDefaults,
|
|
2412
|
+
...presetOverrides,
|
|
2413
|
+
...active
|
|
2414
|
+
};
|
|
2415
|
+
const compoundClasses = resolveCompounds(resolvedValues, compounds);
|
|
2416
|
+
return { variantClasses, compoundClasses };
|
|
1831
2417
|
}
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
normalized.name
|
|
1840
|
-
);
|
|
1841
|
-
const filterProps = composeFilter(ownedKeys, normalized.filterProps);
|
|
2418
|
+
|
|
2419
|
+
// ../../lib/adapter-utils/src/build-pipeline.ts
|
|
2420
|
+
function buildStylePipeline(variants, presets, defaults, compounds, variantLookup) {
|
|
2421
|
+
if (variants === void 0 && compounds === void 0 && presets === void 0 && variantLookup === void 0) {
|
|
2422
|
+
return void 0;
|
|
2423
|
+
}
|
|
2424
|
+
const variantConfig = buildVariantConfig(variants, presets, defaults, compounds);
|
|
1842
2425
|
return {
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
...childrenEvaluator !== void 0 && { childrenEvaluator }
|
|
2426
|
+
execute(decoration, recipe) {
|
|
2427
|
+
return resolveClasses(decoration, variantConfig, defaults, recipe, compounds, variantLookup);
|
|
2428
|
+
}
|
|
1847
2429
|
};
|
|
1848
2430
|
}
|
|
1849
2431
|
|
|
1850
|
-
// ../../
|
|
1851
|
-
|
|
2432
|
+
// ../../lib/adapter-utils/src/join-classes.ts
|
|
2433
|
+
function joinClasses(...classes) {
|
|
2434
|
+
return classes.filter(Boolean).join(" ");
|
|
2435
|
+
}
|
|
1852
2436
|
|
|
1853
|
-
// ../../
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
const vnodes = raw.filter(isVNode);
|
|
1858
|
-
return { vnodes, discarded: raw.length - vnodes.length };
|
|
2437
|
+
// ../../lib/adapter-utils/src/decoration-utils.ts
|
|
2438
|
+
function withAttributes(dec, attributes) {
|
|
2439
|
+
const { attributes: _a, ...rest } = dec;
|
|
2440
|
+
return attributes !== void 0 ? { ...rest, attributes } : rest;
|
|
1859
2441
|
}
|
|
1860
2442
|
|
|
1861
|
-
// ../../
|
|
1862
|
-
function
|
|
2443
|
+
// ../../lib/adapter-utils/src/apply-aria.ts
|
|
2444
|
+
function applyAria(decoration, tag, ariaEngine) {
|
|
2445
|
+
if (ariaEngine === void 0) return decoration;
|
|
2446
|
+
const dec = decoration["root"];
|
|
2447
|
+
if (dec?.attributes === void 0) return decoration;
|
|
2448
|
+
const result = ariaEngine.validate(tag, dec.attributes);
|
|
2449
|
+
const cleaned = result.props;
|
|
1863
2450
|
return {
|
|
1864
|
-
...
|
|
1865
|
-
|
|
2451
|
+
...decoration,
|
|
2452
|
+
root: withAttributes(dec, Object.keys(cleaned).length > 0 ? cleaned : void 0)
|
|
1866
2453
|
};
|
|
1867
2454
|
}
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
const
|
|
1873
|
-
|
|
1874
|
-
const
|
|
1875
|
-
|
|
1876
|
-
tag,
|
|
1877
|
-
normalizedProps,
|
|
1878
|
-
typeof className === "string" ? className : void 0,
|
|
1879
|
-
typeof recipe === "string" ? recipe : void 0
|
|
2455
|
+
|
|
2456
|
+
// ../../lib/adapter-utils/src/apply-filter-props.ts
|
|
2457
|
+
function applyFilterProps(decoration, filterFn, variantKeys) {
|
|
2458
|
+
if (filterFn === void 0) return decoration;
|
|
2459
|
+
const dec = decoration["root"];
|
|
2460
|
+
if (dec?.attributes === void 0) return decoration;
|
|
2461
|
+
const kept = Object.fromEntries(
|
|
2462
|
+
Object.entries(dec.attributes).filter(([k]) => !filterFn(k, variantKeys))
|
|
1880
2463
|
);
|
|
1881
|
-
const filteredProps = applyFilter(normalizedProps, filterProps, runtime.options.variantKeys);
|
|
1882
2464
|
return {
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
className: resolvedClass,
|
|
1886
|
-
props: filteredProps
|
|
2465
|
+
...decoration,
|
|
2466
|
+
root: withAttributes(dec, Object.keys(kept).length > 0 ? kept : void 0)
|
|
1887
2467
|
};
|
|
1888
2468
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
2469
|
+
|
|
2470
|
+
// ../../adapters/vue/src/backend/extract-decoration.ts
|
|
2471
|
+
function isStyleValue(v) {
|
|
2472
|
+
return isString(v) || isNumber(v);
|
|
2473
|
+
}
|
|
2474
|
+
function isAttributeValue(v) {
|
|
2475
|
+
return isString(v) || isNumber(v) || typeof v === "boolean";
|
|
2476
|
+
}
|
|
2477
|
+
function assignIfNotEmpty(target, key, value) {
|
|
2478
|
+
if (Object.keys(value).length > 0) {
|
|
2479
|
+
target[key] = value;
|
|
1895
2480
|
}
|
|
2481
|
+
}
|
|
2482
|
+
function extractStyles(value, styles) {
|
|
2483
|
+
if (!isObject(value)) return false;
|
|
2484
|
+
iterate.forEachEntry(value, (k, v) => {
|
|
2485
|
+
if (isStyleValue(v)) {
|
|
2486
|
+
styles[k] = v;
|
|
2487
|
+
}
|
|
2488
|
+
});
|
|
1896
2489
|
return true;
|
|
1897
2490
|
}
|
|
1898
|
-
function
|
|
1899
|
-
if (!
|
|
1900
|
-
|
|
1901
|
-
const extraction = extractSlottable(children);
|
|
1902
|
-
if (extraction) {
|
|
1903
|
-
const merged = cloneVNode(extraction.child, { ...state.props, class: state.className });
|
|
1904
|
-
return extraction.rebuild(merged);
|
|
2491
|
+
function extractListener(key, value, listeners) {
|
|
2492
|
+
if (!key.startsWith("on") || !isFunction(value)) {
|
|
2493
|
+
return false;
|
|
1905
2494
|
}
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
2495
|
+
listeners[key] = value;
|
|
2496
|
+
return true;
|
|
2497
|
+
}
|
|
2498
|
+
function extractAttributeOrVariant(key, value, attributes, variants, variantKeys) {
|
|
2499
|
+
if (variantKeys?.has(key)) {
|
|
2500
|
+
variants[key] = value;
|
|
2501
|
+
} else {
|
|
2502
|
+
attributes[key] = value;
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
function extractDecoration(props, variantKeys) {
|
|
2506
|
+
const attributes = {};
|
|
2507
|
+
const styles = {};
|
|
2508
|
+
const listeners = {};
|
|
2509
|
+
const variants = {};
|
|
2510
|
+
const dec = {};
|
|
2511
|
+
iterate.forEachEntry(props, (key, value) => {
|
|
2512
|
+
if (key === "children" || key === "slot" || key === "ref") return;
|
|
2513
|
+
if (key === "style" && extractStyles(value, styles)) return;
|
|
2514
|
+
if (extractListener(key, value, listeners)) return;
|
|
2515
|
+
if (isAttributeValue(value)) {
|
|
2516
|
+
extractAttributeOrVariant(key, value, attributes, variants, variantKeys);
|
|
2517
|
+
}
|
|
2518
|
+
});
|
|
2519
|
+
assignIfNotEmpty(dec, "attributes", attributes);
|
|
2520
|
+
assignIfNotEmpty(dec, "styles", styles);
|
|
2521
|
+
assignIfNotEmpty(dec, "listeners", listeners);
|
|
2522
|
+
assignIfNotEmpty(dec, "variants", variants);
|
|
2523
|
+
const ref = props.ref;
|
|
2524
|
+
if (ref !== void 0) {
|
|
2525
|
+
dec.ref = ref;
|
|
1910
2526
|
}
|
|
1911
|
-
|
|
1912
|
-
return null;
|
|
2527
|
+
return dec;
|
|
1913
2528
|
}
|
|
2529
|
+
|
|
2530
|
+
// ../../adapters/vue/src/helpers/render-normally.ts
|
|
2531
|
+
import { h as h2 } from "vue";
|
|
2532
|
+
|
|
2533
|
+
// ../../adapters/vue/src/backend/vue-backend.ts
|
|
2534
|
+
import { Fragment, h } from "vue";
|
|
2535
|
+
|
|
2536
|
+
// ../../adapters/vue/src/backend/build-props.ts
|
|
2537
|
+
function buildPropsFromDecoration(id, decoration) {
|
|
2538
|
+
return {
|
|
2539
|
+
key: id,
|
|
2540
|
+
...decoration?.attributes,
|
|
2541
|
+
...decoration?.styles !== void 0 ? { style: decoration.styles } : {},
|
|
2542
|
+
...decoration?.listeners,
|
|
2543
|
+
...decoration?.ref !== void 0 ? { ref: decoration.ref } : {}
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
// ../../adapters/vue/src/backend/vue-backend.ts
|
|
1914
2548
|
var MULTI_WORD_EVENT_RE = /^on[A-Z][a-z]+[A-Z]/;
|
|
1915
|
-
function
|
|
2549
|
+
function normalizeListenerKeys(listeners) {
|
|
1916
2550
|
const out = {};
|
|
1917
|
-
for (const k in
|
|
1918
|
-
out[MULTI_WORD_EVENT_RE.test(k) ? "on" + k.slice(2).toLowerCase() : k] =
|
|
2551
|
+
for (const k in listeners) {
|
|
2552
|
+
out[MULTI_WORD_EVENT_RE.test(k) ? "on" + k.slice(2).toLowerCase() : k] = listeners[k];
|
|
1919
2553
|
}
|
|
1920
2554
|
return out;
|
|
1921
2555
|
}
|
|
1922
|
-
function
|
|
1923
|
-
const
|
|
1924
|
-
|
|
2556
|
+
function renderNode(node, render, isRoot) {
|
|
2557
|
+
const children = node.children.map((child) => renderNode(child, render, false));
|
|
2558
|
+
if (node.kind === "component") {
|
|
2559
|
+
return h(Fragment, isRoot ? null : { key: node.id }, children);
|
|
2560
|
+
}
|
|
2561
|
+
const decoration = render.decoration.get(node.id);
|
|
2562
|
+
const base = buildPropsFromDecoration(isRoot ? "" : node.id, decoration);
|
|
2563
|
+
const { key: _key, ...rest } = base;
|
|
2564
|
+
const props = {
|
|
2565
|
+
...isRoot ? {} : { key: node.id },
|
|
1925
2566
|
...rest,
|
|
1926
|
-
|
|
1927
|
-
|
|
2567
|
+
...decoration?.listeners !== void 0 ? normalizeListenerKeys(decoration.listeners) : {}
|
|
2568
|
+
};
|
|
2569
|
+
return h(node.tag, props, children.length > 0 ? children : void 0);
|
|
2570
|
+
}
|
|
2571
|
+
var vueBackend = {
|
|
2572
|
+
render(context) {
|
|
2573
|
+
return renderNode(context.tree.root, context.render, true);
|
|
2574
|
+
}
|
|
2575
|
+
};
|
|
2576
|
+
|
|
2577
|
+
// ../../adapters/vue/src/helpers/render-normally.ts
|
|
2578
|
+
function renderNormally(definition, tag, decoration, slots) {
|
|
2579
|
+
const treeCtx = buildTreeContext({ kind: "native", tag, id: "root", children: [] });
|
|
2580
|
+
const rendered = renderComponent(definition, treeCtx, buildRenderContext(decoration), vueBackend);
|
|
2581
|
+
if (slots?.default === void 0) return rendered;
|
|
2582
|
+
const { key: _key, ...props } = rendered.props ?? {};
|
|
2583
|
+
return h2(tag, props, { default: slots.default });
|
|
2584
|
+
}
|
|
2585
|
+
|
|
2586
|
+
// ../../adapters/vue/src/normalize-children.ts
|
|
2587
|
+
import { isVNode } from "vue";
|
|
2588
|
+
function normalizeChildren(slots) {
|
|
2589
|
+
const raw = slots.default?.() ?? [];
|
|
2590
|
+
const vnodes = raw.filter(isVNode);
|
|
2591
|
+
return { vnodes, discarded: raw.length - vnodes.length };
|
|
2592
|
+
}
|
|
2593
|
+
|
|
2594
|
+
// ../../adapters/vue/src/slot/Slottable.ts
|
|
2595
|
+
import { defineComponent, h as h3, Fragment as Fragment2 } from "vue";
|
|
2596
|
+
var Slottable = defineComponent({
|
|
2597
|
+
name: "Slottable",
|
|
2598
|
+
setup(_, { slots }) {
|
|
2599
|
+
return () => h3(Fragment2, null, slots.default?.());
|
|
2600
|
+
}
|
|
2601
|
+
});
|
|
2602
|
+
|
|
2603
|
+
// ../../adapters/vue/src/slot/extractSlottable.ts
|
|
2604
|
+
import { h as h4, Fragment as Fragment3 } from "vue";
|
|
2605
|
+
function isSlottableVNode(vnode) {
|
|
2606
|
+
return vnode.type === Slottable;
|
|
2607
|
+
}
|
|
2608
|
+
function extractSlottable(children) {
|
|
2609
|
+
const slottables = children.filter(isSlottableVNode);
|
|
2610
|
+
invariant(slottables.length <= 1, "Slot: multiple Slottable children are not allowed");
|
|
2611
|
+
if (slottables.length === 0) return null;
|
|
2612
|
+
const [slottable] = slottables;
|
|
2613
|
+
invariant(slottable !== void 0, "Slottable element is undefined");
|
|
2614
|
+
const slots = slottable.children;
|
|
2615
|
+
const defaultChildren = slots?.default?.() ?? [];
|
|
2616
|
+
invariant(
|
|
2617
|
+
defaultChildren.length === 1,
|
|
2618
|
+
`Slottable expects exactly one VNode child, received ${defaultChildren.length}`
|
|
2619
|
+
);
|
|
2620
|
+
const child = defaultChildren[0];
|
|
2621
|
+
invariant(child !== void 0, "Slottable child is undefined");
|
|
2622
|
+
const index = children.indexOf(slottable);
|
|
2623
|
+
return {
|
|
2624
|
+
child,
|
|
2625
|
+
rebuild(merged) {
|
|
2626
|
+
const out = children.map((node, i) => i === index ? merged : node);
|
|
2627
|
+
return h4(Fragment3, null, out);
|
|
2628
|
+
}
|
|
1928
2629
|
};
|
|
1929
|
-
if (typeof tag !== "string") return base;
|
|
1930
|
-
const validated = runtime.resolveAria(tag, base);
|
|
1931
|
-
const {
|
|
1932
|
-
className: _className,
|
|
1933
|
-
ref: _ref,
|
|
1934
|
-
children: _children,
|
|
1935
|
-
...validatedRest
|
|
1936
|
-
} = validated.props;
|
|
1937
|
-
return { ...validatedRest, class: className };
|
|
1938
|
-
}
|
|
1939
|
-
function render({
|
|
1940
|
-
runtime,
|
|
1941
|
-
attrs,
|
|
1942
|
-
slots,
|
|
1943
|
-
filterProps,
|
|
1944
|
-
slotValidator,
|
|
1945
|
-
childrenEvaluator,
|
|
1946
|
-
resolvedState
|
|
1947
|
-
}) {
|
|
1948
|
-
const state = resolvedState ?? resolveRenderState(runtime, attrs, filterProps);
|
|
1949
|
-
const { vnodes: children, discarded } = normalizeChildren(slots);
|
|
1950
|
-
if (process.env.NODE_ENV !== "production") childrenEvaluator?.evaluate(children);
|
|
1951
|
-
const slotResult = tryRenderAsChild(state, children, discarded, slotValidator);
|
|
1952
|
-
if (slotResult !== null) return slotResult;
|
|
1953
|
-
const domProps = buildDomProps(runtime, state.props, state.className, state.tag);
|
|
1954
|
-
return h3(state.tag, domProps, slots.default ? { default: slots.default } : void 0);
|
|
1955
2630
|
}
|
|
1956
2631
|
|
|
1957
2632
|
// ../../adapters/vue/src/create-contract-component.ts
|
|
2633
|
+
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
1958
2634
|
function createContractComponent(options) {
|
|
1959
|
-
const
|
|
2635
|
+
const resolved = resolveAdapterCommonOptions(options);
|
|
2636
|
+
const displayName = resolved.name;
|
|
2637
|
+
const defaultTag = options.tag ?? "div";
|
|
2638
|
+
const definition = buildDefinition(displayName, defaultTag);
|
|
2639
|
+
const variantKeys = new Set(Object.keys(options.styling?.variants ?? {}));
|
|
2640
|
+
const domDefaults = options.defaults;
|
|
2641
|
+
const stylePipeline = buildStylePipeline(
|
|
2642
|
+
options.styling?.variants,
|
|
2643
|
+
options.styling?.presets,
|
|
2644
|
+
options.styling?.defaults ?? {},
|
|
2645
|
+
options.styling?.compounds,
|
|
2646
|
+
void 0
|
|
2647
|
+
);
|
|
2648
|
+
const base = options.styling?.base !== void 0 ? flattenClassName(options.styling.base) : void 0;
|
|
2649
|
+
const filterFn = options.filterProps;
|
|
2650
|
+
const allowedAs = options.enforcement?.allowedAs;
|
|
2651
|
+
const normalizeFn = options.normalize;
|
|
2652
|
+
const enforcementNormalizers = options.enforcement?.props;
|
|
2653
|
+
const classPlugin = options.styling?.plugin !== void 0 ? options.styling.plugin(
|
|
2654
|
+
options.styling,
|
|
2655
|
+
resolved.diagnostics
|
|
2656
|
+
) : void 0;
|
|
2657
|
+
const pluginKeys = classPlugin?.ownedKeys ?? EMPTY_SET;
|
|
2658
|
+
const { childrenEvaluator: explicitEvaluator } = buildEngines(
|
|
2659
|
+
resolved.diagnostics,
|
|
2660
|
+
options.enforcement?.children,
|
|
2661
|
+
displayName
|
|
2662
|
+
);
|
|
2663
|
+
const ariaEngine = options.enforcement !== void 0 ? new AriaPolicyEngine(resolved.diagnostics) : void 0;
|
|
2664
|
+
const slotValidator = new SlotValidator(displayName, resolved.diagnostics, "VNode");
|
|
1960
2665
|
const Component = defineComponent2({
|
|
1961
|
-
name:
|
|
1962
|
-
// Without inheritAttrs: false Vue would double-bind attrs onto the root element
|
|
1963
|
-
// before our render pipeline has a chance to filter, transform, and re-apply them.
|
|
2666
|
+
name: displayName,
|
|
1964
2667
|
inheritAttrs: false,
|
|
1965
2668
|
setup(_, { attrs, slots }) {
|
|
1966
|
-
const
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
2669
|
+
const decorationState = computed(() => {
|
|
2670
|
+
const {
|
|
2671
|
+
as,
|
|
2672
|
+
asChild,
|
|
2673
|
+
class: callerClass,
|
|
2674
|
+
recipe,
|
|
2675
|
+
...ownProps
|
|
2676
|
+
} = attrs;
|
|
2677
|
+
const tag = typeof as === "string" ? as : defaultTag;
|
|
2678
|
+
if (allowedAs !== void 0)
|
|
2679
|
+
enforceAllowedAs(tag, allowedAs, resolved.diagnostics, displayName);
|
|
2680
|
+
const rawBaseProps = domDefaults !== void 0 ? { ...domDefaults, ...ownProps } : ownProps;
|
|
2681
|
+
const normalizedProps = applyPropNormalizers(tag, rawBaseProps, enforcementNormalizers);
|
|
2682
|
+
const baseProps = normalizeFn !== void 0 ? normalizeFn(normalizedProps) : normalizedProps;
|
|
2683
|
+
const pluginProps = {};
|
|
2684
|
+
const propsForExtraction = pluginKeys.size > 0 ? Object.fromEntries(
|
|
2685
|
+
Object.entries(baseProps).filter(([k]) => {
|
|
2686
|
+
if (pluginKeys.has(k)) {
|
|
2687
|
+
pluginProps[k] = baseProps[k];
|
|
2688
|
+
return false;
|
|
2689
|
+
}
|
|
2690
|
+
return true;
|
|
2691
|
+
})
|
|
2692
|
+
) : baseProps;
|
|
2693
|
+
const rootDec = extractDecoration(propsForExtraction, variantKeys);
|
|
2694
|
+
const decoration = applyAria(
|
|
2695
|
+
Object.keys(rootDec).length > 0 ? { root: rootDec } : {},
|
|
2696
|
+
tag,
|
|
2697
|
+
ariaEngine
|
|
2698
|
+
);
|
|
2699
|
+
const recipeName = typeof recipe === "string" ? recipe : void 0;
|
|
2700
|
+
const { variantClasses, compoundClasses } = stylePipeline ? stylePipeline.execute(decoration, recipeName) : { variantClasses: [], compoundClasses: [] };
|
|
2701
|
+
const rawClassName = joinClasses(
|
|
2702
|
+
base,
|
|
2703
|
+
...variantClasses,
|
|
2704
|
+
...compoundClasses,
|
|
2705
|
+
typeof callerClass === "string" ? callerClass : void 0
|
|
2706
|
+
);
|
|
2707
|
+
const className = classPlugin !== void 0 ? classPlugin.pipeline(tag, pluginProps, rawClassName, recipeName) : rawClassName;
|
|
2708
|
+
let finalDecoration = className ? applyAttributes("root", { className }, decoration, variantKeys) : decoration;
|
|
2709
|
+
finalDecoration = applyFilterProps(finalDecoration, filterFn, variantKeys);
|
|
2710
|
+
return { tag, asChild, as, finalDecoration, className };
|
|
2711
|
+
});
|
|
2712
|
+
return () => {
|
|
2713
|
+
const { tag, asChild, as, finalDecoration, className } = decorationState.value;
|
|
2714
|
+
const { vnodes: children, discarded } = normalizeChildren(slots);
|
|
2715
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2716
|
+
const childEval = explicitEvaluator ?? getHtmlChildrenEvaluator(tag);
|
|
2717
|
+
childEval?.evaluate(children);
|
|
2718
|
+
}
|
|
2719
|
+
if (asChild === true) {
|
|
2720
|
+
if (typeof as === "string") {
|
|
2721
|
+
slotValidator.assertExclusive();
|
|
2722
|
+
} else {
|
|
2723
|
+
if (discarded > 0) slotValidator.warnDiscardedChildren(discarded);
|
|
2724
|
+
const extraction = extractSlottable(children);
|
|
2725
|
+
if (extraction) {
|
|
2726
|
+
return extraction.rebuild(
|
|
2727
|
+
cloneVNode(extraction.child, {
|
|
2728
|
+
...finalDecoration["root"]?.attributes,
|
|
2729
|
+
class: className
|
|
2730
|
+
})
|
|
2731
|
+
);
|
|
2732
|
+
}
|
|
2733
|
+
if (children.length === 1 && children[0] !== void 0) {
|
|
2734
|
+
return cloneVNode(children[0], {
|
|
2735
|
+
...finalDecoration["root"]?.attributes,
|
|
2736
|
+
class: className
|
|
2737
|
+
});
|
|
2738
|
+
}
|
|
2739
|
+
slotValidator.assertSingleChild(children.length);
|
|
2740
|
+
return null;
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
return renderNormally(definition, tag, finalDecoration, slots);
|
|
2744
|
+
};
|
|
1970
2745
|
}
|
|
1971
2746
|
});
|
|
1972
2747
|
applyDisplayName(Component, options.name);
|
|
1973
|
-
if (typeof
|
|
1974
|
-
Object.assign(Component, { [COMPONENT_DEFAULT_TAG]:
|
|
2748
|
+
if (typeof defaultTag === "string") {
|
|
2749
|
+
Object.assign(Component, { [COMPONENT_DEFAULT_TAG]: defaultTag });
|
|
1975
2750
|
}
|
|
1976
2751
|
return Component;
|
|
1977
2752
|
}
|