praxis-kit 6.5.0 → 6.6.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/dist/{chunk-AM5J6PY3.js → chunk-OCG5VM4H.js} +34 -17
- package/dist/contract/index.d.ts +10 -0
- package/dist/contract/index.js +2 -0
- package/dist/guards/index.d.ts +11 -2
- package/dist/html/index.d.ts +98 -0
- package/dist/html/index.js +860 -0
- package/dist/lit/index.d.ts +10 -0
- package/dist/lit/index.js +34 -17
- package/dist/preact/index.d.ts +19 -0
- package/dist/preact/index.js +34 -17
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +1 -1
- package/dist/react/legacy.d.ts +2 -2
- package/dist/react/legacy.js +1 -1
- package/dist/{react-options-DoFNqNdY.d.ts → react-options-BUBVohU6.d.ts} +49 -33
- package/dist/solid/index.d.ts +19 -0
- package/dist/solid/index.js +34 -17
- package/dist/svelte/index.d.ts +10 -0
- package/dist/svelte/index.js +34 -17
- package/dist/vue/index.d.ts +10 -0
- package/dist/vue/index.js +34 -17
- package/dist/web/index.d.ts +10 -0
- package/dist/web/index.js +34 -17
- package/package.json +9 -2
|
@@ -28,6 +28,9 @@ function isNull(value) {
|
|
|
28
28
|
function isNonNull(value) {
|
|
29
29
|
return value != null;
|
|
30
30
|
}
|
|
31
|
+
function isNullish(value) {
|
|
32
|
+
return isNull(value) || value === void 0;
|
|
33
|
+
}
|
|
31
34
|
|
|
32
35
|
// ../../lib/primitive/src/utils/type-guards.ts
|
|
33
36
|
function isObject(value, excludeArrays = false) {
|
|
@@ -655,20 +658,29 @@ function isAriaAttributeValidForRole(attr, role) {
|
|
|
655
658
|
}
|
|
656
659
|
|
|
657
660
|
// ../../lib/primitive/src/guards/aria/is-aria-role.ts
|
|
661
|
+
function lookupImplicitRole(tag) {
|
|
662
|
+
return IMPLICIT_ROLE_RECORD[tag];
|
|
663
|
+
}
|
|
658
664
|
function isStrongImplicitRole(tag) {
|
|
659
|
-
|
|
660
|
-
return STRONG_ROLES_SET.has(
|
|
665
|
+
const role = lookupImplicitRole(tag);
|
|
666
|
+
return !isNullish(role) && STRONG_ROLES_SET.has(role);
|
|
661
667
|
}
|
|
662
|
-
function
|
|
663
|
-
|
|
664
|
-
return STANDALONE_ROLES_SET.has(
|
|
668
|
+
function hasStandaloneRole(tag) {
|
|
669
|
+
const role = lookupImplicitRole(tag);
|
|
670
|
+
return !isNullish(role) && STANDALONE_ROLES_SET.has(role);
|
|
665
671
|
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
return
|
|
672
|
+
var LIST_ELIGIBLE_INPUT_TYPES = /* @__PURE__ */ new Set(["text", "search", "tel", "url", "email"]);
|
|
673
|
+
function getInputImplicitRole(type, list) {
|
|
674
|
+
if (!isString(type)) return void 0;
|
|
675
|
+
const role = INPUT_TYPE_ROLE_MAP[type];
|
|
676
|
+
if (!role) return void 0;
|
|
677
|
+
if (!isNullish(list) && LIST_ELIGIBLE_INPUT_TYPES.has(type)) {
|
|
678
|
+
return "combobox";
|
|
679
|
+
}
|
|
680
|
+
return role;
|
|
669
681
|
}
|
|
670
682
|
function getConditionalImplicitRole(tag, ariaLabel, ariaLabelledBy) {
|
|
671
|
-
const isNamed = isString(ariaLabel) || isString(ariaLabelledBy);
|
|
683
|
+
const isNamed = isString(ariaLabel) && ariaLabel.trim().length > 0 || isString(ariaLabelledBy) && ariaLabelledBy.trim().length > 0;
|
|
672
684
|
if (!isNamed) return void 0;
|
|
673
685
|
if (tag === "section") return "region";
|
|
674
686
|
if (tag === "form") return "form";
|
|
@@ -720,7 +732,7 @@ function isTag(...args) {
|
|
|
720
732
|
// ../../lib/contract/src/aria/aria-role-policy.ts
|
|
721
733
|
function getImplicitRole(tag, props) {
|
|
722
734
|
if (tag in IMPLICIT_ROLE_RECORD) return IMPLICIT_ROLE_RECORD[tag];
|
|
723
|
-
if (tag === "input") return getInputImplicitRole(props?.type);
|
|
735
|
+
if (tag === "input") return getInputImplicitRole(props?.type, props?.list);
|
|
724
736
|
if (tag === "img") return props?.alt === "" ? "none" : "img";
|
|
725
737
|
if (tag === "section" || tag === "form") {
|
|
726
738
|
return getConditionalImplicitRole(tag, props?.["aria-label"], props?.["aria-labelledby"]);
|
|
@@ -1409,7 +1421,6 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1409
1421
|
if (!isIntrinsicTag(tag)) return { proceed: false, result: { props, violations: [] } };
|
|
1410
1422
|
const implicitRole = getImplicitRole(tag, props);
|
|
1411
1423
|
const hasRole2 = isNonNull(implicitRole) || isString(props.role) && props.role.length > 0;
|
|
1412
|
-
if (!hasRole2) return { proceed: false, result: { props, violations: [] } };
|
|
1413
1424
|
const normalized = _AriaPolicyEngine.#normalizeEmptyRole(tag, props);
|
|
1414
1425
|
const workingProps = normalized.normalized ? normalized.result.props : props;
|
|
1415
1426
|
const preExistingViolations = normalized.normalized ? normalized.result.violations : [];
|
|
@@ -1419,6 +1430,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1419
1430
|
tag,
|
|
1420
1431
|
implicitRole,
|
|
1421
1432
|
effectiveRole,
|
|
1433
|
+
hasRole: hasRole2,
|
|
1422
1434
|
props: workingProps,
|
|
1423
1435
|
preExistingViolations,
|
|
1424
1436
|
context: { tag, props: workingProps, implicitRole, effectiveRole }
|
|
@@ -1462,6 +1474,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1462
1474
|
static evaluate(tag, props) {
|
|
1463
1475
|
const derived = _AriaPolicyEngine.#deriveContext(tag, props);
|
|
1464
1476
|
if (!derived.proceed) return derived.result;
|
|
1477
|
+
if (!derived.hasRole)
|
|
1478
|
+
return { props: derived.props, violations: [...derived.preExistingViolations] };
|
|
1465
1479
|
const {
|
|
1466
1480
|
tag: narrowedTag,
|
|
1467
1481
|
implicitRole,
|
|
@@ -1486,10 +1500,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1486
1500
|
props: workingProps,
|
|
1487
1501
|
preExistingViolations
|
|
1488
1502
|
} = derived;
|
|
1489
|
-
const
|
|
1490
|
-
|
|
1491
|
-
context
|
|
1492
|
-
);
|
|
1503
|
+
const rules = derived.hasRole ? [..._AriaPolicyEngine.#getRules(context), ...extraRules] : extraRules;
|
|
1504
|
+
const { violations, fixes } = _AriaPolicyEngine.#runRules(rules, context);
|
|
1493
1505
|
const next = _AriaPolicyEngine.#applyFixes(narrowedTag, implicitRole, workingProps, fixes);
|
|
1494
1506
|
return { props: next, violations: [...preExistingViolations, ...violations] };
|
|
1495
1507
|
}
|
|
@@ -1688,7 +1700,7 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
|
|
|
1688
1700
|
static #checkStandaloneRegion({ tag, props, implicitRole }) {
|
|
1689
1701
|
const role = props.role;
|
|
1690
1702
|
if (role !== "region") return NO_VIOLATIONS2;
|
|
1691
|
-
if (!
|
|
1703
|
+
if (!hasStandaloneRole(tag)) return NO_VIOLATIONS2;
|
|
1692
1704
|
const diagnostic = HtmlDiagnostics.standaloneRegionOverride(tag, implicitRole ?? tag);
|
|
1693
1705
|
return [
|
|
1694
1706
|
{
|
|
@@ -3178,6 +3190,11 @@ function composeNormalizers(normalizers, fn) {
|
|
|
3178
3190
|
function whenDefined(key, value) {
|
|
3179
3191
|
return value === void 0 ? {} : { [key]: value };
|
|
3180
3192
|
}
|
|
3193
|
+
function mergeAriaRules(aria, rules) {
|
|
3194
|
+
if (!aria?.length) return rules;
|
|
3195
|
+
if (!rules?.length) return aria;
|
|
3196
|
+
return [...aria, ...rules];
|
|
3197
|
+
}
|
|
3181
3198
|
function resolveFactoryOptions(options = {}) {
|
|
3182
3199
|
const { styling, enforcement } = options;
|
|
3183
3200
|
const composedNormalizeFn = composeNormalizers(enforcement?.props, options.normalize);
|
|
@@ -3198,7 +3215,7 @@ function resolveFactoryOptions(options = {}) {
|
|
|
3198
3215
|
...whenDefined("defaultVariants", styling?.defaults),
|
|
3199
3216
|
...whenDefined("compoundVariants", styling?.compounds),
|
|
3200
3217
|
...whenDefined("normalizeFn", composedNormalizeFn),
|
|
3201
|
-
...whenDefined("ariaRules", enforcement?.aria),
|
|
3218
|
+
...whenDefined("ariaRules", mergeAriaRules(enforcement?.aria, enforcement?.rules)),
|
|
3202
3219
|
...whenDefined("childRules", enforcement?.children),
|
|
3203
3220
|
...whenDefined("exclusiveChildren", enforcement?.exclusiveChildren),
|
|
3204
3221
|
...whenDefined("allowText", enforcement?.allowText),
|
package/dist/contract/index.d.ts
CHANGED
|
@@ -231,6 +231,16 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
231
231
|
*/
|
|
232
232
|
readonly diagnostics?: Diagnostics$1 | DiagnosticsMode;
|
|
233
233
|
readonly aria?: readonly AriaRule[];
|
|
234
|
+
/**
|
|
235
|
+
* Rules that need `AriaPolicyEngine`'s fix-application/caching machinery
|
|
236
|
+
* (`AriaRule`'s `readsProps`, fixable `AriaFix` results) but have no
|
|
237
|
+
* relationship to ARIA semantics — an HTML fact or a security check like a
|
|
238
|
+
* dangerous-URL-scheme guard, for example. Evaluated together with `aria`
|
|
239
|
+
* (both run through the same engine, merged into one rule set) — this is a
|
|
240
|
+
* separate bucket purely so a non-ARIA rule doesn't have to sit under the
|
|
241
|
+
* misleading `aria` name to get the machinery it needs.
|
|
242
|
+
*/
|
|
243
|
+
readonly rules?: readonly AriaRule[];
|
|
234
244
|
readonly children?: readonly ChildRuleInput[];
|
|
235
245
|
/**
|
|
236
246
|
* When true, only children matching a `children` rule (or text, per `allowText`)
|
package/dist/contract/index.js
CHANGED
|
@@ -313,6 +313,7 @@ var selectedContract = stateContract([selectedProps]);
|
|
|
313
313
|
function mergeContracts(...contracts) {
|
|
314
314
|
const props = contracts.flatMap((c) => c.props ?? []);
|
|
315
315
|
const aria = contracts.flatMap((c) => c.aria ?? []);
|
|
316
|
+
const rules = contracts.flatMap((c) => c.rules ?? []);
|
|
316
317
|
const children = contracts.flatMap((c) => c.children ?? []);
|
|
317
318
|
let diagnostics;
|
|
318
319
|
let allowedAs;
|
|
@@ -323,6 +324,7 @@ function mergeContracts(...contracts) {
|
|
|
323
324
|
return {
|
|
324
325
|
...props.length > 0 && { props },
|
|
325
326
|
...aria.length > 0 && { aria },
|
|
327
|
+
...rules.length > 0 && { rules },
|
|
326
328
|
...children.length > 0 && { children },
|
|
327
329
|
...diagnostics !== void 0 && { diagnostics },
|
|
328
330
|
...allowedAs !== void 0 && { allowedAs }
|
package/dist/guards/index.d.ts
CHANGED
|
@@ -22,15 +22,24 @@ type TagChild = {
|
|
|
22
22
|
};
|
|
23
23
|
declare function isTag(tag: string, ...tags: readonly string[]): (child: unknown) => child is TagChild;
|
|
24
24
|
declare function isTag(child: unknown, tag: string, ...tags: readonly string[]): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* A vnode (or text node) that qualifies as flow content: text nodes
|
|
27
|
+
* (string/number) always qualify, and elements/components qualify unless
|
|
28
|
+
* their resolved tag is blocked — see `isFlowContent`.
|
|
29
|
+
*/
|
|
30
|
+
type FlowContentChild = string | number | TagChild;
|
|
25
31
|
/**
|
|
26
32
|
* Checks whether a vnode is flow content per the HTML content model: text nodes
|
|
27
33
|
* (string/number) always qualify, and elements/components qualify unless their
|
|
28
34
|
* resolved tag is in the blocked set.
|
|
35
|
+
*
|
|
36
|
+
* Returns a type guard (not a plain boolean predicate) so it can be used
|
|
37
|
+
* directly as a `ChildRuleInput.match`, which requires the narrowed type.
|
|
29
38
|
*/
|
|
30
|
-
declare function isFlowContent(...blockedTags: readonly string[]): (child: unknown) =>
|
|
39
|
+
declare function isFlowContent(...blockedTags: readonly string[]): (child: unknown) => child is FlowContentChild;
|
|
31
40
|
|
|
32
41
|
declare function isObject(value: unknown, excludeArrays: true): value is AnyRecord;
|
|
33
42
|
declare function isObject(value: unknown, excludeArrays?: false): value is object;
|
|
34
43
|
declare function isString(value: unknown): value is string;
|
|
35
44
|
|
|
36
|
-
export { getTag, isFlowContent, isObject, isString, isTag };
|
|
45
|
+
export { type FlowContentChild, type TagChild, getTag, isFlowContent, isObject, isString, isTag };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { ReadonlyDeep } from 'type-fest';
|
|
2
|
+
import { DiagnosticInput } from '../_shared/diagnostics.js';
|
|
3
|
+
|
|
4
|
+
type StringMap<T = unknown> = Record<string, T>;
|
|
5
|
+
type AnyRecord = StringMap<unknown>;
|
|
6
|
+
|
|
7
|
+
type IntrinsicTag = keyof HTMLElementTagNameMap;
|
|
8
|
+
|
|
9
|
+
declare const KNOWN_ARIA_ROLES: readonly ["alert", "alertdialog", "application", "article", "banner", "blockquote", "button", "caption", "cell", "checkbox", "code", "columnheader", "combobox", "complementary", "contentinfo", "definition", "deletion", "dialog", "document", "emphasis", "feed", "figure", "form", "generic", "grid", "gridcell", "group", "heading", "img", "insertion", "link", "list", "listbox", "listitem", "log", "main", "marquee", "math", "menu", "menubar", "menuitem", "menuitemcheckbox", "menuitemradio", "meter", "navigation", "none", "note", "option", "paragraph", "presentation", "progressbar", "radio", "radiogroup", "region", "row", "rowgroup", "rowheader", "scrollbar", "search", "searchbox", "separator", "slider", "spinbutton", "status", "strong", "subscript", "superscript", "switch", "tab", "table", "tablist", "tabpanel", "term", "textbox", "time", "timer", "toolbar", "tooltip", "tree", "treegrid", "treeitem"];
|
|
10
|
+
type KnownAriaRole = (typeof KNOWN_ARIA_ROLES)[number];
|
|
11
|
+
|
|
12
|
+
type AriaRole = KnownAriaRole | (string & {});
|
|
13
|
+
type IntrinsicProps = AnyRecord & {
|
|
14
|
+
role?: AriaRole;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type ValidResult = {
|
|
18
|
+
valid: true;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type AriaContext = {
|
|
22
|
+
readonly tag: IntrinsicTag;
|
|
23
|
+
readonly implicitRole: AriaRole | undefined;
|
|
24
|
+
readonly effectiveRole: string | undefined;
|
|
25
|
+
readonly props: ReadonlyDeep<IntrinsicProps>;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type RemoveAttributeFixKind = `removeAttribute:${string}`;
|
|
29
|
+
type InjectLiveFixKind = `injectLive:${string}`;
|
|
30
|
+
type FixKind = 'removeRole' | 'setRole' | 'normalizeRelevantAll' | RemoveAttributeFixKind | InjectLiveFixKind;
|
|
31
|
+
|
|
32
|
+
type AriaFixResult = {
|
|
33
|
+
applied: false;
|
|
34
|
+
next: ReadonlyDeep<IntrinsicProps>;
|
|
35
|
+
} | {
|
|
36
|
+
applied: true;
|
|
37
|
+
next: ReadonlyDeep<IntrinsicProps>;
|
|
38
|
+
previous: ReadonlyDeep<IntrinsicProps>;
|
|
39
|
+
};
|
|
40
|
+
type AriaFix = {
|
|
41
|
+
readonly kind: FixKind;
|
|
42
|
+
readonly priority?: number;
|
|
43
|
+
readonly source?: string;
|
|
44
|
+
readonly apply: (context: AriaContext) => AriaFixResult;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
type Severity = 'error' | 'warning' | (string & {});
|
|
48
|
+
|
|
49
|
+
type AriaInvalidBase<M extends string = string> = {
|
|
50
|
+
valid: false;
|
|
51
|
+
severity: Severity;
|
|
52
|
+
message?: M;
|
|
53
|
+
attribute?: string;
|
|
54
|
+
diagnostic?: DiagnosticInput;
|
|
55
|
+
};
|
|
56
|
+
type AriaInvalidWithFix<M extends string = string> = AriaInvalidBase<M> & {
|
|
57
|
+
fixable: true;
|
|
58
|
+
fix: AriaFix;
|
|
59
|
+
};
|
|
60
|
+
type AriaInvalidWithoutFix<M extends string = string> = AriaInvalidBase<M> & {
|
|
61
|
+
fixable: false;
|
|
62
|
+
};
|
|
63
|
+
type AriaInvalidResult<M extends string = string> = AriaInvalidWithFix<M> | AriaInvalidWithoutFix<M>;
|
|
64
|
+
type AriaResult = ValidResult | AriaInvalidResult;
|
|
65
|
+
|
|
66
|
+
type AriaRule<C extends AriaContext = AriaContext> = ((context: C) => readonly AriaResult[]) & {
|
|
67
|
+
readonly readsProps?: readonly string[];
|
|
68
|
+
readonly tags?: readonly string[];
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
declare const landmarkRoleRule: AriaRule;
|
|
72
|
+
declare function requireAccessibleName({ tag, props }: AriaContext): readonly AriaResult[];
|
|
73
|
+
declare const landmarkNameAdvisory: AriaRule;
|
|
74
|
+
declare const HTML_ARIA_RULES: readonly AriaRule[];
|
|
75
|
+
|
|
76
|
+
declare const roleNotPermittedRule: AriaRule;
|
|
77
|
+
|
|
78
|
+
declare const supportedInputTypeRule: AriaRule;
|
|
79
|
+
declare const checkedRequiresCheckableTypeRule: AriaRule;
|
|
80
|
+
declare const multipleRequiresSupportedTypeRule: AriaRule;
|
|
81
|
+
declare const maxLengthRequiresTextTypeRule: AriaRule;
|
|
82
|
+
declare const minLengthRequiresTextTypeRule: AriaRule;
|
|
83
|
+
declare const patternRequiresTextTypeRule: AriaRule;
|
|
84
|
+
declare const minRequiresNumericTypeRule: AriaRule;
|
|
85
|
+
declare const maxRequiresNumericTypeRule: AriaRule;
|
|
86
|
+
declare const stepRequiresNumericTypeRule: AriaRule;
|
|
87
|
+
declare const acceptRequiresFileTypeRule: AriaRule;
|
|
88
|
+
declare const captureRequiresFileTypeRule: AriaRule;
|
|
89
|
+
declare const sizeRequiresTextTypeRule: AriaRule;
|
|
90
|
+
declare const altRequiresImageTypeRule: AriaRule;
|
|
91
|
+
declare const heightRequiresImageTypeRule: AriaRule;
|
|
92
|
+
declare const widthRequiresImageTypeRule: AriaRule;
|
|
93
|
+
declare const inputAccessibleNameRule: AriaRule;
|
|
94
|
+
declare const passwordAutocompleteRule: AriaRule;
|
|
95
|
+
declare const requiredReadOnlyConflictRule: AriaRule;
|
|
96
|
+
declare const INPUT_RULES: readonly AriaRule[];
|
|
97
|
+
|
|
98
|
+
export { HTML_ARIA_RULES, INPUT_RULES, acceptRequiresFileTypeRule, altRequiresImageTypeRule, captureRequiresFileTypeRule, checkedRequiresCheckableTypeRule, heightRequiresImageTypeRule, inputAccessibleNameRule, landmarkNameAdvisory, landmarkRoleRule, maxLengthRequiresTextTypeRule, maxRequiresNumericTypeRule, minLengthRequiresTextTypeRule, minRequiresNumericTypeRule, multipleRequiresSupportedTypeRule, passwordAutocompleteRule, patternRequiresTextTypeRule, requireAccessibleName, requiredReadOnlyConflictRule, roleNotPermittedRule, sizeRequiresTextTypeRule, stepRequiresNumericTypeRule, supportedInputTypeRule, widthRequiresImageTypeRule };
|