stimeo-ui 0.4.0 → 0.5.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 +68 -0
- package/dist/controllers/announcer_controller.js.map +1 -1
- package/dist/controllers/aspect_ratio_controller.d.ts +2 -2
- package/dist/controllers/aspect_ratio_controller.js +1 -1
- package/dist/controllers/aspect_ratio_controller.js.map +1 -1
- package/dist/controllers/breadcrumb_controller.js +5 -1
- package/dist/controllers/breadcrumb_controller.js.map +1 -1
- package/dist/controllers/carousel_controller.js +5 -1
- package/dist/controllers/carousel_controller.js.map +1 -1
- package/dist/controllers/clipboard_controller.js +8 -3
- package/dist/controllers/clipboard_controller.js.map +1 -1
- package/dist/controllers/collapsible_controller.d.ts +1 -1
- package/dist/controllers/collapsible_controller.js +4 -1
- package/dist/controllers/collapsible_controller.js.map +1 -1
- package/dist/controllers/color_picker_controller.d.ts +2 -2
- package/dist/controllers/color_picker_controller.js +6 -2
- package/dist/controllers/color_picker_controller.js.map +1 -1
- package/dist/controllers/combobox_controller.js.map +1 -1
- package/dist/controllers/command_palette_controller.js.map +1 -1
- package/dist/controllers/context_menu_controller.d.ts +1 -1
- package/dist/controllers/context_menu_controller.js +2 -2
- package/dist/controllers/context_menu_controller.js.map +1 -1
- package/dist/controllers/countdown_controller.d.ts +5 -3
- package/dist/controllers/countdown_controller.js +5 -1
- package/dist/controllers/countdown_controller.js.map +1 -1
- package/dist/controllers/date_range_picker_controller.js +5 -1
- package/dist/controllers/date_range_picker_controller.js.map +1 -1
- package/dist/controllers/direct_upload_controller.d.ts +1 -1
- package/dist/controllers/direct_upload_controller.js +3 -3
- package/dist/controllers/direct_upload_controller.js.map +1 -1
- package/dist/controllers/empty_state_controller.d.ts +27 -7
- package/dist/controllers/empty_state_controller.js +107 -16
- package/dist/controllers/empty_state_controller.js.map +1 -1
- package/dist/controllers/flash_controller.d.ts +25 -5
- package/dist/controllers/flash_controller.js +161 -21
- package/dist/controllers/flash_controller.js.map +1 -1
- package/dist/controllers/form_validation_controller.js +8 -2
- package/dist/controllers/form_validation_controller.js.map +1 -1
- package/dist/controllers/frame_loading_controller.d.ts +19 -2
- package/dist/controllers/frame_loading_controller.js +94 -22
- package/dist/controllers/frame_loading_controller.js.map +1 -1
- package/dist/controllers/highlight_controller.d.ts +8 -4
- package/dist/controllers/highlight_controller.js +38 -1
- package/dist/controllers/highlight_controller.js.map +1 -1
- package/dist/controllers/idle_controller.d.ts +2 -1
- package/dist/controllers/idle_controller.js +13 -2
- package/dist/controllers/idle_controller.js.map +1 -1
- package/dist/controllers/listbox_controller.js.map +1 -1
- package/dist/controllers/local_time_controller.js +2 -0
- package/dist/controllers/local_time_controller.js.map +1 -1
- package/dist/controllers/masonry_controller.d.ts +1 -1
- package/dist/controllers/masonry_controller.js +1 -1
- package/dist/controllers/masonry_controller.js.map +1 -1
- package/dist/controllers/meter_controller.js +3 -1
- package/dist/controllers/meter_controller.js.map +1 -1
- package/dist/controllers/multi_select_controller.js.map +1 -1
- package/dist/controllers/network_status_controller.d.ts +15 -13
- package/dist/controllers/network_status_controller.js +1 -3
- package/dist/controllers/network_status_controller.js.map +1 -1
- package/dist/controllers/number_input_controller.d.ts +8 -0
- package/dist/controllers/number_input_controller.js +191 -24
- package/dist/controllers/number_input_controller.js.map +1 -1
- package/dist/controllers/overflow_menu_controller.js +1 -1
- package/dist/controllers/overflow_menu_controller.js.map +1 -1
- package/dist/controllers/pagination_controller.js +5 -1
- package/dist/controllers/pagination_controller.js.map +1 -1
- package/dist/controllers/password_strength_controller.d.ts +1 -1
- package/dist/controllers/password_strength_controller.js +1 -1
- package/dist/controllers/password_strength_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.js +10 -0
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/portal_controller.js +10 -0
- package/dist/controllers/portal_controller.js.map +1 -1
- package/dist/controllers/progress_controller.d.ts +1 -1
- package/dist/controllers/progress_controller.js +7 -3
- package/dist/controllers/progress_controller.js.map +1 -1
- package/dist/controllers/range_slider_controller.d.ts +23 -0
- package/dist/controllers/range_slider_controller.js +385 -94
- package/dist/controllers/range_slider_controller.js.map +1 -1
- package/dist/controllers/rating_controller.js +2 -0
- package/dist/controllers/rating_controller.js.map +1 -1
- package/dist/controllers/relative_time_controller.js +2 -0
- package/dist/controllers/relative_time_controller.js.map +1 -1
- package/dist/controllers/scroll_area_controller.d.ts +1 -1
- package/dist/controllers/scroll_area_controller.js +1 -1
- package/dist/controllers/scroll_area_controller.js.map +1 -1
- package/dist/controllers/separator_controller.js +13 -17
- package/dist/controllers/separator_controller.js.map +1 -1
- package/dist/controllers/skeleton_controller.d.ts +2 -2
- package/dist/controllers/skeleton_controller.js +71 -3
- package/dist/controllers/skeleton_controller.js.map +1 -1
- package/dist/controllers/slider_controller.d.ts +17 -1
- package/dist/controllers/slider_controller.js +325 -48
- package/dist/controllers/slider_controller.js.map +1 -1
- package/dist/controllers/spinner_controller.d.ts +15 -10
- package/dist/controllers/spinner_controller.js +18 -3
- package/dist/controllers/spinner_controller.js.map +1 -1
- package/dist/controllers/step_indicator_controller.d.ts +1 -1
- package/dist/controllers/step_indicator_controller.js +3 -1
- package/dist/controllers/step_indicator_controller.js.map +1 -1
- package/dist/controllers/stepper_controller.js +2 -0
- package/dist/controllers/stepper_controller.js.map +1 -1
- package/dist/controllers/switch_controller.d.ts +12 -8
- package/dist/controllers/switch_controller.js +162 -18
- package/dist/controllers/switch_controller.js.map +1 -1
- package/dist/controllers/textarea_autosize_controller.js +1 -1
- package/dist/controllers/textarea_autosize_controller.js.map +1 -1
- package/dist/controllers/time_picker_controller.d.ts +3 -0
- package/dist/controllers/time_picker_controller.js +6 -3
- package/dist/controllers/time_picker_controller.js.map +1 -1
- package/dist/controllers/tree_view_controller.d.ts +1 -2
- package/dist/controllers/tree_view_controller.js +19 -1
- package/dist/controllers/tree_view_controller.js.map +1 -1
- package/dist/index.js +1214 -307
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.d.ts +76 -1
- package/dist/inspector/cli.js +152 -0
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.js +212 -2
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +17 -17
- package/dist/inspector/manifest.json +408 -26
- package/package.json +3 -3
|
@@ -612,6 +612,26 @@ function readEntry(code, start, base) {
|
|
|
612
612
|
};
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
|
+
const number = /^[+-]?\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?/.exec(
|
|
616
|
+
code.slice(valueStart)
|
|
617
|
+
)?.[0];
|
|
618
|
+
if (number !== void 0) {
|
|
619
|
+
const end = valueStart + number.length;
|
|
620
|
+
const after = skipTrivia(code, end);
|
|
621
|
+
const whole = after >= code.length || code[after] === "," || code[after] === "}";
|
|
622
|
+
if (whole) {
|
|
623
|
+
return {
|
|
624
|
+
attr: {
|
|
625
|
+
name,
|
|
626
|
+
value: number,
|
|
627
|
+
...anchor,
|
|
628
|
+
valueStart: base + valueStart,
|
|
629
|
+
valueEnd: base + end
|
|
630
|
+
},
|
|
631
|
+
end
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
}
|
|
615
635
|
return { attr: { name, value: null, ...anchor }, end: skipValue(code, valueStart) };
|
|
616
636
|
}
|
|
617
637
|
function readKey(code, start) {
|
|
@@ -928,6 +948,7 @@ var DIAGNOSTIC_CODES = [
|
|
|
928
948
|
"unknown-controller",
|
|
929
949
|
"unknown-target",
|
|
930
950
|
"unknown-value",
|
|
951
|
+
"invalid-value",
|
|
931
952
|
"unknown-action-controller",
|
|
932
953
|
"unknown-action-method",
|
|
933
954
|
"orphan-target",
|
|
@@ -936,6 +957,7 @@ var DIAGNOSTIC_CODES = [
|
|
|
936
957
|
"missing-aria",
|
|
937
958
|
"invalid-aria-value",
|
|
938
959
|
"keyboard-inaccessible",
|
|
960
|
+
"invalid-host",
|
|
939
961
|
"unresolved-idref",
|
|
940
962
|
"managed-aria",
|
|
941
963
|
"composition-mismatch",
|
|
@@ -967,6 +989,36 @@ function checkSource(source, manifest) {
|
|
|
967
989
|
if (hostAttr && isDynamicValue(hostAttr)) return null;
|
|
968
990
|
return when.equals.includes(hostAttr ? hostAttr.value.trim() : when.default);
|
|
969
991
|
};
|
|
992
|
+
const isContentEditable2 = (element) => {
|
|
993
|
+
let current = element;
|
|
994
|
+
while (current && current.tag !== "#root") {
|
|
995
|
+
const attr = current.attrs.find((candidate) => candidate.name === "contenteditable");
|
|
996
|
+
if (attr) {
|
|
997
|
+
if (isDynamicValue(attr)) return null;
|
|
998
|
+
const value = attr.value.trim().toLowerCase();
|
|
999
|
+
if (value === "false") return false;
|
|
1000
|
+
if (value === "" || value === "true" || value === "plaintext-only") return true;
|
|
1001
|
+
}
|
|
1002
|
+
current = current.parent;
|
|
1003
|
+
}
|
|
1004
|
+
return false;
|
|
1005
|
+
};
|
|
1006
|
+
const hostIsAllowed = (element, rule) => {
|
|
1007
|
+
if (element.tag === "button") {
|
|
1008
|
+
if (rule.mode === "non-interactive") return false;
|
|
1009
|
+
const type = element.attrs.find((attr) => attr.name === "type");
|
|
1010
|
+
if (type && isDynamicValue(type)) return null;
|
|
1011
|
+
const effectiveType = type?.value.trim().toLowerCase() || "submit";
|
|
1012
|
+
return (rule.buttonTypes ?? []).includes(effectiveType);
|
|
1013
|
+
}
|
|
1014
|
+
if (ALWAYS_INTERACTIVE_HOSTS.has(element.tag)) return false;
|
|
1015
|
+
if ((element.tag === "a" || element.tag === "area") && hasAttr(element, "href")) return false;
|
|
1016
|
+
if ((element.tag === "audio" || element.tag === "video") && hasAttr(element, "controls")) {
|
|
1017
|
+
return false;
|
|
1018
|
+
}
|
|
1019
|
+
const editable = isContentEditable2(element);
|
|
1020
|
+
return editable === null ? null : !editable;
|
|
1021
|
+
};
|
|
970
1022
|
const suppressed = (node, code) => {
|
|
971
1023
|
if (code === "unknown-ignore-code") return false;
|
|
972
1024
|
let current = node;
|
|
@@ -1074,6 +1126,7 @@ function checkSource(source, manifest) {
|
|
|
1074
1126
|
focusableRoleTally.set(role, (focusableRoleTally.get(role) ?? 0) + 1);
|
|
1075
1127
|
}
|
|
1076
1128
|
}
|
|
1129
|
+
const authoredValueIdentifiers = /* @__PURE__ */ new Set();
|
|
1077
1130
|
for (const attr of node.attrs) {
|
|
1078
1131
|
if (attr.name === IGNORE_ATTR) {
|
|
1079
1132
|
for (const token of attr.value.split(/\s+/).filter((t) => t.length > 0)) {
|
|
@@ -1198,6 +1251,7 @@ function checkSource(source, manifest) {
|
|
|
1198
1251
|
attr
|
|
1199
1252
|
);
|
|
1200
1253
|
} else {
|
|
1254
|
+
authoredValueIdentifiers.add(parsed.identifier);
|
|
1201
1255
|
const controller = known[parsed.identifier];
|
|
1202
1256
|
const valid = controller?.values.some((v) => dasherize(v) === parsed.valueToken) ?? false;
|
|
1203
1257
|
if (!valid) {
|
|
@@ -1209,6 +1263,20 @@ function checkSource(source, manifest) {
|
|
|
1209
1263
|
attr,
|
|
1210
1264
|
didYouMean(parsed.valueToken, (controller?.values ?? []).map(dasherize))
|
|
1211
1265
|
);
|
|
1266
|
+
} else if (!isDynamicValue(attr)) {
|
|
1267
|
+
const constraint = controller?.valueConstraints.find(
|
|
1268
|
+
(candidate) => dasherize(candidate.value) === parsed.valueToken
|
|
1269
|
+
);
|
|
1270
|
+
if (constraint && !valueSatisfiesConstraint(attr.value, constraint)) {
|
|
1271
|
+
report(
|
|
1272
|
+
node,
|
|
1273
|
+
"invalid-value",
|
|
1274
|
+
"error",
|
|
1275
|
+
`Invalid value "${attr.value.trim()}" for "${parsed.identifier}.${parsed.valueToken}". Expected ${describeValueConstraint(constraint)}.`,
|
|
1276
|
+
attr,
|
|
1277
|
+
constraint.suggestion
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1212
1280
|
}
|
|
1213
1281
|
}
|
|
1214
1282
|
continue;
|
|
@@ -1243,6 +1311,34 @@ function checkSource(source, manifest) {
|
|
|
1243
1311
|
}
|
|
1244
1312
|
}
|
|
1245
1313
|
}
|
|
1314
|
+
for (const identifier of authoredValueIdentifiers) {
|
|
1315
|
+
const controller = known[identifier];
|
|
1316
|
+
if (!controller) continue;
|
|
1317
|
+
for (const relation of controller.valueRelations) {
|
|
1318
|
+
const leftAttr = node.attrs.find(
|
|
1319
|
+
(attr) => attr.name === `data-${identifier}-${dasherize(relation.left)}-value`
|
|
1320
|
+
);
|
|
1321
|
+
const rightAttr = node.attrs.find(
|
|
1322
|
+
(attr) => attr.name === `data-${identifier}-${dasherize(relation.right)}-value`
|
|
1323
|
+
);
|
|
1324
|
+
const at = rightAttr ?? leftAttr;
|
|
1325
|
+
if (!at || leftAttr && isDynamicValue(leftAttr) || rightAttr && isDynamicValue(rightAttr)) {
|
|
1326
|
+
continue;
|
|
1327
|
+
}
|
|
1328
|
+
const left = leftAttr ? decodeNumericValue(leftAttr.value) : relation.leftDefault;
|
|
1329
|
+
const right = rightAttr ? decodeNumericValue(rightAttr.value) : relation.rightDefault;
|
|
1330
|
+
if (!Number.isFinite(left) || !Number.isFinite(right)) continue;
|
|
1331
|
+
if (relation.operator === "less-than-or-equal" && left <= right) continue;
|
|
1332
|
+
report(
|
|
1333
|
+
node,
|
|
1334
|
+
"invalid-value",
|
|
1335
|
+
"error",
|
|
1336
|
+
`Invalid values for "${identifier}": "${relation.left}" (${left}) must be less than or equal to "${relation.right}" (${right}).`,
|
|
1337
|
+
at,
|
|
1338
|
+
relation.suggestion
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1246
1342
|
});
|
|
1247
1343
|
const scopeIsComplete = (container, scope, identifier) => container.origin === "markup" && !targetsUnreadable(container, scope, identifier);
|
|
1248
1344
|
for (const { node, identifier } of scopes) {
|
|
@@ -1320,6 +1416,28 @@ function checkSource(source, manifest) {
|
|
|
1320
1416
|
}
|
|
1321
1417
|
}
|
|
1322
1418
|
}
|
|
1419
|
+
for (const { node, identifier } of scopes) {
|
|
1420
|
+
const controller = known[identifier];
|
|
1421
|
+
if (!controller) continue;
|
|
1422
|
+
for (const rule of controller.hosts) {
|
|
1423
|
+
const elements = rule.target === "" ? [node] : targetNodes.get(node)?.get(identifier)?.get(rule.target) ?? [];
|
|
1424
|
+
const where = rule.target === "" ? "scope element" : `"${rule.target}" target`;
|
|
1425
|
+
for (const element of elements) {
|
|
1426
|
+
if (!hasReadableMarkup(element)) continue;
|
|
1427
|
+
if (hostIsAllowed(element, rule) !== false) continue;
|
|
1428
|
+
const type = element.attrs.find((attr) => attr.name === "type");
|
|
1429
|
+
const detail = element.tag === "button" ? `the unsupported ${type ? `type="${type.value}"` : 'implicit type="submit"'}` : `an unsupported interactive <${element.tag}>`;
|
|
1430
|
+
report(
|
|
1431
|
+
element,
|
|
1432
|
+
"invalid-host",
|
|
1433
|
+
"error",
|
|
1434
|
+
`The ${where} of "${identifier}" uses ${detail} host.`,
|
|
1435
|
+
type ?? element,
|
|
1436
|
+
rule.suggestion
|
|
1437
|
+
);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1323
1441
|
for (const { node, identifier } of scopes) {
|
|
1324
1442
|
const controller = known[identifier];
|
|
1325
1443
|
if (!controller) continue;
|
|
@@ -1561,6 +1679,23 @@ function checkSource(source, manifest) {
|
|
|
1561
1679
|
diagnostics.sort((a, b) => a.line - b.line || a.column - b.column);
|
|
1562
1680
|
return diagnostics;
|
|
1563
1681
|
}
|
|
1682
|
+
function valueSatisfiesConstraint(raw, constraint) {
|
|
1683
|
+
const value = decodeNumericValue(raw);
|
|
1684
|
+
if (Number.isNaN(value)) return false;
|
|
1685
|
+
if (constraint.finite && !Number.isFinite(value)) return false;
|
|
1686
|
+
if (constraint.greaterThan !== void 0 && !(value > constraint.greaterThan)) return false;
|
|
1687
|
+
return true;
|
|
1688
|
+
}
|
|
1689
|
+
function decodeNumericValue(raw) {
|
|
1690
|
+
return Number(raw.replace(/_/g, ""));
|
|
1691
|
+
}
|
|
1692
|
+
function describeValueConstraint(constraint) {
|
|
1693
|
+
const parts = [constraint.finite ? "a finite number" : "a number"];
|
|
1694
|
+
if (constraint.greaterThan !== void 0) {
|
|
1695
|
+
parts.push(`greater than ${constraint.greaterThan}`);
|
|
1696
|
+
}
|
|
1697
|
+
return parts.join(" ");
|
|
1698
|
+
}
|
|
1564
1699
|
var UNRESOLVED_TARGET_HINT = "Part of this scope is rendered by a helper or a non-literal data: hash, so the target may exist at runtime.";
|
|
1565
1700
|
var UNRESOLVED_HOST_HINT = "An enclosing helper's data: option is not a literal hash, so the host controller may be declared at runtime.";
|
|
1566
1701
|
function hasReadableMarkup(el) {
|
|
@@ -1633,6 +1768,20 @@ function describeCounted(target, attr, values) {
|
|
|
1633
1768
|
return `"${target}" targets with ${attr}${constrained}`;
|
|
1634
1769
|
}
|
|
1635
1770
|
var NATIVE_FOCUSABLE_TAGS = /* @__PURE__ */ new Set(["button", "select", "textarea", "summary"]);
|
|
1771
|
+
var ALWAYS_INTERACTIVE_HOSTS = /* @__PURE__ */ new Set([
|
|
1772
|
+
"input",
|
|
1773
|
+
"select",
|
|
1774
|
+
"textarea",
|
|
1775
|
+
"label",
|
|
1776
|
+
"summary",
|
|
1777
|
+
"details",
|
|
1778
|
+
"iframe",
|
|
1779
|
+
"object",
|
|
1780
|
+
"embed"
|
|
1781
|
+
]);
|
|
1782
|
+
function hasAttr(element, name) {
|
|
1783
|
+
return element.attrs.some((attr) => attr.name === name);
|
|
1784
|
+
}
|
|
1636
1785
|
function isNativelyFocusable(el) {
|
|
1637
1786
|
if (NATIVE_FOCUSABLE_TAGS.has(el.tag)) return true;
|
|
1638
1787
|
if (el.tag === "input") {
|
|
@@ -1783,12 +1932,15 @@ function isCheckableFile(path) {
|
|
|
1783
1932
|
var CONTROLLER_ARRAY_FIELDS = [
|
|
1784
1933
|
"targets",
|
|
1785
1934
|
"values",
|
|
1935
|
+
"valueConstraints",
|
|
1936
|
+
"valueRelations",
|
|
1786
1937
|
"actions",
|
|
1787
1938
|
"events",
|
|
1788
1939
|
"requiredTargets",
|
|
1789
1940
|
"conditionalTargets",
|
|
1790
1941
|
"a11y",
|
|
1791
1942
|
"keyboard",
|
|
1943
|
+
"hosts",
|
|
1792
1944
|
"managedAria",
|
|
1793
1945
|
"compositions",
|
|
1794
1946
|
"companions",
|
|
@@ -2261,6 +2413,37 @@ var CONTROLLER_CONTRACT_SCHEMA = {
|
|
|
2261
2413
|
id: { type: "string", description: 'Controller identifier, e.g. "stimeo--tabs".' },
|
|
2262
2414
|
targets: STRING_ARRAY,
|
|
2263
2415
|
values: STRING_ARRAY,
|
|
2416
|
+
valueConstraints: {
|
|
2417
|
+
type: "array",
|
|
2418
|
+
description: "Statically checkable semantic bounds on authored Stimulus Values.",
|
|
2419
|
+
items: {
|
|
2420
|
+
type: "object",
|
|
2421
|
+
properties: {
|
|
2422
|
+
value: { type: "string", description: "Camel-case declared Value name." },
|
|
2423
|
+
type: { type: "string", enum: ["number"] },
|
|
2424
|
+
finite: { type: "boolean" },
|
|
2425
|
+
greaterThan: { type: "number" },
|
|
2426
|
+
suggestion: { type: "string" }
|
|
2427
|
+
},
|
|
2428
|
+
required: ["value", "type", "suggestion"]
|
|
2429
|
+
}
|
|
2430
|
+
},
|
|
2431
|
+
valueRelations: {
|
|
2432
|
+
type: "array",
|
|
2433
|
+
description: "Statically checkable relationships between authored Stimulus Values.",
|
|
2434
|
+
items: {
|
|
2435
|
+
type: "object",
|
|
2436
|
+
properties: {
|
|
2437
|
+
left: { type: "string", description: "Camel-case left Value name." },
|
|
2438
|
+
operator: { type: "string", enum: ["less-than-or-equal"] },
|
|
2439
|
+
right: { type: "string", description: "Camel-case right Value name." },
|
|
2440
|
+
leftDefault: { type: "number" },
|
|
2441
|
+
rightDefault: { type: "number" },
|
|
2442
|
+
suggestion: { type: "string" }
|
|
2443
|
+
},
|
|
2444
|
+
required: ["left", "operator", "right", "leftDefault", "rightDefault", "suggestion"]
|
|
2445
|
+
}
|
|
2446
|
+
},
|
|
2264
2447
|
actions: STRING_ARRAY,
|
|
2265
2448
|
events: STRING_ARRAY,
|
|
2266
2449
|
requiredTargets: {
|
|
@@ -2342,6 +2525,30 @@ var CONTROLLER_CONTRACT_SCHEMA = {
|
|
|
2342
2525
|
required: ["target", "suggestion"]
|
|
2343
2526
|
}
|
|
2344
2527
|
},
|
|
2528
|
+
hosts: {
|
|
2529
|
+
type: "array",
|
|
2530
|
+
description: "Scope or target host-element contracts that prevent the controller from competing with an incompatible native interaction.",
|
|
2531
|
+
items: {
|
|
2532
|
+
type: "object",
|
|
2533
|
+
properties: {
|
|
2534
|
+
target: {
|
|
2535
|
+
type: "string",
|
|
2536
|
+
description: 'Target name; "" means the data-controller element itself.'
|
|
2537
|
+
},
|
|
2538
|
+
mode: {
|
|
2539
|
+
type: "string",
|
|
2540
|
+
enum: ["non-interactive", "non-interactive-or-button"],
|
|
2541
|
+
description: "Supported static host family."
|
|
2542
|
+
},
|
|
2543
|
+
buttonTypes: {
|
|
2544
|
+
...STRING_ARRAY,
|
|
2545
|
+
description: "Literal button types admitted by non-interactive-or-button."
|
|
2546
|
+
},
|
|
2547
|
+
suggestion: { type: "string" }
|
|
2548
|
+
},
|
|
2549
|
+
required: ["target", "mode", "suggestion"]
|
|
2550
|
+
}
|
|
2551
|
+
},
|
|
2345
2552
|
managedAria: {
|
|
2346
2553
|
type: "array",
|
|
2347
2554
|
description: "ARIA the controller recomputes at runtime; authoring it is a warning.",
|
|
@@ -2478,12 +2685,15 @@ var CONTROLLER_CONTRACT_SCHEMA = {
|
|
|
2478
2685
|
"id",
|
|
2479
2686
|
"targets",
|
|
2480
2687
|
"values",
|
|
2688
|
+
"valueConstraints",
|
|
2689
|
+
"valueRelations",
|
|
2481
2690
|
"actions",
|
|
2482
2691
|
"events",
|
|
2483
2692
|
"requiredTargets",
|
|
2484
2693
|
"conditionalTargets",
|
|
2485
2694
|
"a11y",
|
|
2486
2695
|
"keyboard",
|
|
2696
|
+
"hosts",
|
|
2487
2697
|
"managedAria",
|
|
2488
2698
|
"compositions",
|
|
2489
2699
|
"companions",
|
|
@@ -2502,7 +2712,7 @@ var TOOL_DESCRIPTORS = [
|
|
|
2502
2712
|
{
|
|
2503
2713
|
name: "stimeo_check",
|
|
2504
2714
|
title: "Check Stimeo UI markup",
|
|
2505
|
-
description: "Statically check HTML or ERB source that uses Stimeo UI (stimeo--*) controllers \u2014 the headless, accessible Stimulus UI component library for Rails. Returns a CheckReport with diagnostics \u2014 unknown controllers/targets/values/action methods, missing required targets, missing or invalid author-supplied ARIA, keyboard-focusability prerequisites, and misaligned cross-controller composition values \u2014 each with a fix suggestion when available. Call this to validate any Rails view, ERB template, or HTML you write or edit with these components, before finalizing it; ok=true means no errors.",
|
|
2715
|
+
description: "Statically check HTML or ERB source that uses Stimeo UI (stimeo--*) controllers \u2014 the headless, accessible Stimulus UI component library for Rails. Returns a CheckReport with diagnostics \u2014 unknown controllers/targets/values/action methods, missing required targets, missing or invalid author-supplied ARIA, keyboard-focusability prerequisites, incompatible interactive hosts, and misaligned cross-controller composition values \u2014 each with a fix suggestion when available. Call this to validate any Rails view, ERB template, or HTML you write or edit with these components, before finalizing it; ok=true means no errors.",
|
|
2506
2716
|
annotations: READ_ONLY_ANNOTATIONS,
|
|
2507
2717
|
inputSchema: {
|
|
2508
2718
|
type: "object",
|
|
@@ -2536,7 +2746,7 @@ var TOOL_DESCRIPTORS = [
|
|
|
2536
2746
|
{
|
|
2537
2747
|
name: "stimeo_controller",
|
|
2538
2748
|
title: "Get one controller's usage contract",
|
|
2539
|
-
description: 'Fetch the full usage contract of one Stimeo UI controller by identifier (e.g. "stimeo--tabs"): targets, values, actions, events, required targets, and the accessibility contract \u2014 author-supplied ARIA requirements, keyboard-focusability prerequisites, the ARIA attributes the controller manages at runtime (which the author must NOT hardcode), and cross-controller composition value alignments. Use it after stimeo_catalog to write correct, accessible Rails ERB or HTML markup for that Stimulus component.',
|
|
2749
|
+
description: 'Fetch the full usage contract of one Stimeo UI controller by identifier (e.g. "stimeo--tabs"): targets, values, actions, events, required targets, and the accessibility contract \u2014 author-supplied ARIA requirements, keyboard-focusability prerequisites, supported host-element shapes, the ARIA attributes the controller manages at runtime (which the author must NOT hardcode), and cross-controller composition value alignments. Use it after stimeo_catalog to write correct, accessible Rails ERB or HTML markup for that Stimulus component.',
|
|
2540
2750
|
annotations: READ_ONLY_ANNOTATIONS,
|
|
2541
2751
|
inputSchema: {
|
|
2542
2752
|
type: "object",
|