@ggui-ai/ui-gen 0.15.0 → 0.17.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.
Files changed (123) hide show
  1. package/dist/adapters/generation-dispatch.d.ts +24 -4
  2. package/dist/adapters/generation-dispatch.js +5188 -3920
  3. package/dist/adapters/generation-dispatch.js.map +1 -1
  4. package/dist/adapters/index.js +33 -26
  5. package/dist/adapters/index.js.map +1 -1
  6. package/dist/advanced/index.d.ts +22 -13
  7. package/dist/advanced/index.js +4889 -3561
  8. package/dist/advanced/index.js.map +1 -1
  9. package/dist/blueprint-validator.js +8 -12
  10. package/dist/blueprint-validator.js.map +1 -1
  11. package/dist/boilerplate.d.ts +19 -1
  12. package/dist/boilerplate.js +671 -254
  13. package/dist/boilerplate.js.map +1 -1
  14. package/dist/check/index.d.ts +17 -3
  15. package/dist/check/index.js +34 -25
  16. package/dist/check/index.js.map +1 -1
  17. package/dist/compose.js +1 -1
  18. package/dist/compose.js.map +1 -1
  19. package/dist/create-ui-generator-C8Ki9Wz1.d.ts +189 -0
  20. package/dist/design-mode-DLufhrNp.d.ts +61 -0
  21. package/dist/{dispatch-BuZfTh9r.d.ts → dispatch-D2htzi9h.d.ts} +4 -1
  22. package/dist/evaluation/axis-checks/index.d.ts +4 -3
  23. package/dist/evaluation/axis-checks/index.js +300 -14
  24. package/dist/evaluation/axis-checks/index.js.map +1 -1
  25. package/dist/evaluation/axis-checks/registry.d.ts +2 -1
  26. package/dist/evaluation/axis-checks/registry.js +253 -1
  27. package/dist/evaluation/axis-checks/registry.js.map +1 -1
  28. package/dist/evaluation/index.d.ts +297 -5
  29. package/dist/evaluation/index.js +4515 -120
  30. package/dist/evaluation/index.js.map +1 -1
  31. package/dist/fragments/index.js +1 -1
  32. package/dist/fragments/index.js.map +1 -1
  33. package/dist/{generate-BTfvELgl.d.ts → generate-9IeNT4ZY.d.ts} +10 -1
  34. package/dist/harness/check/runtime-render/index.d.ts +3 -1
  35. package/dist/harness/check/runtime-render/index.js +8 -12
  36. package/dist/harness/check/runtime-render/index.js.map +1 -1
  37. package/dist/harness/index.d.ts +3 -1
  38. package/dist/harness/index.js +913 -441
  39. package/dist/harness/index.js.map +1 -1
  40. package/dist/harness/llm-trace-sink.d.ts +3 -3
  41. package/dist/harness/llm-trace-sink.js.map +1 -1
  42. package/dist/harness/prompts.d.ts +2 -1
  43. package/dist/harness/prompts.js +6 -3
  44. package/dist/harness/prompts.js.map +1 -1
  45. package/dist/harness/result-types.d.ts +17 -5
  46. package/dist/harness/result-types.js.map +1 -1
  47. package/dist/harness/runtime.d.ts +28 -3
  48. package/dist/harness/runtime.js +702 -274
  49. package/dist/harness/runtime.js.map +1 -1
  50. package/dist/harness/types-public.d.ts +39 -1
  51. package/dist/harness/types-public.js +913 -441
  52. package/dist/harness/types-public.js.map +1 -1
  53. package/dist/harness/validator-trace-sink.d.ts +2 -1
  54. package/dist/index.d.ts +32 -6
  55. package/dist/index.js +4899 -3560
  56. package/dist/index.js.map +1 -1
  57. package/dist/patch.d.ts +3 -1
  58. package/dist/{prompts-BVhtH3M1.d.ts → prompts-YU9piOgs.d.ts} +21 -45
  59. package/dist/providers/index.d.ts +2 -2
  60. package/dist/providers/index.js.map +1 -1
  61. package/dist/styling-profile-CxfvV48g.d.ts +35 -0
  62. package/dist/tools/get-primitives-ts.d.ts +1 -1
  63. package/dist/tools/get-primitives-ts.js +1 -1
  64. package/dist/tools/get-primitives-ts.js.map +1 -1
  65. package/dist/{types-public-CkNWEov9.d.ts → types-public-DVSssdc-.d.ts} +85 -5
  66. package/dist/validation/index.d.ts +1 -1
  67. package/dist/validation/index.js +4 -4
  68. package/dist/validation/index.js.map +1 -1
  69. package/dist/workflows.d.ts +3 -1
  70. package/package.json +12 -12
  71. package/src/adapters/generation-dispatch.ts +62 -4
  72. package/src/adapters/provider-router.ts +7 -6
  73. package/src/adapters/tools.ts +5 -5
  74. package/src/advanced/generator.ts +11 -10
  75. package/src/advanced/index.ts +5 -4
  76. package/src/boilerplate/free-design-prompt.ts +336 -0
  77. package/src/boilerplate/generate.ts +10 -1
  78. package/src/boilerplate/hard-sections.ts +257 -0
  79. package/src/boilerplate/render.ts +32 -8
  80. package/src/boilerplate/styling-profile.ts +166 -0
  81. package/src/boilerplate/system-prompt.ts +101 -237
  82. package/src/boilerplate/templates/base-free.tsx.tmpl +24 -0
  83. package/src/check/run-tier0.ts +82 -20
  84. package/src/coding-agent/tools.ts +8 -2
  85. package/src/contract-context.ts +43 -14
  86. package/src/create-harness.ts +15 -0
  87. package/src/create-ui-generator.ts +112 -27
  88. package/src/design-mode.ts +192 -0
  89. package/src/design-system-docs.ts +24 -17
  90. package/src/effort.ts +48 -0
  91. package/src/evaluation/axis-checks/checks/grid.ts +148 -0
  92. package/src/evaluation/axis-checks/checks/universal.ts +244 -0
  93. package/src/evaluation/axis-checks/dispatch.ts +82 -13
  94. package/src/evaluation/axis-checks/extras.ts +5 -0
  95. package/src/evaluation/axis-checks/helpers.ts +12 -0
  96. package/src/evaluation/axis-checks/registry.ts +2 -0
  97. package/src/evaluation/cost-tracker.ts +2 -3
  98. package/src/evaluation/design-identity.ts +96 -0
  99. package/src/evaluation/index.ts +63 -2
  100. package/src/evaluation/llm-evaluator.ts +89 -21
  101. package/src/evaluation/theme-css.ts +14 -0
  102. package/src/evaluation/types-public.ts +137 -8
  103. package/src/evaluation/visual-evaluator.ts +759 -54
  104. package/src/fragments/render.ts +1 -1
  105. package/src/harness/check/runtime-render/prepare-mockup.ts +18 -11
  106. package/src/harness/coding/dupe-break.ts +0 -0
  107. package/src/harness/coding/init-session.ts +2 -0
  108. package/src/harness/coding/run-coding-turn.ts +9 -14
  109. package/src/harness/coding/run-eval-round.ts +46 -5
  110. package/src/harness/llm-trace-sink.ts +3 -3
  111. package/src/harness/result-types.ts +15 -3
  112. package/src/harness/runtime.ts +28 -0
  113. package/src/harness/types-public.ts +38 -0
  114. package/src/index.ts +28 -0
  115. package/src/internal/extract-call-signatures.ts +2 -2
  116. package/src/pin-fixtures.ts +98 -0
  117. package/src/providers/bedrock.ts +4 -4
  118. package/src/run-check.ts +11 -10
  119. package/src/tools/get-primitives-ts.ts +1 -1
  120. package/src/tools.ts +2 -1
  121. package/src/validation/allowed-imports.ts +8 -2
  122. package/src/validation/primitives.ts +1 -1
  123. package/dist/create-ui-generator-D6TKuv9V.d.ts +0 -106
@@ -1,4 +1,5 @@
1
- import { A as AxisCheck } from '../../types-public-CkNWEov9.js';
1
+ import { A as AxisCheck } from '../../types-public-DVSssdc-.js';
2
+ import '../../design-mode-DLufhrNp.js';
2
3
  import '@ggui-ai/protocol';
3
4
  import '../../axes-CzLEMDeB.js';
4
5
  import '../../types-BOvHNG7K.js';
@@ -1,6 +1,7 @@
1
+ import { LUCIDE_ICON_NAMES } from '@ggui-ai/design';
1
2
  import { listContractGadgets, HOOK_NAME_RE, STDLIB_GADGETS_PACKAGE } from '@ggui-ai/protocol';
2
3
 
3
- // src/evaluation/axis-checks/helpers.ts
4
+ // src/evaluation/axis-checks/checks/universal.ts
4
5
  var ID_FIELD_CANDIDATES = ["id", "uuid", "symbol", "key", "slug", "code"];
5
6
  function getItemsProperties(p) {
6
7
  return p.items?.properties ?? p.schema?.items?.properties;
@@ -157,6 +158,9 @@ function mkIssue(subcategory, description, fix, result = "fail") {
157
158
  function cap(s) {
158
159
  return s.charAt(0).toUpperCase() + s.slice(1);
159
160
  }
161
+ function axisCheckTraceEnabled() {
162
+ return process.env["GGUI_AXIS_CHECK_TRACE"] === "1";
163
+ }
160
164
 
161
165
  // src/evaluation/axis-checks/checks/universal.ts
162
166
  var ALL_RENDER_VALUES = [
@@ -260,7 +264,172 @@ function runPropSeedNoResync(input) {
260
264
  }
261
265
  return issues;
262
266
  }
267
+ var KNOWN_ICON_KEYS = new Set(
268
+ LUCIDE_ICON_NAMES.map((n) => n.replace(/[-_]/g, "").toLowerCase())
269
+ );
270
+ function isKnownIconName(name) {
271
+ return KNOWN_ICON_KEYS.has(name.replace(/[-_]/g, "").toLowerCase());
272
+ }
273
+ var ICON_NAME_LITERAL_RX = /<Icon\b[^>]*?\bname\s*=\s*(?:"([^"]*)"|'([^']*)'|\{\s*"([^"]*)"\s*\}|\{\s*'([^']*)'\s*\})/g;
274
+ function findUnknownIconNames(sourceCode) {
275
+ const unknown = /* @__PURE__ */ new Set();
276
+ for (const m of sourceCode.matchAll(ICON_NAME_LITERAL_RX)) {
277
+ const name = m[1] ?? m[2] ?? m[3] ?? m[4] ?? "";
278
+ if (name.length === 0) continue;
279
+ if (/[^\x20-\x7e]/.test(name)) continue;
280
+ if (!isKnownIconName(name)) unknown.add(name);
281
+ }
282
+ return [...unknown];
283
+ }
284
+ function runIconNameKnown(input) {
285
+ if (input.compiledCode === null) return [];
286
+ const unknown = findUnknownIconNames(input.sourceCode);
287
+ if (unknown.length === 0) return [];
288
+ const list = unknown.map((n) => `"${n}"`).join(", ");
289
+ return [
290
+ mkIssue(
291
+ "universal.icon_name_known",
292
+ `<Icon name=\u2026> uses ${unknown.length} name(s) outside the design system's Lucide subset: ${list} \u2014 an unknown name renders an empty box.`,
293
+ "Call get_available_icons and pick a listed name (kebab-case), or use an emoji directly."
294
+ )
295
+ ];
296
+ }
297
+ var LADDER_STOP_AS_TEXT_RX = /(?<![\w-])color\s*(?:=\s*\{?\s*|:\s*)["'`]?\s*var\(--ggui-color-primary-(\d{2,3})\s*[,)]/g;
298
+ var TEXT_INK_STOP_MIN = 300;
299
+ var TEXT_INK_STOP_MAX = 600;
300
+ function findLadderStopsAsText(sourceCode) {
301
+ const found = /* @__PURE__ */ new Set();
302
+ for (const m of sourceCode.matchAll(LADDER_STOP_AS_TEXT_RX)) {
303
+ const digits = m[1] ?? "";
304
+ const stop = Number(digits);
305
+ if (stop >= TEXT_INK_STOP_MIN && stop <= TEXT_INK_STOP_MAX) found.add(`primary-${digits}`);
306
+ }
307
+ return [...found];
308
+ }
309
+ function runAccentTextInk(input) {
310
+ if (input.compiledCode === null) return [];
311
+ const stops = findLadderStopsAsText(input.sourceCode);
312
+ if (stops.length === 0) return [];
313
+ const list = stops.map((s) => `\`${s}\``).join(", ");
314
+ return [
315
+ mkIssue(
316
+ "universal.accent_text_ink",
317
+ `Text is painted with a brand-ladder fill stop as its color (${list}) \u2014 on a low-saturation brand these stops are mid-grey on the surface and the text fails readability.`,
318
+ 'Accent text (eyebrows, taglines, links, labels, inline arrows) takes var(--ggui-color-link) or <Text tone="emphasized">; body text takes var(--ggui-color-onContainer); keep primary-* stops on fills and borders.'
319
+ )
320
+ ];
321
+ }
322
+ var SCOPED_SURFACE_TAG_RX = /<(Card|Box)\b([^<>]*?)surface\s*=\s*["'](inverted|hero)["']([^<>]*?)>/g;
323
+ var STYLE_BACKGROUND_RX = /\bstyle\s*=\s*\{\{[^}]*\b(background|backgroundColor|backgroundImage)\s*:/;
324
+ function findScopedSurfaceBackgrounds(sourceCode) {
325
+ const hits = [];
326
+ for (const m of sourceCode.matchAll(SCOPED_SURFACE_TAG_RX)) {
327
+ const attrs = `${m[2] ?? ""} ${m[4] ?? ""}`;
328
+ if (STYLE_BACKGROUND_RX.test(attrs)) hits.push([m[1] ?? "", m[3] ?? ""]);
329
+ }
330
+ return hits;
331
+ }
332
+ function runScopedSurfaceOwnsGround(input) {
333
+ if (input.compiledCode === null) return [];
334
+ if (input.designMode === "free") return [];
335
+ const hits = findScopedSurfaceBackgrounds(input.sourceCode);
336
+ if (hits.length === 0) return [];
337
+ const [tag, surface] = hits[0];
338
+ return [
339
+ mkIssue(
340
+ "universal.scoped_surface_owns_ground",
341
+ `<${tag} surface="${surface}"> sets its own background in style \u2014 a scoped surface owns its ground; repainting it puts the scope's swapped inks over the wrong ground (ink on ink).`,
342
+ `Remove the background from that ${tag}'s style \u2014 surface="${surface}" paints the ground; pick another surface if a different ground is wanted.`
343
+ )
344
+ ];
345
+ }
346
+ var CAPS_TEXT_RX = /<Text\b(?=[^>]*\bcaps\b)[^>]*>([\s\S]*?)<\/Text>/g;
347
+ function findInventedCapsLabels(sourceCode) {
348
+ const out = [];
349
+ for (const m of sourceCode.matchAll(CAPS_TEXT_RX)) {
350
+ const inner = (m[1] ?? "").trim();
351
+ if (inner.length === 0) continue;
352
+ if (inner.includes("{")) continue;
353
+ out.push(inner.replace(/\s+/g, " ").slice(0, 60));
354
+ }
355
+ return out;
356
+ }
357
+ function runCapsLabelInvented(input) {
358
+ if (input.compiledCode === null) return [];
359
+ const invented = findInventedCapsLabels(input.sourceCode);
360
+ if (invented.length === 0) return [];
361
+ const list = invented.map((t) => `"${t}"`).join(", ");
362
+ return [
363
+ mkIssue(
364
+ "universal.caps_label_invented",
365
+ `${invented.length} caps label(s) carry invented copy the props do not supply: ${list} \u2014 an eyebrow, kicker or overline the agent cannot change is chatter on every render.`,
366
+ "Remove the label, or bind its text to a prop (`<Text caps>{props.section}</Text>`); copy comes from the contract, never from the component."
367
+ )
368
+ ];
369
+ }
370
+ var VIEWPORT_UNIT = String.raw`(?:calc\(\s*)?100(?:vh|dvh|svh|lvh)\b(?:[^)"'\x60;\n]*\))?`;
371
+ var VIEWPORT_STYLE_OBJECT_RX = new RegExp(
372
+ String.raw`\b(?:minHeight|height|minBlockSize|blockSize)\s*:\s*["'\x60]\s*${VIEWPORT_UNIT}["'\x60]?`,
373
+ "g"
374
+ );
375
+ var VIEWPORT_CSS_RX = new RegExp(
376
+ String.raw`(?<![\w-])(?:min-)?(?:height|block-size)\s*:\s*${VIEWPORT_UNIT}`,
377
+ "g"
378
+ );
379
+ var VIEWPORT_CLASS_RX = /(?<![\w-])(?:min-)?h-(?:screen|dvh|svh|lvh)\b/g;
380
+ function findViewportSizing(sourceCode) {
381
+ const hits = [];
382
+ for (const rx of [VIEWPORT_STYLE_OBJECT_RX, VIEWPORT_CSS_RX, VIEWPORT_CLASS_RX]) {
383
+ for (const m of sourceCode.matchAll(rx)) {
384
+ hits.push({ at: m.index ?? 0, text: m[0].replace(/\s+/g, " ").trim().slice(0, 60) });
385
+ }
386
+ }
387
+ return hits.sort((a, b) => a.at - b.at).map((h) => h.text);
388
+ }
389
+ function runViewportSized(input) {
390
+ if (input.compiledCode === null) return [];
391
+ const sized = findViewportSizing(input.sourceCode);
392
+ if (sized.length === 0) return [];
393
+ const list = sized.map((t) => "`" + t + "`").join(", ");
394
+ return [
395
+ mkIssue(
396
+ "universal.viewport_sized",
397
+ `${sized.length} element(s) are sized to the viewport: ${list} \u2014 the frame owns the height; a content-sized frame is measured from the content, so a viewport-sized root never shrinks and grows the frame on every re-measure.`,
398
+ "Remove the viewport height \u2014 size to content, never to the viewport. Under fullscreen the frame stretches your root already (centre inside it with `display: flex; flex-direction: column; justify-content: center`); to fill a parent that has a height use `height: 100%` or `flex: 1`."
399
+ )
400
+ ];
401
+ }
263
402
  var UNIVERSAL_CHECKS = [
403
+ {
404
+ id: "universal.icon_name_known",
405
+ axis: "render",
406
+ values: ALL_RENDER_VALUES,
407
+ run: runIconNameKnown
408
+ },
409
+ {
410
+ id: "universal.caps_label_invented",
411
+ axis: "render",
412
+ values: ALL_RENDER_VALUES,
413
+ run: runCapsLabelInvented
414
+ },
415
+ {
416
+ id: "universal.viewport_sized",
417
+ axis: "render",
418
+ values: ALL_RENDER_VALUES,
419
+ run: runViewportSized
420
+ },
421
+ {
422
+ id: "universal.accent_text_ink",
423
+ axis: "render",
424
+ values: ALL_RENDER_VALUES,
425
+ run: runAccentTextInk
426
+ },
427
+ {
428
+ id: "universal.scoped_surface_owns_ground",
429
+ axis: "render",
430
+ values: ALL_RENDER_VALUES,
431
+ run: runScopedSurfaceOwnsGround
432
+ },
264
433
  {
265
434
  id: "universal.prop_coverage",
266
435
  axis: "render",
@@ -1063,6 +1232,87 @@ var TOOLING_CHECKS = [
1063
1232
  }
1064
1233
  ];
1065
1234
 
1235
+ // src/evaluation/axis-checks/checks/grid.ts
1236
+ var BOARD_PROP_RX = /^(columns?|lanes?|stages?|lists?|buckets?|swimlanes?)$/i;
1237
+ var BOARD_PROMPT_RX = /\b(kanban|board)\b/i;
1238
+ var BOARD_NAMES = ["columns", "lanes", "stages", "lists", "buckets", "swimlanes"];
1239
+ var LAYOUT_TAG_RX = /<(\/?)(Grid|Row|Stack|Card|Box|Container|ScrollArea|div|section)\b([^<>]*?)>/g;
1240
+ var SIDE_BY_SIDE = /* @__PURE__ */ new Set(["Grid", "Row"]);
1241
+ function boardPropNames(contract) {
1242
+ const propsField = contract?.propsSpec;
1243
+ const properties = propsField?.properties ?? {};
1244
+ return Object.entries(properties).filter(([name, p]) => BOARD_PROP_RX.test(name) && (p?.type === "array" || p?.schema?.type === "array")).map(([name]) => name);
1245
+ }
1246
+ function jsxMapPositions(sourceCode, name) {
1247
+ const rx = new RegExp(
1248
+ `\\b${name}(?:\\?\\.)?\\.map\\(\\s*\\(?\\s*\\w+(?:\\s*,\\s*\\w+)?\\s*\\)?\\s*=>\\s*(?:\\(?\\s*<|\\{[^{}]{0,600}?\\breturn\\s*\\(?\\s*<)`,
1249
+ "g"
1250
+ );
1251
+ return [...sourceCode.matchAll(rx)].map((m) => m.index ?? 0);
1252
+ }
1253
+ function enclosingLayoutTag(sourceCode, pos) {
1254
+ const stack = [];
1255
+ for (const m of sourceCode.slice(0, pos).matchAll(LAYOUT_TAG_RX)) {
1256
+ const closing = m[1] === "/";
1257
+ const name = m[2] ?? "";
1258
+ const attrs = m[3] ?? "";
1259
+ if (closing) {
1260
+ if (stack[stack.length - 1] === name) stack.pop();
1261
+ continue;
1262
+ }
1263
+ if (attrs.trimEnd().endsWith("/")) continue;
1264
+ stack.push(name);
1265
+ }
1266
+ return stack[stack.length - 1];
1267
+ }
1268
+ function describeBoardRead(input) {
1269
+ const declared = boardPropNames(input.contract);
1270
+ const names = declared.length > 0 ? declared : BOARD_PROMPT_RX.test(input.originalPrompt) ? [...BOARD_NAMES] : BOARD_NAMES.filter((n) => jsxMapPositions(input.sourceCode, n).length > 0);
1271
+ const perName = names.map((name) => {
1272
+ const positions = jsxMapPositions(input.sourceCode, name);
1273
+ return { name, maps: positions.length, enclosing: positions.map((pos) => enclosingLayoutTag(input.sourceCode, pos) ?? "nothing") };
1274
+ });
1275
+ return { declared, names, perName };
1276
+ }
1277
+ function findStackedBoardColumns(input) {
1278
+ const stacked = [];
1279
+ for (const { name, enclosing } of describeBoardRead(input).perName) {
1280
+ for (const tag of enclosing) if (!SIDE_BY_SIDE.has(tag)) stacked.push([name, tag]);
1281
+ }
1282
+ return stacked;
1283
+ }
1284
+ function runBoardColumnsSideBySide(input) {
1285
+ if (input.compiledCode === null) return [];
1286
+ const standDown = input.designMode === "free";
1287
+ const stacked = standDown ? [] : findStackedBoardColumns(input);
1288
+ if (axisCheckTraceEnabled()) {
1289
+ const line = {
1290
+ ...describeBoardRead(input),
1291
+ designMode: input.designMode ?? "constrained",
1292
+ standDown,
1293
+ result: standDown ? "stand-down" : stacked.length > 0 ? "fail" : "pass"
1294
+ };
1295
+ console.log(JSON.stringify({ boardColumnsTrace: line }));
1296
+ }
1297
+ if (stacked.length === 0) return [];
1298
+ const [name, tag] = stacked[0];
1299
+ return [
1300
+ mkIssue(
1301
+ "grid.board_columns_side_by_side",
1302
+ `The board's \`${name}\` are composed under <${tag}> \u2014 a vertical stack of column sections; at md and wider the columns must sit side by side.`,
1303
+ `Wrap the ${name} map in <Grid columns={{ base: 1, md: ${name}.length }} gap="md"> (each column its own <Stack> of cards); never a <Stack> of column sections.`
1304
+ )
1305
+ ];
1306
+ }
1307
+ var GRID_CHECKS = [
1308
+ {
1309
+ id: "grid.board_columns_side_by_side",
1310
+ axis: "render",
1311
+ values: ["grid"],
1312
+ run: runBoardColumnsSideBySide
1313
+ }
1314
+ ];
1315
+
1066
1316
  // src/evaluation/axis-checks/extras.ts
1067
1317
  function mkIssue2(subcategory, description, fix, result = "warn") {
1068
1318
  return { tier: 0, result, category: "mode", subcategory, description, fix };
@@ -1152,6 +1402,7 @@ var stepperAdopted = {
1152
1402
  values: ["multi-step"],
1153
1403
  run(input) {
1154
1404
  if (input.compiledCode === null) return [];
1405
+ if (input.designMode === "free") return [];
1155
1406
  if (/<Stepper[\s/>]/.test(input.sourceCode)) return [];
1156
1407
  return [
1157
1408
  mkIssue2(
@@ -1201,6 +1452,7 @@ var REGISTRY = [
1201
1452
  ...WRITES_CHECKS,
1202
1453
  ...STATE_PAYLOAD_CHECKS,
1203
1454
  ...TOOLING_CHECKS,
1455
+ ...GRID_CHECKS,
1204
1456
  ...EXTRA_CHECKS
1205
1457
  ];
1206
1458