praxis-kit 6.2.3 → 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.
@@ -218,6 +218,7 @@ type AriaPhase = 'evaluate' | 'fix';
218
218
 
219
219
  type AriaRule<C extends AriaContext = AriaContext> = ((context: C) => readonly AriaResult[]) & {
220
220
  readonly readsProps?: readonly string[];
221
+ readonly tags?: readonly string[];
221
222
  };
222
223
 
223
224
  type PropNormalizer = (props: Readonly<AnyRecord & IntrinsicProps>) => Partial<AnyRecord & IntrinsicProps>;
@@ -230,6 +231,16 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
230
231
  */
231
232
  readonly diagnostics?: Diagnostics$1 | DiagnosticsMode;
232
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[];
233
244
  readonly children?: readonly ChildRuleInput[];
234
245
  /**
235
246
  * When true, only children matching a `children` rule (or text, per `allowText`)
@@ -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 }
@@ -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) => boolean;
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 };