stimeo-ui 0.2.0 → 0.3.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/CHANGELOG.md +163 -0
- package/dist/cable/index.d.ts +16 -16
- package/dist/cable/index.js.map +1 -1
- package/dist/controllers/accordion_controller.d.ts +3 -2
- package/dist/controllers/accordion_controller.js +10 -0
- package/dist/controllers/accordion_controller.js.map +1 -1
- package/dist/controllers/alert_dialog_controller.d.ts +64 -0
- package/dist/controllers/alert_dialog_controller.js +318 -0
- package/dist/controllers/alert_dialog_controller.js.map +1 -0
- package/dist/controllers/breadcrumb_controller.d.ts +97 -10
- package/dist/controllers/breadcrumb_controller.js +225 -13
- package/dist/controllers/breadcrumb_controller.js.map +1 -1
- package/dist/controllers/calendar_controller.d.ts +11 -1
- package/dist/controllers/calendar_controller.js +89 -22
- package/dist/controllers/calendar_controller.js.map +1 -1
- package/dist/controllers/carousel_controller.d.ts +115 -0
- package/dist/controllers/carousel_controller.js +313 -0
- package/dist/controllers/carousel_controller.js.map +1 -0
- package/dist/controllers/clipboard_controller.d.ts +72 -0
- package/dist/controllers/clipboard_controller.js +144 -0
- package/dist/controllers/clipboard_controller.js.map +1 -0
- package/dist/controllers/collapsible_controller.d.ts +70 -0
- package/dist/controllers/collapsible_controller.js +327 -0
- package/dist/controllers/collapsible_controller.js.map +1 -0
- package/dist/controllers/color_picker_controller.d.ts +87 -0
- package/dist/controllers/color_picker_controller.js +252 -0
- package/dist/controllers/color_picker_controller.js.map +1 -0
- package/dist/controllers/combobox_controller.d.ts +14 -1
- package/dist/controllers/combobox_controller.js +162 -23
- package/dist/controllers/combobox_controller.js.map +1 -1
- package/dist/controllers/command_palette_controller.d.ts +2 -0
- package/dist/controllers/command_palette_controller.js +194 -17
- package/dist/controllers/command_palette_controller.js.map +1 -1
- package/dist/controllers/confirm_controller.js.map +1 -1
- package/dist/controllers/context_menu_controller.d.ts +7 -6
- package/dist/controllers/context_menu_controller.js +32 -10
- package/dist/controllers/context_menu_controller.js.map +1 -1
- package/dist/controllers/count_up_controller.js +8 -1
- package/dist/controllers/count_up_controller.js.map +1 -1
- package/dist/controllers/currency_input_controller.d.ts +72 -0
- package/dist/controllers/currency_input_controller.js +147 -0
- package/dist/controllers/currency_input_controller.js.map +1 -0
- package/dist/controllers/data_grid_controller.d.ts +89 -0
- package/dist/controllers/data_grid_controller.js +246 -0
- package/dist/controllers/data_grid_controller.js.map +1 -0
- package/dist/controllers/date_range_picker_controller.d.ts +88 -0
- package/dist/controllers/date_range_picker_controller.js +441 -0
- package/dist/controllers/date_range_picker_controller.js.map +1 -0
- package/dist/controllers/dialog_controller.js.map +1 -1
- package/dist/controllers/dismissible_controller.d.ts +57 -0
- package/dist/controllers/dismissible_controller.js +117 -0
- package/dist/controllers/dismissible_controller.js.map +1 -0
- package/dist/controllers/drawer_controller.d.ts +96 -0
- package/dist/controllers/drawer_controller.js +630 -0
- package/dist/controllers/drawer_controller.js.map +1 -0
- package/dist/controllers/dropdown_controller.d.ts +1 -2
- package/dist/controllers/dropdown_controller.js.map +1 -1
- package/dist/controllers/editable_controller.d.ts +73 -0
- package/dist/controllers/editable_controller.js +169 -0
- package/dist/controllers/editable_controller.js.map +1 -0
- package/dist/controllers/file_dropzone_controller.d.ts +92 -0
- package/dist/controllers/file_dropzone_controller.js +165 -0
- package/dist/controllers/file_dropzone_controller.js.map +1 -0
- package/dist/controllers/filter_controller.d.ts +60 -0
- package/dist/controllers/filter_controller.js +86 -0
- package/dist/controllers/filter_controller.js.map +1 -0
- package/dist/controllers/flash_controller.js +36 -5
- package/dist/controllers/flash_controller.js.map +1 -1
- package/dist/controllers/focus_controller.d.ts +1 -1
- package/dist/controllers/focus_controller.js.map +1 -1
- package/dist/controllers/form_field_controller.js.map +1 -1
- package/dist/controllers/form_validation_controller.js +1 -1
- package/dist/controllers/form_validation_controller.js.map +1 -1
- package/dist/controllers/highlight_controller.js +6 -4
- package/dist/controllers/highlight_controller.js.map +1 -1
- package/dist/controllers/hover_card_controller.d.ts +1 -1
- package/dist/controllers/hover_card_controller.js.map +1 -1
- package/dist/controllers/intersection_controller.js +67 -19
- package/dist/controllers/intersection_controller.js.map +1 -1
- package/dist/controllers/lazy_frame_controller.js +54 -11
- package/dist/controllers/lazy_frame_controller.js.map +1 -1
- package/dist/controllers/listbox_controller.d.ts +9 -2
- package/dist/controllers/listbox_controller.js +257 -53
- package/dist/controllers/listbox_controller.js.map +1 -1
- package/dist/controllers/local_time_controller.js +2 -2
- package/dist/controllers/local_time_controller.js.map +1 -1
- package/dist/controllers/masonry_controller.d.ts +54 -0
- package/dist/controllers/masonry_controller.js +142 -0
- package/dist/controllers/masonry_controller.js.map +1 -0
- package/dist/controllers/menu_controller.d.ts +29 -11
- package/dist/controllers/menu_controller.js +104 -17
- package/dist/controllers/menu_controller.js.map +1 -1
- package/dist/controllers/menubar_controller.d.ts +142 -0
- package/dist/controllers/menubar_controller.js +785 -0
- package/dist/controllers/menubar_controller.js.map +1 -0
- package/dist/controllers/meter_controller.js.map +1 -1
- package/dist/controllers/multi_select_controller.d.ts +141 -0
- package/dist/controllers/multi_select_controller.js +755 -0
- package/dist/controllers/multi_select_controller.js.map +1 -0
- package/dist/controllers/navigation_menu_controller.d.ts +146 -0
- package/dist/controllers/navigation_menu_controller.js +511 -0
- package/dist/controllers/navigation_menu_controller.js.map +1 -0
- package/dist/controllers/nested_form_controller.d.ts +4 -5
- package/dist/controllers/nested_form_controller.js.map +1 -1
- package/dist/controllers/number_input_controller.d.ts +1 -1
- package/dist/controllers/number_input_controller.js +7 -0
- package/dist/controllers/number_input_controller.js.map +1 -1
- package/dist/controllers/otp_controller.js +18 -1
- package/dist/controllers/otp_controller.js.map +1 -1
- package/dist/controllers/overflow_indicator_controller.d.ts +15 -6
- package/dist/controllers/overflow_indicator_controller.js +246 -27
- package/dist/controllers/overflow_indicator_controller.js.map +1 -1
- package/dist/controllers/overflow_menu_controller.d.ts +78 -19
- package/dist/controllers/overflow_menu_controller.js +381 -57
- package/dist/controllers/overflow_menu_controller.js.map +1 -1
- package/dist/controllers/pagination_controller.d.ts +36 -5
- package/dist/controllers/pagination_controller.js +163 -32
- package/dist/controllers/pagination_controller.js.map +1 -1
- package/dist/controllers/password_reveal_controller.d.ts +49 -0
- package/dist/controllers/password_reveal_controller.js +117 -0
- package/dist/controllers/password_reveal_controller.js.map +1 -0
- package/dist/controllers/persist_controller.js +6 -6
- package/dist/controllers/persist_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.d.ts +2 -3
- package/dist/controllers/pointer_drag_controller.js +9 -1
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/popover_controller.d.ts +1 -2
- package/dist/controllers/popover_controller.js +2 -2
- package/dist/controllers/popover_controller.js.map +1 -1
- package/dist/controllers/portal_controller.d.ts +4 -4
- package/dist/controllers/portal_controller.js.map +1 -1
- package/dist/controllers/progress_controller.js.map +1 -1
- package/dist/controllers/radio_group_controller.js +22 -3
- package/dist/controllers/radio_group_controller.js.map +1 -1
- package/dist/controllers/range_slider_controller.d.ts +97 -0
- package/dist/controllers/range_slider_controller.js +192 -0
- package/dist/controllers/range_slider_controller.js.map +1 -0
- package/dist/controllers/rating_controller.js +16 -2
- package/dist/controllers/rating_controller.js.map +1 -1
- package/dist/controllers/read_more_controller.d.ts +52 -0
- package/dist/controllers/read_more_controller.js +238 -0
- package/dist/controllers/read_more_controller.js.map +1 -0
- package/dist/controllers/reading_progress_controller.js.map +1 -1
- package/dist/controllers/resizable_controller.d.ts +3 -1
- package/dist/controllers/resizable_controller.js +65 -1
- package/dist/controllers/resizable_controller.js.map +1 -1
- package/dist/controllers/roving_controller.js +17 -2
- package/dist/controllers/roving_controller.js.map +1 -1
- package/dist/controllers/scroll_area_controller.js +101 -14
- package/dist/controllers/scroll_area_controller.js.map +1 -1
- package/dist/controllers/scroll_restore_controller.d.ts +54 -0
- package/dist/controllers/scroll_restore_controller.js +93 -0
- package/dist/controllers/scroll_restore_controller.js.map +1 -0
- package/dist/controllers/scroll_visibility_controller.d.ts +6 -3
- package/dist/controllers/scroll_visibility_controller.js +40 -6
- package/dist/controllers/scroll_visibility_controller.js.map +1 -1
- package/dist/controllers/scrollspy_controller.d.ts +64 -15
- package/dist/controllers/scrollspy_controller.js +369 -74
- package/dist/controllers/scrollspy_controller.js.map +1 -1
- package/dist/controllers/separator_controller.d.ts +69 -0
- package/dist/controllers/separator_controller.js +96 -0
- package/dist/controllers/separator_controller.js.map +1 -0
- package/dist/controllers/sidebar_controller.d.ts +107 -0
- package/dist/controllers/sidebar_controller.js +761 -0
- package/dist/controllers/sidebar_controller.js.map +1 -0
- package/dist/controllers/skeleton_controller.js +1 -1
- package/dist/controllers/skeleton_controller.js.map +1 -1
- package/dist/controllers/slider_controller.d.ts +11 -1
- package/dist/controllers/slider_controller.js +32 -6
- package/dist/controllers/slider_controller.js.map +1 -1
- package/dist/controllers/sortable_controller.d.ts +3 -1
- package/dist/controllers/sortable_controller.js +34 -3
- package/dist/controllers/sortable_controller.js.map +1 -1
- package/dist/controllers/spinner_controller.js +1 -1
- package/dist/controllers/spinner_controller.js.map +1 -1
- package/dist/controllers/stepper_controller.d.ts +4 -0
- package/dist/controllers/stepper_controller.js +28 -12
- package/dist/controllers/stepper_controller.js.map +1 -1
- package/dist/controllers/stick_to_bottom_controller.d.ts +5 -6
- package/dist/controllers/stick_to_bottom_controller.js +9 -4
- package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
- package/dist/controllers/sticky_observer_controller.d.ts +17 -4
- package/dist/controllers/sticky_observer_controller.js +109 -20
- package/dist/controllers/sticky_observer_controller.js.map +1 -1
- package/dist/controllers/submit_once_controller.d.ts +2 -2
- package/dist/controllers/submit_once_controller.js.map +1 -1
- package/dist/controllers/switch_controller.js +1 -0
- package/dist/controllers/switch_controller.js.map +1 -1
- package/dist/controllers/tabs_controller.d.ts +13 -4
- package/dist/controllers/tabs_controller.js +26 -3
- package/dist/controllers/tabs_controller.js.map +1 -1
- package/dist/controllers/tags_input_controller.d.ts +91 -0
- package/dist/controllers/tags_input_controller.js +295 -0
- package/dist/controllers/tags_input_controller.js.map +1 -0
- package/dist/controllers/theme_controller.d.ts +1 -1
- package/dist/controllers/theme_controller.js +42 -13
- package/dist/controllers/theme_controller.js.map +1 -1
- package/dist/controllers/time_picker_controller.d.ts +67 -0
- package/dist/controllers/time_picker_controller.js +231 -0
- package/dist/controllers/time_picker_controller.js.map +1 -0
- package/dist/controllers/toast_controller.d.ts +5 -14
- package/dist/controllers/toast_controller.js +40 -14
- package/dist/controllers/toast_controller.js.map +1 -1
- package/dist/controllers/toggle_group_controller.js +23 -2
- package/dist/controllers/toggle_group_controller.js.map +1 -1
- package/dist/controllers/toolbar_controller.d.ts +53 -13
- package/dist/controllers/toolbar_controller.js +230 -31
- package/dist/controllers/toolbar_controller.js.map +1 -1
- package/dist/controllers/tooltip_controller.d.ts +1 -1
- package/dist/controllers/tooltip_controller.js.map +1 -1
- package/dist/controllers/transition_controller.d.ts +14 -8
- package/dist/controllers/transition_controller.js +153 -38
- package/dist/controllers/transition_controller.js.map +1 -1
- package/dist/controllers/tree_view_controller.d.ts +135 -0
- package/dist/controllers/tree_view_controller.js +691 -0
- package/dist/controllers/tree_view_controller.js.map +1 -0
- package/dist/index.d.ts +27 -1818
- package/dist/index.js +4256 -915
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.d.ts +375 -39
- package/dist/inspector/cli.js +228 -14
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.js +419 -48
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +26 -26
- package/dist/inspector/manifest.json +1054 -127
- package/package.json +5 -6
package/dist/inspector/cli.js
CHANGED
|
@@ -267,12 +267,17 @@ var DIAGNOSTIC_CODES = [
|
|
|
267
267
|
"unknown-action-method",
|
|
268
268
|
"orphan-target",
|
|
269
269
|
"missing-required-target",
|
|
270
|
+
"missing-conditional-target",
|
|
270
271
|
"missing-aria",
|
|
271
272
|
"invalid-aria-value",
|
|
272
273
|
"keyboard-inaccessible",
|
|
273
274
|
"unresolved-idref",
|
|
274
275
|
"managed-aria",
|
|
275
276
|
"composition-mismatch",
|
|
277
|
+
"missing-companion",
|
|
278
|
+
"undeclared-target",
|
|
279
|
+
"cardinality-violation",
|
|
280
|
+
"forbidden-aria",
|
|
276
281
|
"unknown-ignore-code"
|
|
277
282
|
];
|
|
278
283
|
|
|
@@ -290,6 +295,14 @@ function checkSource(source, manifest) {
|
|
|
290
295
|
if (valueStart === void 0 || valueEnd === void 0) return false;
|
|
291
296
|
return erbRanges.some(([start, end]) => start < valueEnd && end > valueStart);
|
|
292
297
|
};
|
|
298
|
+
const conditionHolds = (scope, identifier, when) => {
|
|
299
|
+
if (!when) return true;
|
|
300
|
+
const hostAttr = scope.attrs.find(
|
|
301
|
+
(a) => a.name === `data-${identifier}-${dasherize(when.value)}-value`
|
|
302
|
+
);
|
|
303
|
+
if (hostAttr && isDynamicValue(hostAttr)) return null;
|
|
304
|
+
return when.equals.includes(hostAttr ? hostAttr.value.trim() : when.default);
|
|
305
|
+
};
|
|
293
306
|
const suppressed = (node, code) => {
|
|
294
307
|
if (code === "unknown-ignore-code") return false;
|
|
295
308
|
let current = node;
|
|
@@ -337,7 +350,40 @@ function checkSource(source, manifest) {
|
|
|
337
350
|
if (found) found.push(el);
|
|
338
351
|
else byName.set(target, [el]);
|
|
339
352
|
};
|
|
353
|
+
const contentHolds = (scope, identifier, element, condition) => {
|
|
354
|
+
if (!condition) return true;
|
|
355
|
+
const nodes = targetNodes.get(scope)?.get(identifier)?.get(condition.target) ?? [];
|
|
356
|
+
let held = 0;
|
|
357
|
+
for (const node of nodes) if (isWithin(node, element)) held += 1;
|
|
358
|
+
if (condition.min !== void 0 && held < condition.min) return false;
|
|
359
|
+
if (condition.max !== void 0 && held > condition.max) return false;
|
|
360
|
+
return true;
|
|
361
|
+
};
|
|
362
|
+
const elementHolds = (element, condition) => !condition?.exceptTags.includes(element.tag);
|
|
363
|
+
const roleTally = /* @__PURE__ */ new Map();
|
|
364
|
+
const focusableRoleTally = /* @__PURE__ */ new Map();
|
|
365
|
+
const documentHolds = (condition) => {
|
|
366
|
+
if (condition === void 0) return false;
|
|
367
|
+
const tally = condition.focusable ? focusableRoleTally : roleTally;
|
|
368
|
+
return (tally.get(condition.role) ?? 0) >= condition.atLeast;
|
|
369
|
+
};
|
|
370
|
+
const declarationAttrs = /* @__PURE__ */ new Set();
|
|
371
|
+
for (const controller of Object.values(known)) {
|
|
372
|
+
for (const rule of controller.targetDeclarations) declarationAttrs.add(rule.attr);
|
|
373
|
+
}
|
|
374
|
+
const declarationCandidates = [];
|
|
340
375
|
walk(tree, (node) => {
|
|
376
|
+
if (declarationAttrs.size > 0 && node.attrs.some((a) => declarationAttrs.has(a.name))) {
|
|
377
|
+
declarationCandidates.push(node);
|
|
378
|
+
}
|
|
379
|
+
const roleAttr = node.attrs.find((a) => a.name === "role");
|
|
380
|
+
if (roleAttr && !isDynamicValue(roleAttr)) {
|
|
381
|
+
const role = roleAttr.value.trim();
|
|
382
|
+
roleTally.set(role, (roleTally.get(role) ?? 0) + 1);
|
|
383
|
+
if (isFocusable(node, "tab")) {
|
|
384
|
+
focusableRoleTally.set(role, (focusableRoleTally.get(role) ?? 0) + 1);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
341
387
|
for (const attr of node.attrs) {
|
|
342
388
|
if (attr.name === IGNORE_ATTR) {
|
|
343
389
|
for (const token of attr.value.split(/\s+/).filter((t) => t.length > 0)) {
|
|
@@ -416,7 +462,7 @@ function checkSource(source, manifest) {
|
|
|
416
462
|
);
|
|
417
463
|
continue;
|
|
418
464
|
}
|
|
419
|
-
const targetName = attr.value.trim();
|
|
465
|
+
const targetName = isDynamicValue(attr) ? "" : attr.value.trim();
|
|
420
466
|
if (targetName.length > 0 && !controller.targets.includes(targetName)) {
|
|
421
467
|
const best = nearestName(targetName, controller.targets);
|
|
422
468
|
report(
|
|
@@ -520,13 +566,36 @@ function checkSource(source, manifest) {
|
|
|
520
566
|
}
|
|
521
567
|
}
|
|
522
568
|
}
|
|
569
|
+
for (const { node, identifier } of scopes) {
|
|
570
|
+
const controller = known[identifier];
|
|
571
|
+
if (!controller) continue;
|
|
572
|
+
const present = presence.get(node)?.get(identifier) ?? /* @__PURE__ */ new Set();
|
|
573
|
+
for (const rule of controller.conditionalTargets) {
|
|
574
|
+
if (!present.has(rule.whenPresent)) continue;
|
|
575
|
+
const missing = rule.require.filter((target) => !present.has(target));
|
|
576
|
+
if (missing.length === 0) continue;
|
|
577
|
+
report(
|
|
578
|
+
node,
|
|
579
|
+
"missing-conditional-target",
|
|
580
|
+
"error",
|
|
581
|
+
`"${identifier}" has a "${rule.whenPresent}" target, which also requires ${list(missing)}.`,
|
|
582
|
+
node,
|
|
583
|
+
rule.suggestion
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
523
587
|
for (const { node, identifier } of scopes) {
|
|
524
588
|
const controller = known[identifier];
|
|
525
589
|
if (!controller) continue;
|
|
526
590
|
for (const req of controller.a11y) {
|
|
591
|
+
if (conditionHolds(node, identifier, req.when) !== true) continue;
|
|
527
592
|
const elements = req.target === "" ? [node] : targetNodes.get(node)?.get(identifier)?.get(req.target) ?? [];
|
|
593
|
+
if (req.whenDocument && !documentHolds(req.whenDocument)) continue;
|
|
594
|
+
const severity = documentHolds(req.escalateWhen) ? "error" : req.severity ?? "error";
|
|
528
595
|
for (const el of elements) {
|
|
529
|
-
|
|
596
|
+
if (!contentHolds(node, identifier, el, req.whenContains)) continue;
|
|
597
|
+
if (!elementHolds(el, req.whenElement)) continue;
|
|
598
|
+
checkA11y(report, el, identifier, req, severity);
|
|
530
599
|
}
|
|
531
600
|
}
|
|
532
601
|
}
|
|
@@ -573,6 +642,32 @@ function checkSource(source, manifest) {
|
|
|
573
642
|
}
|
|
574
643
|
}
|
|
575
644
|
}
|
|
645
|
+
for (const { node, identifier } of scopes) {
|
|
646
|
+
const controller = known[identifier];
|
|
647
|
+
if (!controller) continue;
|
|
648
|
+
for (const rule of controller.forbiddenAria) {
|
|
649
|
+
const elements = rule.target === "" ? [node] : targetNodes.get(node)?.get(identifier)?.get(rule.target) ?? [];
|
|
650
|
+
const where = rule.target === "" ? "scope element" : `"${rule.target}" target`;
|
|
651
|
+
for (const el of elements) {
|
|
652
|
+
if (!contentHolds(node, identifier, el, rule.whenContains)) continue;
|
|
653
|
+
for (const name of rule.attrs) {
|
|
654
|
+
const attr = el.attrs.find((a) => a.name === name);
|
|
655
|
+
if (!attr) continue;
|
|
656
|
+
if (rule.values && (isDynamicValue(attr) || !rule.values.includes(attr.value.trim()))) {
|
|
657
|
+
continue;
|
|
658
|
+
}
|
|
659
|
+
report(
|
|
660
|
+
el,
|
|
661
|
+
"forbidden-aria",
|
|
662
|
+
"warning",
|
|
663
|
+
`${name} on the ${where} of "${identifier}" contradicts the markup around it.`,
|
|
664
|
+
attr,
|
|
665
|
+
rule.suggestion
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
}
|
|
576
671
|
for (const { node, identifier } of scopes) {
|
|
577
672
|
const controller = known[identifier];
|
|
578
673
|
if (!controller) continue;
|
|
@@ -581,14 +676,7 @@ function checkSource(source, manifest) {
|
|
|
581
676
|
const elements = rule.target === "" ? [node] : targeted ?? (rule.fallbackToScope ? [node] : []);
|
|
582
677
|
const where = rule.target === "" || !targeted ? "scope element" : `"${rule.target}" target`;
|
|
583
678
|
const when = rule.when;
|
|
584
|
-
if (when)
|
|
585
|
-
const hostAttr = node.attrs.find(
|
|
586
|
-
(a) => a.name === `data-${identifier}-${dasherize(when.value)}-value`
|
|
587
|
-
);
|
|
588
|
-
if (hostAttr && isDynamicValue(hostAttr)) continue;
|
|
589
|
-
const hostEffective = hostAttr ? hostAttr.value.trim() : when.default;
|
|
590
|
-
if (!when.equals.includes(hostEffective)) continue;
|
|
591
|
-
}
|
|
679
|
+
if (conditionHolds(node, identifier, when) !== true) continue;
|
|
592
680
|
const hostContext = when ? ` (${when.value} ${list(when.equals)})` : "";
|
|
593
681
|
for (const el of elements) {
|
|
594
682
|
const declared = el.attrs.find((a) => a.name === "data-controller");
|
|
@@ -624,6 +712,113 @@ function checkSource(source, manifest) {
|
|
|
624
712
|
}
|
|
625
713
|
}
|
|
626
714
|
}
|
|
715
|
+
for (const { node, identifier } of scopes) {
|
|
716
|
+
const controller = known[identifier];
|
|
717
|
+
if (!controller) continue;
|
|
718
|
+
for (const rule of controller.companions) {
|
|
719
|
+
const elements = rule.target === "" ? [node] : targetNodes.get(node)?.get(identifier)?.get(rule.target) ?? [];
|
|
720
|
+
const where = rule.target === "" ? "scope element" : `"${rule.target}" target`;
|
|
721
|
+
for (const el of elements) {
|
|
722
|
+
const declared = el.attrs.find((a) => a.name === "data-controller");
|
|
723
|
+
if (declared && isDynamicValue(declared)) continue;
|
|
724
|
+
if (declared && controllerIdentifiers(declared.value).includes(rule.controller)) continue;
|
|
725
|
+
report(
|
|
726
|
+
el,
|
|
727
|
+
"missing-companion",
|
|
728
|
+
"error",
|
|
729
|
+
`The ${where} of "${identifier}" must also declare "${rule.controller}" in data-controller.`,
|
|
730
|
+
declared ?? el,
|
|
731
|
+
rule.suggestion,
|
|
732
|
+
// Appending to an existing list is unambiguous; creating the
|
|
733
|
+
// attribute from nothing is an insertion the anchor cannot express.
|
|
734
|
+
declared ? valueFix(
|
|
735
|
+
declared,
|
|
736
|
+
`${declared.value.trim()} ${rule.controller}`.trim(),
|
|
737
|
+
`Add "${rule.controller}" to data-controller`
|
|
738
|
+
) : void 0
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
for (const { node, identifier } of scopes) {
|
|
744
|
+
const controller = known[identifier];
|
|
745
|
+
if (!controller) continue;
|
|
746
|
+
if (controller.targetDeclarations.length === 0) continue;
|
|
747
|
+
const targetAttrName = `data-${identifier}-target`;
|
|
748
|
+
for (const rule of controller.targetDeclarations) {
|
|
749
|
+
for (const el of declarationCandidates) {
|
|
750
|
+
const marker = el.attrs.find((a) => a.name === rule.attr);
|
|
751
|
+
if (!marker || isDynamicValue(marker)) continue;
|
|
752
|
+
const value = marker.value.trim();
|
|
753
|
+
if (value.length === 0) continue;
|
|
754
|
+
if (rule.values && !rule.values.includes(value)) continue;
|
|
755
|
+
if (findOwner(el, identifier) !== node) continue;
|
|
756
|
+
const declaredAs = el.attrs.find((a) => a.name === targetAttrName);
|
|
757
|
+
if (declaredAs && !isDynamicValue(declaredAs) && declaredAs.value.trim() === rule.target) {
|
|
758
|
+
continue;
|
|
759
|
+
}
|
|
760
|
+
if (declaredAs && isDynamicValue(declaredAs)) continue;
|
|
761
|
+
report(
|
|
762
|
+
el,
|
|
763
|
+
"undeclared-target",
|
|
764
|
+
"error",
|
|
765
|
+
`${rule.attr}="${value}" inside "${identifier}" is not declared as its "${rule.target}" target, so the controller never manages it.`,
|
|
766
|
+
marker,
|
|
767
|
+
rule.suggestion
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
for (const { node, identifier } of scopes) {
|
|
773
|
+
const controller = known[identifier];
|
|
774
|
+
if (!controller) continue;
|
|
775
|
+
for (const rule of controller.cardinality) {
|
|
776
|
+
if (conditionHolds(node, identifier, rule.when) !== true) continue;
|
|
777
|
+
const byName = targetNodes.get(node)?.get(identifier);
|
|
778
|
+
const counted = byName?.get(rule.target) ?? [];
|
|
779
|
+
const containers = rule.within === "" ? [node] : byName?.get(rule.within) ?? [];
|
|
780
|
+
const what = describeCounted(rule.target, rule.attr, rule.values);
|
|
781
|
+
const where = rule.within === "" ? "controller scope" : `"${rule.within}" target`;
|
|
782
|
+
for (const container of containers) {
|
|
783
|
+
const matched = [];
|
|
784
|
+
for (const el of counted) {
|
|
785
|
+
if (!isWithin(el, container)) continue;
|
|
786
|
+
if (rule.attr === void 0) {
|
|
787
|
+
matched.push({ el, at: el });
|
|
788
|
+
continue;
|
|
789
|
+
}
|
|
790
|
+
const attr = el.attrs.find((a) => a.name === rule.attr);
|
|
791
|
+
if (!attr) continue;
|
|
792
|
+
if (rule.values && (isDynamicValue(attr) || !rule.values.includes(attr.value.trim()))) {
|
|
793
|
+
continue;
|
|
794
|
+
}
|
|
795
|
+
matched.push({ el, at: attr });
|
|
796
|
+
}
|
|
797
|
+
if (rule.max !== void 0 && matched.length > rule.max) {
|
|
798
|
+
for (const { el, at } of matched.slice(rule.max)) {
|
|
799
|
+
report(
|
|
800
|
+
el,
|
|
801
|
+
"cardinality-violation",
|
|
802
|
+
"error",
|
|
803
|
+
`"${identifier}" allows at most ${rule.max} ${what} per ${where}, but found ${matched.length}.`,
|
|
804
|
+
at,
|
|
805
|
+
rule.suggestion
|
|
806
|
+
);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
if (rule.min !== void 0 && matched.length < rule.min) {
|
|
810
|
+
report(
|
|
811
|
+
container,
|
|
812
|
+
"cardinality-violation",
|
|
813
|
+
"error",
|
|
814
|
+
`"${identifier}" requires at least ${rule.min} ${what} per ${where}, but found ${matched.length}.`,
|
|
815
|
+
container,
|
|
816
|
+
rule.suggestion
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
}
|
|
627
822
|
const ids = /* @__PURE__ */ new Set();
|
|
628
823
|
walk(tree, (node) => {
|
|
629
824
|
const id = node.attrs.find((a) => a.name === "id");
|
|
@@ -661,7 +856,7 @@ function checkSource(source, manifest) {
|
|
|
661
856
|
diagnostics.sort((a, b) => a.line - b.line || a.column - b.column);
|
|
662
857
|
return diagnostics;
|
|
663
858
|
}
|
|
664
|
-
function checkA11y(report, el, identifier, req) {
|
|
859
|
+
function checkA11y(report, el, identifier, req, severity) {
|
|
665
860
|
const groups = [
|
|
666
861
|
{ attrs: req.attrs, values: req.values },
|
|
667
862
|
...req.or ?? []
|
|
@@ -690,11 +885,12 @@ function checkA11y(report, el, identifier, req) {
|
|
|
690
885
|
}
|
|
691
886
|
}
|
|
692
887
|
if (!anyPresent) {
|
|
888
|
+
const verb = severity === "warning" ? "recommends" : "requires";
|
|
693
889
|
report(
|
|
694
890
|
el,
|
|
695
891
|
"missing-aria",
|
|
696
|
-
|
|
697
|
-
`"${identifier}"
|
|
892
|
+
severity,
|
|
893
|
+
`"${identifier}" ${verb} ${describeAttrs([...allowedByAttr.keys()])} on its ${where}.`,
|
|
698
894
|
el,
|
|
699
895
|
req.suggestion
|
|
700
896
|
);
|
|
@@ -713,6 +909,19 @@ function checkA11y(report, el, identifier, req) {
|
|
|
713
909
|
);
|
|
714
910
|
}
|
|
715
911
|
}
|
|
912
|
+
function isWithin(node, container) {
|
|
913
|
+
let current = node;
|
|
914
|
+
while (current) {
|
|
915
|
+
if (current === container) return true;
|
|
916
|
+
current = current.parent;
|
|
917
|
+
}
|
|
918
|
+
return false;
|
|
919
|
+
}
|
|
920
|
+
function describeCounted(target, attr, values) {
|
|
921
|
+
if (attr === void 0) return `"${target}" targets`;
|
|
922
|
+
const constrained = values && values.length > 0 ? ` set to ${list(values)}` : "";
|
|
923
|
+
return `"${target}" targets with ${attr}${constrained}`;
|
|
924
|
+
}
|
|
716
925
|
var NATIVE_FOCUSABLE_TAGS = /* @__PURE__ */ new Set(["button", "select", "textarea", "summary"]);
|
|
717
926
|
function isNativelyFocusable(el) {
|
|
718
927
|
if (NATIVE_FOCUSABLE_TAGS.has(el.tag)) return true;
|
|
@@ -866,10 +1075,15 @@ var CONTROLLER_ARRAY_FIELDS = [
|
|
|
866
1075
|
"actions",
|
|
867
1076
|
"events",
|
|
868
1077
|
"requiredTargets",
|
|
1078
|
+
"conditionalTargets",
|
|
869
1079
|
"a11y",
|
|
870
1080
|
"keyboard",
|
|
871
1081
|
"managedAria",
|
|
872
|
-
"compositions"
|
|
1082
|
+
"compositions",
|
|
1083
|
+
"companions",
|
|
1084
|
+
"targetDeclarations",
|
|
1085
|
+
"cardinality",
|
|
1086
|
+
"forbiddenAria"
|
|
873
1087
|
];
|
|
874
1088
|
function isCompatibleManifest(value) {
|
|
875
1089
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|