@motion-proto/live-tokens 0.78.0 → 0.80.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 (172) hide show
  1. package/.claude/skills/live-tokens-check-compliance/SKILL.md +49 -38
  2. package/.claude/skills/live-tokens-create-component/SKILL.md +23 -28
  3. package/.claude/skills/live-tokens-create-component/references/contract-tests.md +61 -0
  4. package/.claude/skills/live-tokens-create-component/references/sketch-mode.md +2 -2
  5. package/.claude/skills/live-tokens-create-component/references/token-naming.md +6 -15
  6. package/.claude/skills/live-tokens-create-page/SKILL.md +6 -4
  7. package/.claude/skills/live-tokens-create-theme/references/design-directions.md +1 -1
  8. package/.claude/skills/live-tokens-pick-component/SKILL.md +3 -3
  9. package/.claude/skills/live-tokens-set-colors/references/color-anchors.md +1 -1
  10. package/.claude/skills/live-tokens-set-geometry/SKILL.md +1 -1
  11. package/.claude/skills/live-tokens-set-geometry/references/geometry-anchors.md +1 -1
  12. package/CHANGELOG.md +271 -0
  13. package/README.md +10 -16
  14. package/bin/check-component.mjs +154 -551
  15. package/bin/check-page.mjs +57 -541
  16. package/bin/cli.mjs +93 -16
  17. package/bin/contractRunner.mjs +37 -91
  18. package/bin/lib/buildChecks.mjs +32 -0
  19. package/bin/lib/catalogue.mjs +161 -34
  20. package/bin/lib/componentSource.mjs +152 -0
  21. package/bin/lib/cssValues.mjs +9 -0
  22. package/bin/lib/dataDir.mjs +126 -0
  23. package/bin/lib/findings.mjs +103 -12
  24. package/bin/lib/fixers.mjs +64 -0
  25. package/bin/lib/geometry.mjs +92 -0
  26. package/bin/lib/pageSource.mjs +230 -0
  27. package/bin/lib/report.mjs +57 -59
  28. package/bin/lib/tokenVocabulary.mjs +104 -34
  29. package/bin/migrate-build-script.mjs +66 -0
  30. package/bin/migrate.mjs +5 -0
  31. package/bin/rules/componentStructure.mjs +344 -0
  32. package/bin/rules/componentUse.mjs +313 -0
  33. package/bin/rules/importsAndRoutes.mjs +136 -0
  34. package/bin/rules/testRuns.mjs +122 -0
  35. package/bin/rules/tokens.mjs +426 -0
  36. package/bin/setup-claude.mjs +1 -2
  37. package/dist-plugin/{chunk-PDNL4NC5.js → chunk-D4WRIKEZ.js} +7 -2
  38. package/dist-plugin/{chunk-SWXRVZKT.js → chunk-REBHE3ZM.js} +414 -1
  39. package/dist-plugin/index.cjs +470 -19
  40. package/dist-plugin/index.d.cts +1 -0
  41. package/dist-plugin/index.d.ts +1 -0
  42. package/dist-plugin/index.js +87 -55
  43. package/dist-plugin/migrateData/index.cjs +422 -4
  44. package/dist-plugin/migrateData/index.js +2 -2
  45. package/dist-plugin/setColors/index.cjs +414 -1
  46. package/dist-plugin/setColors/index.d.cts +1 -1
  47. package/dist-plugin/setColors/index.d.ts +1 -1
  48. package/dist-plugin/setColors/index.js +1 -1
  49. package/dist-plugin/setGeometry/index.cjs +423 -13
  50. package/dist-plugin/setGeometry/index.d.cts +3 -3
  51. package/dist-plugin/setGeometry/index.d.ts +3 -3
  52. package/dist-plugin/setGeometry/index.js +10 -13
  53. package/dist-plugin/setType/index.d.cts +1 -1
  54. package/dist-plugin/setType/index.d.ts +1 -1
  55. package/dist-plugin/{themeTypes-BxRtuN5V.d.cts → themeTypes-B8_Idrp4.d.cts} +2 -2
  56. package/dist-plugin/{themeTypes-BxRtuN5V.d.ts → themeTypes-B8_Idrp4.d.ts} +2 -2
  57. package/package.json +2 -2
  58. package/src/editor/component-editor/CalloutEditor.svelte +2 -2
  59. package/src/editor/component-editor/CollapsibleSectionEditor.svelte +14 -15
  60. package/src/editor/component-editor/CornerBadgeEditor.svelte +14 -14
  61. package/src/editor/component-editor/DialogEditor.svelte +5 -5
  62. package/src/editor/component-editor/InlineEditActionsEditor.svelte +2 -2
  63. package/src/editor/component-editor/RadioButtonEditor.svelte +21 -21
  64. package/src/editor/component-editor/SectionDividerEditor.svelte +7 -7
  65. package/src/editor/component-editor/SegmentedControlEditor.svelte +5 -5
  66. package/src/editor/component-editor/SideNavigationEditor.svelte +25 -25
  67. package/src/editor/component-editor/TabBarEditor.svelte +6 -6
  68. package/src/editor/component-editor/TableEditor.svelte +6 -6
  69. package/src/editor/component-editor/ToggleEditor.svelte +2 -2
  70. package/src/editor/component-editor/index.ts +3 -0
  71. package/src/editor/component-editor/registry.ts +57 -1
  72. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +14 -14
  73. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +3 -0
  74. package/src/editor/component-editor/scaffolding/types.ts +15 -0
  75. package/src/editor/core/components/adjustAliases.ts +4 -4
  76. package/src/editor/core/components/aliasKinds.ts +20 -19
  77. package/src/editor/core/sketch/sketchLayer.ts +3 -3
  78. package/src/editor/core/themes/migrateComponentConfig.ts +14 -6
  79. package/src/editor/core/themes/migrations/2026-09-13-badge-brand.ts +42 -0
  80. package/src/editor/core/themes/migrations/2026-09-13-collapsiblesection-open.ts +33 -0
  81. package/src/editor/core/themes/migrations/2026-09-13-cornerbadge-prefix.ts +70 -0
  82. package/src/editor/core/themes/migrations/2026-09-13-hairline.ts +92 -0
  83. package/src/editor/core/themes/migrations/2026-09-13-indicator.ts +54 -0
  84. package/src/editor/core/themes/migrations/2026-09-13-sectiondivider-surface.ts +36 -0
  85. package/src/editor/core/themes/migrations/2026-09-13-selected-state.ts +124 -0
  86. package/src/editor/core/themes/migrations/2026-09-13-toggle-label.ts +31 -0
  87. package/src/editor/core/themes/migrations/index.ts +16 -0
  88. package/src/editor/core/themes/themeService.ts +3 -3
  89. package/src/editor/core/themes/themeTypes.ts +13 -15
  90. package/src/editor/docs/Docs.svelte +1 -1
  91. package/src/editor/docs/content/light-and-dark.md +3 -3
  92. package/src/editor/docs/content.generated.ts +1 -1
  93. package/src/editor/index.ts +1 -0
  94. package/src/editor/overlay/LiveEditorOverlay.svelte +15 -0
  95. package/src/editor/skill-atlas/SkillAtlas.svelte +4 -4
  96. package/src/editor/skill-atlas/TreeNodeCard.svelte +4 -4
  97. package/src/editor/skill-atlas/skillSources.generated.ts +11 -14
  98. package/src/editor/skill-atlas/skillTrees.ts +1 -3
  99. package/src/editor/skill-atlas/trees/check-compliance.ts +37 -149
  100. package/src/editor/skill-atlas/trees/create-component.ts +62 -64
  101. package/src/editor/skill-atlas/trees/create-page.ts +38 -17
  102. package/src/editor/skill-atlas/trees/pick-component.ts +3 -3
  103. package/src/editor/skill-atlas/trees/set-geometry.ts +1 -1
  104. package/src/editor/ui/UIPaletteSelector.svelte +11 -15
  105. package/src/editor/ui/variantScales.ts +8 -8
  106. package/src/live-tokens/data/themes/autumn.json +188 -188
  107. package/src/live-tokens/data/themes/halloween.json +188 -188
  108. package/src/live-tokens/data/themes/midnight-study.json +245 -245
  109. package/src/live-tokens/data/themes/ocean.json +188 -188
  110. package/src/live-tokens/data/themes/royal-velvet.json +188 -188
  111. package/src/live-tokens/data/themes/sketchy.json +188 -188
  112. package/src/live-tokens/data/themes/spring-meadow.json +188 -188
  113. package/src/live-tokens/data/themes/sunset.json +188 -188
  114. package/src/system/components/Badge.svelte +27 -23
  115. package/src/system/components/Button.svelte +13 -7
  116. package/src/system/components/Callout.svelte +16 -11
  117. package/src/system/components/Card.svelte +22 -15
  118. package/src/system/components/CodeSnippet.svelte +10 -6
  119. package/src/system/components/CollapsibleSection.svelte +81 -76
  120. package/src/system/components/CornerBadge.svelte +78 -72
  121. package/src/system/components/Dialog.svelte +21 -18
  122. package/src/system/components/IconButton.svelte +13 -9
  123. package/src/system/components/Image.svelte +14 -8
  124. package/src/system/components/ImageLightbox.svelte +10 -6
  125. package/src/system/components/InlineEditActions.svelte +17 -14
  126. package/src/system/components/Input.svelte +13 -7
  127. package/src/system/components/MenuSelect.svelte +13 -7
  128. package/src/system/components/Notification.svelte +17 -11
  129. package/src/system/components/Panel.svelte +13 -6
  130. package/src/system/components/ProgressBar.svelte +10 -5
  131. package/src/system/components/RadioButton.svelte +33 -30
  132. package/src/system/components/SectionDivider.svelte +28 -21
  133. package/src/system/components/SegmentedControl.svelte +27 -23
  134. package/src/system/components/SideNavigation.svelte +175 -171
  135. package/src/system/components/Slider.svelte +11 -7
  136. package/src/system/components/TabBar.svelte +53 -49
  137. package/src/system/components/Table.svelte +20 -15
  138. package/src/system/components/Toggle.svelte +14 -10
  139. package/src/system/components/Tooltip.svelte +10 -6
  140. package/src/system/styles/CONVENTIONS.md +3 -4
  141. package/src/testing-js/chunk-3UKGXCDL.js +48 -0
  142. package/src/testing-js/chunk-3UKGXCDL.js.map +1 -0
  143. package/src/testing-js/{chunk-FAFOAWYL.js → chunk-Q3YIAAG3.js} +17 -3
  144. package/src/testing-js/chunk-Q3YIAAG3.js.map +1 -0
  145. package/src/testing-js/{chunk-GNIUPIU2.js → chunk-U7OJE5DU.js} +18 -18
  146. package/src/testing-js/chunk-U7OJE5DU.js.map +1 -0
  147. package/src/testing-js/{chunk-4JQX6WWL.js → chunk-ZMZQZ33J.js} +474 -166
  148. package/src/testing-js/chunk-ZMZQZ33J.js.map +1 -0
  149. package/src/testing-js/component-behavior.contract.js +155 -0
  150. package/src/testing-js/component-behavior.contract.js.map +1 -0
  151. package/src/testing-js/component-editor.contract.js +6 -4
  152. package/src/testing-js/component-editor.contract.js.map +1 -1
  153. package/src/testing-js/component-render.contract.js +14 -10
  154. package/src/testing-js/component-render.contract.js.map +1 -1
  155. package/src/testing-js/index.d.ts +44 -4
  156. package/src/testing-js/index.js +13 -7
  157. package/src/testing-js/index.js.map +1 -1
  158. package/src/testing-js/page-compliance.contract.js +48 -10
  159. package/src/testing-js/page-compliance.contract.js.map +1 -1
  160. package/src/testing-js/registry.contract.js +5 -3
  161. package/src/testing-js/registry.contract.js.map +1 -1
  162. package/src/testing-js/{vitest-C-wNWcoA.d.ts → vitest-BMLIbDs2.d.ts} +8 -2
  163. package/src/testing-js/vitest.d.ts +1 -1
  164. package/src/testing-js/vitest.js +2 -1
  165. package/template/package.json +1 -2
  166. package/template/vite.config.ts +3 -2
  167. package/.claude/skills/live-tokens-create-component/SKILL copy.md +0 -196
  168. package/.claude/skills/live-tokens-fix-findings/SKILL.md +0 -105
  169. package/src/editor/skill-atlas/trees/fix-findings.ts +0 -504
  170. package/src/testing-js/chunk-4JQX6WWL.js.map +0 -1
  171. package/src/testing-js/chunk-FAFOAWYL.js.map +0 -1
  172. package/src/testing-js/chunk-GNIUPIU2.js.map +0 -1
@@ -1,51 +1,10 @@
1
- // src/testing/componentContract.ts
2
- var ContractViolation = class extends Error {
3
- constructor(rule, component, message) {
4
- super(`[${rule}] ${component}: ${message}`);
5
- this.rule = rule;
6
- this.component = component;
7
- this.name = "ContractViolation";
8
- }
9
- rule;
10
- component;
11
- };
12
- function isInapplicable(value) {
13
- return typeof value === "object" && value !== null && value.applicable === false;
14
- }
15
- var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
16
- "button",
17
- "switch",
18
- "checkbox",
19
- "radio",
20
- "slider",
21
- "spinbutton",
22
- "textbox",
23
- "combobox",
24
- "listbox",
25
- "menuitem",
26
- "tab",
27
- "link",
28
- "searchbox",
29
- "option"
30
- ]);
31
- function requiresInteraction(role) {
32
- return role !== null && INTERACTIVE_ROLES.has(role);
33
- }
34
- function partLocator(contract, key) {
35
- const declared = contract.parts[key];
36
- if (declared === void 0) {
37
- throw new ContractViolation("contract-render", contract.id, `no part named "${key}" is declared`);
38
- }
39
- return typeof declared === "string" ? { selector: declared } : declared;
40
- }
41
-
42
1
  // src/testing/contracts/index.ts
43
2
  import path from "path";
44
3
  import { pathToFileURL } from "url";
45
4
 
46
5
  // src/testing/contracts/badge.ts
47
6
  var variants = [
48
- "primary",
7
+ "brand",
49
8
  "accent",
50
9
  "neutral",
51
10
  "alternate",
@@ -83,23 +42,23 @@ function colorPaints(v) {
83
42
  var badgeContract = {
84
43
  id: "badge",
85
44
  origin: "system",
86
- view: { variant: "Primary" },
45
+ view: { variant: "Brand" },
87
46
  root: "root",
88
47
  parts: {
89
48
  root: ".badge",
90
49
  icon: ".icon"
91
50
  },
92
51
  properties: [
93
- { variant: "Primary", state: "base", paints: basePaints("primary") },
94
- { variant: "Primary", state: "colors", paints: colorPaints("primary") },
95
- ...variants.filter((v) => v !== "primary").flatMap((v) => [
52
+ { variant: "Brand", state: "base", paints: basePaints("brand") },
53
+ { variant: "Brand", state: "colors", paints: colorPaints("brand") },
54
+ ...variants.filter((v) => v !== "brand").flatMap((v) => [
96
55
  { variant: v.charAt(0).toUpperCase() + v.slice(1), state: "base", paints: basePaints(v) },
97
56
  { variant: v.charAt(0).toUpperCase() + v.slice(1), state: "colors", paints: colorPaints(v) }
98
57
  ])
99
58
  ],
100
59
  states: [{ state: "base" }, { state: "colors" }],
101
60
  uncovered: {
102
- "--badge-primary-blur": "consumed via backdrop-filter: blur(), which no probe covers",
61
+ "--badge-brand-blur": "consumed via backdrop-filter: blur(), which no probe covers",
103
62
  "--badge-accent-blur": "consumed via backdrop-filter: blur(), which no probe covers",
104
63
  "--badge-neutral-blur": "consumed via backdrop-filter: blur(), which no probe covers",
105
64
  "--badge-alternate-blur": "consumed via backdrop-filter: blur(), which no probe covers",
@@ -114,31 +73,35 @@ var badgeContract = {
114
73
  cases: [
115
74
  {
116
75
  shape: "token",
117
- variant: "Primary",
76
+ variant: "Brand",
118
77
  state: "base",
119
- variable: "--badge-primary-border-width",
78
+ variable: "--badge-brand-border-width",
120
79
  observe: { part: "root", css: "borderTopWidth" }
121
80
  }
122
81
  ],
123
- resetVariable: "--badge-primary-border-width"
82
+ resetVariable: "--badge-brand-border-width"
124
83
  },
125
84
  theme: {
126
85
  theme: "halloween",
127
- changed: ["--badge-primary-border-width", "--badge-primary-radius", "--badge-primary-padding"],
128
- unchanged: ["--badge-primary-shadow", "--badge-primary-icon-size"],
86
+ changed: ["--badge-brand-border-width", "--badge-brand-radius", "--badge-brand-padding"],
87
+ unchanged: ["--badge-brand-shadow", "--badge-brand-icon-size"],
129
88
  aliasedTo: {
130
- "--badge-primary-border-width": "--border-width-3",
131
- "--badge-primary-radius": "--radius-none"
89
+ "--badge-brand-border-width": "--border-width-3",
90
+ "--badge-brand-radius": "--radius-none"
132
91
  },
133
- observe: { part: "root", css: "borderTopWidth", variable: "--badge-primary-border-width" }
92
+ observe: { part: "root", css: "borderTopWidth", variable: "--badge-brand-border-width" }
134
93
  },
135
94
  interaction: {
136
95
  applicable: false,
137
96
  reason: "a badge is a static label with no interactive role"
138
97
  },
98
+ behavior: {
99
+ applicable: false,
100
+ reason: "a badge declares no callback prop and answers no event: its props select paint, which the render obligation reads"
101
+ },
139
102
  sketch: {
140
103
  style: "pencil",
141
- parts: [{ part: "root", fill: "--badge-primary-surface", stroke: "--badge-primary-border" }]
104
+ parts: [{ part: "root", fill: "--badge-brand-surface", stroke: "--badge-brand-border" }]
142
105
  }
143
106
  };
144
107
 
@@ -256,6 +219,21 @@ var buttonContract = {
256
219
  }
257
220
  ]
258
221
  },
222
+ behavior: {
223
+ cases: [
224
+ {
225
+ name: "clicking a button hands the click on",
226
+ action: { kind: "click", part: "root" },
227
+ expect: { kind: "callback", prop: "onclick", args: [{ type: "click" }] }
228
+ },
229
+ {
230
+ name: "a disabled button stays silent",
231
+ props: { disabled: true },
232
+ action: { kind: "click", part: "root" },
233
+ expect: { kind: "no-callback", prop: "onclick" }
234
+ }
235
+ ]
236
+ },
259
237
  sketch: {
260
238
  style: "pencil",
261
239
  parts: [{ part: "root", fill: "--button-primary-surface", stroke: "--button-primary-border" }]
@@ -270,7 +248,7 @@ function paintsFor(v) {
270
248
  backgroundColor: `--callout-${v}-surface`,
271
249
  borderTopColor: `--callout-${v}-border`,
272
250
  borderTopWidth: `--callout-${v}-border-width`,
273
- borderLeftWidth: `--callout-${v}-accent-width`,
251
+ borderLeftWidth: `--callout-${v}-indicator-width`,
274
252
  borderRadius: `--callout-${v}-radius`,
275
253
  paddingTop: `--callout-${v}-padding`
276
254
  },
@@ -329,6 +307,10 @@ var calloutContract = {
329
307
  applicable: false,
330
308
  reason: "a callout is a static box with no interactive role"
331
309
  },
310
+ behavior: {
311
+ applicable: false,
312
+ reason: "a callout declares no callback prop and answers no event"
313
+ },
332
314
  sketch: {
333
315
  style: "pencil",
334
316
  parts: [{ part: "root", fill: "--callout-info-surface", stroke: "--callout-info-border" }]
@@ -454,6 +436,10 @@ var cardContract = {
454
436
  applicable: false,
455
437
  reason: "a card is a static container with no interactive role"
456
438
  },
439
+ behavior: {
440
+ applicable: false,
441
+ reason: "a card declares no callback prop; its header and body arrive as snippets, which a mounted fixture cannot express"
442
+ },
457
443
  sketch: {
458
444
  style: "pencil",
459
445
  parts: [
@@ -541,6 +527,10 @@ var codeSnippetContract = {
541
527
  }
542
528
  ]
543
529
  },
530
+ behavior: {
531
+ applicable: false,
532
+ reason: "the copy control reports through the system clipboard and a timed popover, neither of which is a callback prop"
533
+ },
544
534
  sketch: {
545
535
  style: "pencil",
546
536
  parts: [{ part: "root", fill: "--codesnippet-surface", stroke: "--codesnippet-border" }]
@@ -557,9 +547,9 @@ function headerPaints(v, s) {
557
547
  backgroundColor: `${p}-surface`,
558
548
  paddingTop: `${p}-padding`
559
549
  };
560
- if (v === "divider") {
550
+ if (v === "hairline") {
561
551
  header.borderBottomColor = `${p}-hairline-color`;
562
- header.borderBottomWidth = `${p}-hairline-thickness`;
552
+ header.borderBottomWidth = `${p}-hairline-width`;
563
553
  }
564
554
  return {
565
555
  header,
@@ -603,14 +593,14 @@ var collapsibleSectionContract = {
603
593
  {
604
594
  variant: "Container",
605
595
  state: "Body",
606
- paints: { body: { backgroundColor: "--collapsiblesection-container-expanded-surface", paddingTop: "--collapsiblesection-container-expanded-padding" } }
596
+ paints: { body: { backgroundColor: "--collapsiblesection-container-open-surface", paddingTop: "--collapsiblesection-container-open-padding" } }
607
597
  },
608
598
  { variant: "Chromeless", state: "Header", paints: headerPaints("chromeless", "default") },
609
599
  { variant: "Chromeless", state: "Header", setup: clickHover(), paints: headerPaints("chromeless", "hover") },
610
- { variant: "Chromeless", state: "Body", paints: { body: { paddingTop: "--collapsiblesection-chromeless-expanded-padding" } } },
611
- { variant: "With Divider", state: "Header", paints: headerPaints("divider", "default") },
612
- { variant: "With Divider", state: "Header", setup: clickHover(), paints: headerPaints("divider", "hover") },
613
- { variant: "With Divider", state: "Body", paints: { body: { paddingTop: "--collapsiblesection-divider-expanded-padding" } } }
600
+ { variant: "Chromeless", state: "Body", paints: { body: { paddingTop: "--collapsiblesection-chromeless-open-padding" } } },
601
+ { variant: "With Hairline", state: "Header", paints: headerPaints("hairline", "default") },
602
+ { variant: "With Hairline", state: "Header", setup: clickHover(), paints: headerPaints("hairline", "hover") },
603
+ { variant: "With Hairline", state: "Body", paints: { body: { paddingTop: "--collapsiblesection-hairline-open-padding" } } }
614
604
  ],
615
605
  states: [{ state: "Container" }, { state: "Header" }, { state: "Body" }],
616
606
  persistence: {
@@ -638,7 +628,7 @@ var collapsibleSectionContract = {
638
628
  interaction: {
639
629
  part: "toggleButton",
640
630
  role: "button",
641
- // No activation case: CollapsibleSectionEditor's preview drives `expanded`
631
+ // No activation case: CollapsibleSectionEditor's preview drives `open`
642
632
  // off the active state tab and never wires `ontoggle` back to it, so
643
633
  // clicking the real button here can't move `aria-expanded` (same
644
634
  // constraint documented on ToggleEditor in toggle.ts).
@@ -650,19 +640,40 @@ var collapsibleSectionContract = {
650
640
  }
651
641
  ]
652
642
  },
643
+ behavior: {
644
+ cases: [
645
+ {
646
+ name: "clicking the chevron asks to toggle",
647
+ props: { label: "Details" },
648
+ action: { kind: "click", part: "toggleButton" },
649
+ expect: { kind: "callback", prop: "ontoggle", args: [] }
650
+ },
651
+ {
652
+ name: "open drives the chevron",
653
+ props: { label: "Details", open: true },
654
+ expect: { kind: "attribute", part: "toggleButton", name: "aria-expanded", value: "true" }
655
+ },
656
+ {
657
+ name: "clicking leaves the section where the prop put it",
658
+ props: { label: "Details" },
659
+ action: { kind: "click", part: "toggleButton" },
660
+ expect: { kind: "attribute", part: "toggleButton", name: "aria-expanded", value: "false" }
661
+ }
662
+ ]
663
+ },
653
664
  sketch: {
654
665
  style: "pencil",
655
666
  parts: [
656
667
  { part: "root", stroke: "--collapsiblesection-container-frame-border" },
657
668
  { part: "header", fill: "--collapsiblesection-container-default-surface" },
658
- { part: "body", fill: "--collapsiblesection-container-expanded-surface" }
669
+ { part: "body", fill: "--collapsiblesection-container-open-surface" }
659
670
  ]
660
671
  }
661
672
  };
662
673
 
663
674
  // src/testing/contracts/cornerbadge.ts
664
675
  var variants4 = [
665
- "primary",
676
+ "brand",
666
677
  "accent",
667
678
  "neutral",
668
679
  "alternate",
@@ -676,44 +687,44 @@ var variants4 = [
676
687
  function colorPaints2(v) {
677
688
  return {
678
689
  badge: {
679
- backgroundColor: `--corner-badge-${v}-surface`,
680
- borderTopColor: `--corner-badge-${v}-border`,
681
- color: `--corner-badge-${v}-text`
690
+ backgroundColor: `--cornerbadge-${v}-surface`,
691
+ borderTopColor: `--cornerbadge-${v}-border`,
692
+ color: `--cornerbadge-${v}-text`
682
693
  }
683
694
  };
684
695
  }
685
696
  var basePaints3 = {
686
- root: { bottom: "--corner-badge-margin" },
697
+ root: { bottom: "--cornerbadge-margin" },
687
698
  badge: {
688
- borderTopLeftRadius: "--corner-badge-inner-radius",
689
- borderTopRightRadius: "--corner-badge-v-axis-radius",
690
- borderBottomRightRadius: "--corner-badge-outer-radius",
691
- borderBottomLeftRadius: "--corner-badge-h-axis-radius",
692
- paddingTop: "--corner-badge-padding",
693
- fontFamily: "--corner-badge-text-font-family",
694
- fontSize: "--corner-badge-text-font-size",
695
- fontWeight: "--corner-badge-text-font-weight",
696
- lineHeight: "--corner-badge-text-line-height"
699
+ borderTopLeftRadius: "--cornerbadge-inner-radius",
700
+ borderTopRightRadius: "--cornerbadge-v-axis-radius",
701
+ borderBottomRightRadius: "--cornerbadge-outer-radius",
702
+ borderBottomLeftRadius: "--cornerbadge-h-axis-radius",
703
+ paddingTop: "--cornerbadge-padding",
704
+ fontFamily: "--cornerbadge-text-font-family",
705
+ fontSize: "--cornerbadge-text-font-size",
706
+ fontWeight: "--cornerbadge-text-font-weight",
707
+ lineHeight: "--cornerbadge-text-line-height"
697
708
  }
698
709
  };
699
710
  var cornerBadgeContract = {
700
711
  id: "cornerbadge",
701
712
  origin: "system",
702
- view: { variant: "Primary" },
713
+ view: { variant: "Brand" },
703
714
  root: "root",
704
715
  parts: {
705
- root: ".corner-badge",
706
- badge: ".corner-badge .badge"
716
+ root: ".cornerbadge",
717
+ badge: ".cornerbadge .badge"
707
718
  },
708
719
  properties: [
709
720
  {
710
- variant: "Primary",
721
+ variant: "Brand",
711
722
  paints: {
712
723
  root: basePaints3.root,
713
- badge: { ...basePaints3.badge, ...colorPaints2("primary").badge }
724
+ badge: { ...basePaints3.badge, ...colorPaints2("brand").badge }
714
725
  }
715
726
  },
716
- ...variants4.filter((v) => v !== "primary").map((v) => ({
727
+ ...variants4.filter((v) => v !== "brand").map((v) => ({
717
728
  variant: v.charAt(0).toUpperCase() + v.slice(1),
718
729
  paints: colorPaints2(v)
719
730
  }))
@@ -723,29 +734,33 @@ var cornerBadgeContract = {
723
734
  cases: [
724
735
  {
725
736
  shape: "token",
726
- variable: "--corner-badge-outer-radius",
737
+ variable: "--cornerbadge-outer-radius",
727
738
  observe: { part: "badge", css: "borderBottomRightRadius" }
728
739
  }
729
740
  ],
730
- resetVariable: "--corner-badge-outer-radius"
741
+ resetVariable: "--cornerbadge-outer-radius"
731
742
  },
732
743
  theme: {
733
744
  theme: "ocean",
734
- changed: ["--corner-badge-outer-radius", "--corner-badge-inner-radius", "--corner-badge-margin"],
735
- unchanged: ["--corner-badge-text-font-size"],
745
+ changed: ["--cornerbadge-outer-radius", "--cornerbadge-inner-radius", "--cornerbadge-margin"],
746
+ unchanged: ["--cornerbadge-text-font-size"],
736
747
  aliasedTo: {
737
- "--corner-badge-outer-radius": "--radius-md",
738
- "--corner-badge-inner-radius": "--radius-md"
748
+ "--cornerbadge-outer-radius": "--radius-md",
749
+ "--cornerbadge-inner-radius": "--radius-md"
739
750
  },
740
- observe: { part: "badge", css: "borderBottomRightRadius", variable: "--corner-badge-outer-radius" }
751
+ observe: { part: "badge", css: "borderBottomRightRadius", variable: "--cornerbadge-outer-radius" }
741
752
  },
742
753
  interaction: {
743
754
  applicable: false,
744
755
  reason: "a corner badge is a static marker with no interactive role"
745
756
  },
757
+ behavior: {
758
+ applicable: false,
759
+ reason: "a corner badge declares no callback prop and answers no event"
760
+ },
746
761
  sketch: {
747
762
  style: "pencil",
748
- parts: [{ part: "badge", fill: "--corner-badge-primary-surface", stroke: "--corner-badge-primary-border" }]
763
+ parts: [{ part: "badge", fill: "--cornerbadge-brand-surface", stroke: "--cornerbadge-brand-border" }]
749
764
  }
750
765
  };
751
766
 
@@ -778,8 +793,8 @@ var dialogContract = {
778
793
  },
779
794
  header: {
780
795
  backgroundColor: "--dialog-header-surface",
781
- borderBottomColor: "--dialog-header-divider",
782
- borderBottomWidth: "--dialog-header-divider-width",
796
+ borderBottomColor: "--dialog-header-hairline-color",
797
+ borderBottomWidth: "--dialog-header-hairline-width",
783
798
  paddingTop: "--dialog-header-padding"
784
799
  },
785
800
  title: {
@@ -802,8 +817,8 @@ var dialogContract = {
802
817
  lineHeight: "--dialog-body-line-height"
803
818
  },
804
819
  footer: {
805
- borderTopColor: "--dialog-footer-divider",
806
- borderTopWidth: "--dialog-footer-divider-width",
820
+ borderTopColor: "--dialog-footer-hairline-color",
821
+ borderTopWidth: "--dialog-footer-hairline-width",
807
822
  paddingTop: "--dialog-footer-padding"
808
823
  }
809
824
  }
@@ -865,6 +880,21 @@ var dialogContract = {
865
880
  }
866
881
  ]
867
882
  },
883
+ behavior: {
884
+ cases: [
885
+ {
886
+ name: "clicking close asks to close",
887
+ props: { open: true, inline: true, title: "Confirm" },
888
+ action: { kind: "click", part: "closeButton" },
889
+ expect: { kind: "callback", prop: "onclose", args: [] }
890
+ },
891
+ {
892
+ name: "title drives the heading",
893
+ props: { open: true, inline: true, title: "Confirm" },
894
+ expect: { kind: "text", part: "title", value: "Confirm" }
895
+ }
896
+ ]
897
+ },
868
898
  sketch: {
869
899
  style: "pencil",
870
900
  parts: [
@@ -969,6 +999,22 @@ var iconButtonContract = {
969
999
  }
970
1000
  ]
971
1001
  },
1002
+ behavior: {
1003
+ cases: [
1004
+ {
1005
+ name: "clicking an icon button hands the click on",
1006
+ props: { icon: "fas fa-check", ariaLabel: "Confirm" },
1007
+ action: { kind: "click", part: "root" },
1008
+ expect: { kind: "callback", prop: "onclick", args: [{ type: "click" }] }
1009
+ },
1010
+ {
1011
+ name: "a disabled icon button stays silent",
1012
+ props: { icon: "fas fa-check", ariaLabel: "Confirm", disabled: true },
1013
+ action: { kind: "click", part: "root" },
1014
+ expect: { kind: "no-callback", prop: "onclick" }
1015
+ }
1016
+ ]
1017
+ },
972
1018
  sketch: {
973
1019
  style: "pencil",
974
1020
  parts: [{ part: "root", fill: "--iconbutton-primary-surface", stroke: "--iconbutton-primary-border" }]
@@ -1033,6 +1079,10 @@ var imageContract = {
1033
1079
  applicable: false,
1034
1080
  reason: "a framed picture carries no interactive role; the zoom effect is a hover transform, not an action"
1035
1081
  },
1082
+ behavior: {
1083
+ applicable: false,
1084
+ reason: "an image declares no callback prop; zoom is a hover transform the browser paints"
1085
+ },
1036
1086
  sketch: {
1037
1087
  style: "pencil",
1038
1088
  parts: [{ part: "root", stroke: "--image-default-border" }]
@@ -1164,6 +1214,10 @@ var imageLightboxContract = {
1164
1214
  // can observe, even though PART_SPECS draws it on a real host page (where
1165
1215
  // Sketch mode's scope is the page root). `thumb` never portals, so it is the
1166
1216
  // part this contract can pin.
1217
+ behavior: {
1218
+ applicable: false,
1219
+ reason: "the lightbox declares no callback prop; opening portals a modal sized from measured geometry, which happy-dom has no layout for"
1220
+ },
1167
1221
  sketch: {
1168
1222
  style: "pencil",
1169
1223
  parts: [
@@ -1247,6 +1301,26 @@ var inlineEditActionsContract = {
1247
1301
  }
1248
1302
  ]
1249
1303
  },
1304
+ behavior: {
1305
+ cases: [
1306
+ {
1307
+ name: "clicking save reports it",
1308
+ action: { kind: "click", part: "saveBtn" },
1309
+ expect: { kind: "callback", prop: "onsave", args: [{ type: "click" }] }
1310
+ },
1311
+ {
1312
+ name: "clicking cancel reports it",
1313
+ action: { kind: "click", part: "cancelBtn" },
1314
+ expect: { kind: "callback", prop: "oncancel", args: [{ type: "click" }] }
1315
+ },
1316
+ {
1317
+ name: "disabled actions stay silent",
1318
+ props: { disabled: true },
1319
+ action: { kind: "click", part: "saveBtn" },
1320
+ expect: { kind: "no-callback", prop: "onsave" }
1321
+ }
1322
+ ]
1323
+ },
1250
1324
  sketch: {
1251
1325
  style: "pencil",
1252
1326
  parts: [
@@ -1430,6 +1504,21 @@ var inputContract = {
1430
1504
  }
1431
1505
  ]
1432
1506
  },
1507
+ behavior: {
1508
+ cases: [
1509
+ {
1510
+ name: "typing reports every keystroke",
1511
+ props: { label: "Name" },
1512
+ action: { kind: "input", part: "field", value: "probe" },
1513
+ expect: { kind: "callback", prop: "oninput", args: ["probe"] }
1514
+ },
1515
+ {
1516
+ name: "an error marks the field invalid",
1517
+ props: { label: "Name", error: "Required" },
1518
+ expect: { kind: "attribute", part: "field", name: "aria-invalid", value: "true" }
1519
+ }
1520
+ ]
1521
+ },
1433
1522
  sketch: {
1434
1523
  style: "pencil",
1435
1524
  parts: [{ part: "field", fill: "--input-default-surface", stroke: "--input-default-border" }]
@@ -1447,6 +1536,10 @@ function itemTextPaints(s, full) {
1447
1536
  if (full) paints.lineHeight = `--menuselect-${s}-text-line-height`;
1448
1537
  return paints;
1449
1538
  }
1539
+ var behaviorItems = [
1540
+ { value: "daily", label: "Daily" },
1541
+ { value: "weekly", label: "Weekly" }
1542
+ ];
1450
1543
  var menuSelectContract = {
1451
1544
  id: "menuselect",
1452
1545
  origin: "system",
@@ -1556,6 +1649,27 @@ var menuSelectContract = {
1556
1649
  }
1557
1650
  ]
1558
1651
  },
1652
+ behavior: {
1653
+ cases: [
1654
+ {
1655
+ name: "clicking an item asks for its value",
1656
+ props: { items: behaviorItems, value: "weekly" },
1657
+ action: { kind: "click", part: "item" },
1658
+ expect: { kind: "callback", prop: "onchange", args: ["daily"] }
1659
+ },
1660
+ {
1661
+ name: "value drives the selected item",
1662
+ props: { items: behaviorItems, value: "daily" },
1663
+ expect: { kind: "attribute", part: "item", name: "aria-selected", value: "true" }
1664
+ },
1665
+ {
1666
+ name: "a disabled item stays silent",
1667
+ props: { items: [{ ...behaviorItems[0], disabled: true }, behaviorItems[1]], value: "weekly" },
1668
+ action: { kind: "click", part: "item" },
1669
+ expect: { kind: "no-callback", prop: "onchange" }
1670
+ }
1671
+ ]
1672
+ },
1559
1673
  sketch: {
1560
1674
  style: "pencil",
1561
1675
  parts: [{ part: "root", fill: "--menuselect-menu-surface", stroke: "--menuselect-menu-border" }]
@@ -1599,7 +1713,10 @@ var notificationContract = {
1599
1713
  origin: "system",
1600
1714
  view: {
1601
1715
  variant: "Info",
1602
- setup: [{ kind: "control", selector: '.toolbar-check:has-text("Header button") input', check: true }]
1716
+ setup: [
1717
+ { kind: "control", selector: '.toolbar-check:has-text("Header button") input', check: true },
1718
+ { kind: "control", selector: '.toolbar-check:has-text("Dismissible") input', check: true }
1719
+ ]
1603
1720
  },
1604
1721
  root: "root",
1605
1722
  parts: {
@@ -1608,7 +1725,8 @@ var notificationContract = {
1608
1725
  icon: ".notification-header i",
1609
1726
  title: ".notification-title",
1610
1727
  actionBackdrop: ".action-button-backdrop",
1611
- actionButton: ".action-button-backdrop button"
1728
+ actionButton: ".action-button-backdrop button",
1729
+ closeButton: ".notification-close"
1612
1730
  },
1613
1731
  properties: variants6.map((v) => ({ variant: v.charAt(0).toUpperCase() + v.slice(1), paints: paintsFor2(v) })),
1614
1732
  states: [{ state: "base" }, { state: "colors" }],
@@ -1643,6 +1761,21 @@ var notificationContract = {
1643
1761
  }
1644
1762
  ]
1645
1763
  },
1764
+ behavior: {
1765
+ cases: [
1766
+ {
1767
+ name: "clicking dismiss reports it",
1768
+ props: { title: "Saved", description: "Your changes are live.", dismissible: true },
1769
+ action: { kind: "click", part: "closeButton" },
1770
+ expect: { kind: "callback", prop: "ondismiss", args: [] }
1771
+ },
1772
+ {
1773
+ name: "title drives the heading",
1774
+ props: { title: "Saved", description: "Your changes are live." },
1775
+ expect: { kind: "text", part: "title", value: "Saved" }
1776
+ }
1777
+ ]
1778
+ },
1646
1779
  sketch: {
1647
1780
  style: "pencil",
1648
1781
  parts: [
@@ -1708,6 +1841,10 @@ var panelContract = {
1708
1841
  applicable: false,
1709
1842
  reason: "a framed container carries no interactive role"
1710
1843
  },
1844
+ behavior: {
1845
+ applicable: false,
1846
+ reason: "a panel declares no callback prop; its content arrives as a snippet"
1847
+ },
1711
1848
  sketch: {
1712
1849
  style: "pencil",
1713
1850
  parts: [{ part: "root", fill: "--panel-stage-surface", stroke: "--panel-frame-border" }]
@@ -1783,6 +1920,20 @@ var progressBarContract = {
1783
1920
  applicable: false,
1784
1921
  reason: "a progress readout carries no interactive role"
1785
1922
  },
1923
+ behavior: {
1924
+ cases: [
1925
+ {
1926
+ name: "value drives the readout",
1927
+ props: { label: "Upload", value: 60 },
1928
+ expect: { kind: "text", part: "value", value: "60%" }
1929
+ },
1930
+ {
1931
+ name: "a value past the end clamps",
1932
+ props: { label: "Upload", value: 140 },
1933
+ expect: { kind: "text", part: "value", value: "100%" }
1934
+ }
1935
+ ]
1936
+ },
1786
1937
  sketch: {
1787
1938
  style: "pencil",
1788
1939
  parts: [{ part: "track", fill: "--progressbar-track-surface", stroke: "--progressbar-track-border" }]
@@ -1822,7 +1973,7 @@ var radioButtonContract = {
1822
1973
  properties: [
1823
1974
  { paints: statePaints4("default", true) },
1824
1975
  { state: "hover", paints: statePaints4("hover", true) },
1825
- { state: "active", paints: statePaints4("active", true) }
1976
+ { state: "selected", paints: statePaints4("selected", true) }
1826
1977
  ],
1827
1978
  states: [
1828
1979
  { state: "default" },
@@ -1832,9 +1983,9 @@ var radioButtonContract = {
1832
1983
  paints: statePaints4("hover", false)
1833
1984
  },
1834
1985
  {
1835
- state: "active",
1836
- forceClass: "active",
1837
- paints: statePaints4("active", false)
1986
+ state: "selected",
1987
+ forceClass: "selected",
1988
+ paints: statePaints4("selected", false)
1838
1989
  }
1839
1990
  ],
1840
1991
  persistence: {
@@ -1852,7 +2003,7 @@ var radioButtonContract = {
1852
2003
  changed: [
1853
2004
  "--radiobutton-default-dot-border-width",
1854
2005
  "--radiobutton-hover-dot-border-width",
1855
- "--radiobutton-active-dot-border-width"
2006
+ "--radiobutton-selected-dot-border-width"
1856
2007
  ],
1857
2008
  unchanged: ["--radiobutton-default-label-font-size"],
1858
2009
  aliasedTo: {
@@ -1871,6 +2022,21 @@ var radioButtonContract = {
1871
2022
  }
1872
2023
  ]
1873
2024
  },
2025
+ behavior: {
2026
+ cases: [
2027
+ {
2028
+ name: "clicking an option reports it",
2029
+ props: { label: "Weekly" },
2030
+ action: { kind: "click", part: "root" },
2031
+ expect: { kind: "callback", prop: "onclick", args: [] }
2032
+ },
2033
+ {
2034
+ name: "label names the option",
2035
+ props: { label: "Weekly" },
2036
+ expect: { kind: "text", part: "label", value: "Weekly" }
2037
+ }
2038
+ ]
2039
+ },
1874
2040
  sketch: {
1875
2041
  style: "pencil",
1876
2042
  parts: [{ part: "dot", fill: "--radiobutton-default-dot-fill", stroke: "--radiobutton-default-dot-border-color" }]
@@ -1890,7 +2056,7 @@ function variantPaints(v) {
1890
2056
  borderTopWidth: `--sectiondivider-${v}-border-width`,
1891
2057
  borderTopColor: `--sectiondivider-${v}-border`,
1892
2058
  boxShadow: `--sectiondivider-${v}-shadow`,
1893
- backgroundImage: `--sectiondivider-${v}-background`
2059
+ backgroundImage: `--sectiondivider-${v}-surface`
1894
2060
  },
1895
2061
  titleRow: { paddingTop: `--sectiondivider-${v}-title-padding` },
1896
2062
  title: {
@@ -1919,7 +2085,7 @@ function variantPaints(v) {
1919
2085
  },
1920
2086
  hairline: {
1921
2087
  backgroundColor: `--sectiondivider-${v}-hairline-color`,
1922
- height: `--sectiondivider-${v}-hairline-thickness`
2088
+ height: `--sectiondivider-${v}-hairline-width`
1923
2089
  }
1924
2090
  };
1925
2091
  }
@@ -1955,7 +2121,7 @@ var sectionDividerContract = {
1955
2121
  },
1956
2122
  {
1957
2123
  shape: "gradient",
1958
- variable: "--sectiondivider-lg-background",
2124
+ variable: "--sectiondivider-lg-surface",
1959
2125
  observe: { part: "root", css: "backgroundColor" }
1960
2126
  },
1961
2127
  {
@@ -1972,7 +2138,7 @@ var sectionDividerContract = {
1972
2138
  changed: [
1973
2139
  "--sectiondivider-lg-radius",
1974
2140
  "--sectiondivider-lg-border-width",
1975
- "--sectiondivider-lg-hairline-thickness",
2141
+ "--sectiondivider-lg-hairline-width",
1976
2142
  "--sectiondivider-lg-hairline-color"
1977
2143
  ],
1978
2144
  unchanged: [
@@ -1985,7 +2151,7 @@ var sectionDividerContract = {
1985
2151
  aliasedTo: {
1986
2152
  "--sectiondivider-lg-radius": "--radius-none",
1987
2153
  "--sectiondivider-lg-border-width": "--border-width-3",
1988
- "--sectiondivider-lg-hairline-thickness": "--border-width-3"
2154
+ "--sectiondivider-lg-hairline-width": "--border-width-3"
1989
2155
  },
1990
2156
  observe: { part: "root", css: "borderRadius", variable: "--sectiondivider-lg-radius" }
1991
2157
  },
@@ -1993,6 +2159,10 @@ var sectionDividerContract = {
1993
2159
  applicable: false,
1994
2160
  reason: "a divider is a static banner: no interactive role, nothing focusable, no pointer behaviour"
1995
2161
  },
2162
+ behavior: {
2163
+ applicable: false,
2164
+ reason: "a divider declares no callback prop and answers no event"
2165
+ },
1996
2166
  sketch: {
1997
2167
  style: "pencil",
1998
2168
  parts: [{ part: "hairline", fill: "--sectiondivider-lg-hairline-color" }]
@@ -2000,6 +2170,10 @@ var sectionDividerContract = {
2000
2170
  };
2001
2171
 
2002
2172
  // src/testing/contracts/segmentedcontrol.ts
2173
+ var behaviorSegments = [
2174
+ { value: "grid", label: "Grid" },
2175
+ { value: "list", label: "List" }
2176
+ ];
2003
2177
  var segmentedControlContract = {
2004
2178
  id: "segmentedcontrol",
2005
2179
  origin: "system",
@@ -2011,7 +2185,7 @@ var segmentedControlContract = {
2011
2185
  icon: ".segment i",
2012
2186
  selectedSegment: ".segment.selected",
2013
2187
  selectedIcon: ".segment.selected i",
2014
- divider: ".segment-divider"
2188
+ hairline: ".segment-hairline"
2015
2189
  },
2016
2190
  properties: [
2017
2191
  {
@@ -2025,10 +2199,10 @@ var segmentedControlContract = {
2025
2199
  columnGap: "--segmentedcontrol-bar-gap",
2026
2200
  paddingTop: "--segmentedcontrol-bar-padding"
2027
2201
  },
2028
- divider: {
2029
- backgroundColor: "--segmentedcontrol-divider-color",
2030
- width: "--segmentedcontrol-divider-thickness",
2031
- marginTop: "--segmentedcontrol-divider-inset"
2202
+ hairline: {
2203
+ backgroundColor: "--segmentedcontrol-hairline-color",
2204
+ width: "--segmentedcontrol-hairline-width",
2205
+ marginTop: "--segmentedcontrol-hairline-inset"
2032
2206
  }
2033
2207
  }
2034
2208
  },
@@ -2075,7 +2249,7 @@ var segmentedControlContract = {
2075
2249
  lineHeight: "--segmentedcontrol-option-small-text-line-height"
2076
2250
  },
2077
2251
  icon: { fontSize: "--segmentedcontrol-option-small-icon-size" },
2078
- divider: { width: "--segmentedcontrol-small-divider-thickness", marginTop: "--segmentedcontrol-small-divider-inset" }
2252
+ hairline: { width: "--segmentedcontrol-small-hairline-width", marginTop: "--segmentedcontrol-small-hairline-inset" }
2079
2253
  }
2080
2254
  }
2081
2255
  ],
@@ -2179,6 +2353,27 @@ var segmentedControlContract = {
2179
2353
  }
2180
2354
  ]
2181
2355
  },
2356
+ behavior: {
2357
+ cases: [
2358
+ {
2359
+ name: "clicking a segment asks for its value",
2360
+ props: { segments: behaviorSegments, value: "list" },
2361
+ action: { kind: "click", part: "segment" },
2362
+ expect: { kind: "callback", prop: "onchange", args: ["grid"] }
2363
+ },
2364
+ {
2365
+ name: "value drives the checked segment",
2366
+ props: { segments: behaviorSegments, value: "grid" },
2367
+ expect: { kind: "attribute", part: "segment", name: "aria-checked", value: "true" }
2368
+ },
2369
+ {
2370
+ name: "a disabled control stays silent",
2371
+ props: { segments: behaviorSegments, value: "list", disabled: true },
2372
+ action: { kind: "click", part: "segment" },
2373
+ expect: { kind: "no-callback", prop: "onchange" }
2374
+ }
2375
+ ]
2376
+ },
2182
2377
  sketch: {
2183
2378
  style: "pencil",
2184
2379
  parts: [
@@ -2198,11 +2393,11 @@ function titlePaints(s) {
2198
2393
  backgroundColor: `--sidenavigation-title-${s}-surface`,
2199
2394
  borderTopColor: `--sidenavigation-title-${s}-border`,
2200
2395
  borderTopWidth: `--sidenavigation-title-${s}-border-width`,
2201
- borderLeftColor: `--sidenavigation-title-${s}-accent`,
2202
- borderLeftWidth: `--sidenavigation-title-${s}-accent-width`,
2396
+ borderLeftColor: `--sidenavigation-title-${s}-indicator`,
2397
+ borderLeftWidth: `--sidenavigation-title-${s}-indicator-width`,
2203
2398
  paddingTop: `--sidenavigation-title-${s}-padding`
2204
2399
  },
2205
- titleLabel: {
2400
+ titleLinkBox: {
2206
2401
  color: `--sidenavigation-title-${s}-label`,
2207
2402
  fontFamily: `--sidenavigation-title-${s}-label-font-family`,
2208
2403
  fontSize: `--sidenavigation-title-${s}-label-font-size`,
@@ -2228,8 +2423,8 @@ function sectionPaints(part, labelPart, s) {
2228
2423
  return {
2229
2424
  [part]: {
2230
2425
  backgroundColor: `--sidenavigation-section-${s}-surface`,
2231
- borderLeftColor: `--sidenavigation-section-${s}-accent`,
2232
- borderLeftWidth: `--sidenavigation-section-${s}-accent-width`
2426
+ borderLeftColor: `--sidenavigation-section-${s}-indicator`,
2427
+ borderLeftWidth: `--sidenavigation-section-${s}-indicator-width`
2233
2428
  },
2234
2429
  [labelPart]: {
2235
2430
  color: `--sidenavigation-section-${s}-text`,
@@ -2244,8 +2439,8 @@ function itemPaints(part, s) {
2244
2439
  return {
2245
2440
  [part]: {
2246
2441
  backgroundColor: `--sidenavigation-item-${s}-surface`,
2247
- borderLeftColor: `--sidenavigation-item-${s}-accent`,
2248
- borderLeftWidth: `--sidenavigation-item-${s}-accent-width`,
2442
+ borderLeftColor: `--sidenavigation-item-${s}-indicator`,
2443
+ borderLeftWidth: `--sidenavigation-item-${s}-indicator-width`,
2249
2444
  paddingTop: `--sidenavigation-item-${s}-padding`,
2250
2445
  color: `--sidenavigation-item-${s}-text`,
2251
2446
  fontFamily: `--sidenavigation-item-${s}-text-font-family`,
@@ -2259,8 +2454,8 @@ function footerPaints(s) {
2259
2454
  return {
2260
2455
  footer: {
2261
2456
  backgroundColor: `--sidenavigation-footer-${s}-surface`,
2262
- borderLeftColor: `--sidenavigation-footer-${s}-accent`,
2263
- borderLeftWidth: `--sidenavigation-footer-${s}-accent-width`,
2457
+ borderLeftColor: `--sidenavigation-footer-${s}-indicator`,
2458
+ borderLeftWidth: `--sidenavigation-footer-${s}-indicator-width`,
2264
2459
  paddingTop: `--sidenavigation-footer-${s}-padding`,
2265
2460
  columnGap: `--sidenavigation-footer-${s}-gap`,
2266
2461
  color: `--sidenavigation-footer-${s}-text`,
@@ -2278,25 +2473,25 @@ function footerPaints(s) {
2278
2473
  var sideNavigationContract = {
2279
2474
  id: "sidenavigation",
2280
2475
  origin: "system",
2281
- // Section has no currentPath-driven active state (unlike Item, whose
2476
+ // Section has no currentPath-driven selected state (unlike Item, whose
2282
2477
  // demo path lands inside section-1): it lights up only through the force
2283
- // mechanism behind the "Active" sub-tab, so the inventory's one view has
2284
- // to land there for `sectionActive` to resolve at all.
2285
- view: { state: "Section", setup: sub("Active") },
2478
+ // mechanism behind the "Selected" sub-tab, so the inventory's one view has
2479
+ // to land there for `sectionSelected` to resolve at all.
2480
+ view: { state: "Section", setup: sub("Selected") },
2286
2481
  root: "root",
2287
2482
  parts: {
2288
2483
  root: ".sidenavigation",
2289
2484
  title: ".sn-title",
2290
- titleLabel: ".sn-title-label",
2485
+ titleLinkBox: ".sn-title-label",
2291
2486
  toggle: ".sn-toggle",
2292
2487
  toggleIcon: ".sn-toggle i",
2293
2488
  sectionWrap: ".sn-section",
2294
- section: ".sn-section-header:not(.active)",
2295
- sectionLabel: ".sn-section-header:not(.active) .section-label",
2296
- sectionActive: ".sn-section-header.active",
2297
- sectionLabelActive: ".sn-section-header.active .section-label",
2298
- item: ".sn-item:not(.active)",
2299
- itemActive: ".sn-item.active",
2489
+ section: ".sn-section-header:not(.selected)",
2490
+ sectionLabel: ".sn-section-header:not(.selected) .section-label",
2491
+ sectionSelected: ".sn-section-header.selected",
2492
+ sectionLabelSelected: ".sn-section-header.selected .section-label",
2493
+ item: ".sn-item:not(.selected)",
2494
+ itemSelected: ".sn-item.selected",
2300
2495
  footer: ".sn-footer",
2301
2496
  footerIcon: ".sn-footer i"
2302
2497
  },
@@ -2321,7 +2516,7 @@ var sideNavigationContract = {
2321
2516
  setup: [],
2322
2517
  paints: {
2323
2518
  title: { columnGap: "--sidenavigation-title-gap", borderRadius: "--sidenavigation-title-radius" },
2324
- titleLabel: {
2519
+ titleLinkBox: {
2325
2520
  backgroundColor: "--sidenavigation-title-label-surface",
2326
2521
  borderTopColor: "--sidenavigation-title-label-border",
2327
2522
  borderTopWidth: "--sidenavigation-title-label-border-width",
@@ -2332,18 +2527,18 @@ var sideNavigationContract = {
2332
2527
  },
2333
2528
  { state: "Title", setup: [], paints: titlePaints("default") },
2334
2529
  { state: "Title", setup: sub("Hover"), paints: titlePaints("hover") },
2335
- { state: "Title", setup: sub("Active"), paints: titlePaints("active") },
2530
+ { state: "Title", setup: sub("Selected"), paints: titlePaints("selected") },
2336
2531
  { state: "Toggle", setup: [], paints: togglePaints("default") },
2337
2532
  { state: "Toggle", setup: sub("Hover"), paints: togglePaints("hover") },
2338
2533
  { state: "Section", setup: [], paints: sectionPaints("section", "sectionLabel", "default") },
2339
2534
  { state: "Section", setup: sub("Hover"), paints: sectionPaints("section", "sectionLabel", "hover") },
2340
- { state: "Section", setup: sub("Active"), paints: sectionPaints("sectionActive", "sectionLabelActive", "active") },
2535
+ { state: "Section", setup: sub("Selected"), paints: sectionPaints("sectionSelected", "sectionLabelSelected", "selected") },
2341
2536
  { state: "Item", setup: [], paints: itemPaints("item", "default") },
2342
2537
  { state: "Item", setup: sub("Hover"), paints: itemPaints("item", "hover") },
2343
- { state: "Item", setup: [], paints: itemPaints("itemActive", "active") },
2538
+ { state: "Item", setup: [], paints: itemPaints("itemSelected", "selected") },
2344
2539
  { state: "Footer", setup: [], paints: footerPaints("default") },
2345
2540
  { state: "Footer", setup: sub("Hover"), paints: footerPaints("hover") },
2346
- { state: "Footer", setup: sub("Active"), paints: footerPaints("active") }
2541
+ { state: "Footer", setup: sub("Selected"), paints: footerPaints("selected") }
2347
2542
  ],
2348
2543
  states: [
2349
2544
  { state: "Panel", setup: [] },
@@ -2396,6 +2591,27 @@ var sideNavigationContract = {
2396
2591
  }
2397
2592
  ]
2398
2593
  },
2594
+ behavior: {
2595
+ cases: [
2596
+ {
2597
+ name: "clicking the rail toggle reports it",
2598
+ props: { title: "Docs" },
2599
+ action: { kind: "click", part: "toggle" },
2600
+ expect: { kind: "callback", prop: "ontoggle", args: [] }
2601
+ },
2602
+ {
2603
+ name: "open drives the toggle",
2604
+ props: { title: "Docs", open: false },
2605
+ expect: { kind: "attribute", part: "toggle", name: "aria-expanded", value: "false" }
2606
+ },
2607
+ {
2608
+ name: "clicking leaves the rail where the prop put it",
2609
+ props: { title: "Docs", open: true },
2610
+ action: { kind: "click", part: "toggle" },
2611
+ expect: { kind: "attribute", part: "toggle", name: "aria-expanded", value: "true" }
2612
+ }
2613
+ ]
2614
+ },
2399
2615
  sketch: {
2400
2616
  style: "pencil",
2401
2617
  parts: [{ part: "root", fill: "--sidenavigation-panel-surface", stroke: "--sidenavigation-panel-border" }]
@@ -2576,6 +2792,30 @@ var sliderContract = {
2576
2792
  }
2577
2793
  ]
2578
2794
  },
2795
+ behavior: {
2796
+ // No disabled case: a range reports through `input`, and a dispatched
2797
+ // input event reaches a disabled control, so the case would assert the
2798
+ // environment rather than the slider.
2799
+ cases: [
2800
+ {
2801
+ name: "moving the thumb reports the value",
2802
+ props: { label: "Level", value: 30 },
2803
+ action: { kind: "input", part: "input", value: "70" },
2804
+ expect: { kind: "callback", prop: "onchange", args: [70] }
2805
+ },
2806
+ {
2807
+ name: "a range thumb reports both ends",
2808
+ props: { variant: "range", low: 25, high: 75 },
2809
+ action: { kind: "input", part: "input", value: "10" },
2810
+ expect: { kind: "callback", prop: "onrangechange", args: [10, 75] }
2811
+ },
2812
+ {
2813
+ name: "value drives the readout",
2814
+ props: { label: "Level", value: 30 },
2815
+ expect: { kind: "text", part: "value", value: "30" }
2816
+ }
2817
+ ]
2818
+ },
2579
2819
  sketch: {
2580
2820
  style: "pencil",
2581
2821
  parts: [
@@ -2611,20 +2851,24 @@ function tabPaints(part, iconPart, s, full) {
2611
2851
  [iconPart]: { fontSize: `--tabbar-${s}-icon-size` }
2612
2852
  };
2613
2853
  }
2854
+ var behaviorTabs = [
2855
+ { id: "one", label: "One" },
2856
+ { id: "two", label: "Two" }
2857
+ ];
2614
2858
  var tabBarContract = {
2615
2859
  id: "tabbar",
2616
2860
  origin: "system",
2617
2861
  root: "root",
2618
2862
  parts: {
2619
2863
  root: ".tab-bar",
2620
- tab: ".tab:not(.active):not(:disabled)",
2621
- icon: ".tab:not(.active):not(:disabled) i",
2622
- activeTab: ".tab.active",
2623
- activeIcon: ".tab.active i",
2864
+ tab: ".tab:not(.selected):not(:disabled)",
2865
+ icon: ".tab:not(.selected):not(:disabled) i",
2866
+ tabSelected: ".tab.selected",
2867
+ selectedIcon: ".tab.selected i",
2624
2868
  disabledTab: ".tab:disabled",
2625
2869
  disabledIcon: ".tab:disabled i",
2626
- // Position-stable: clicking `tab` (".tab:not(.active)") makes that very
2627
- // tab active, which would invalidate that selector out from under a
2870
+ // Position-stable: clicking `tab` (".tab:not(.selected)") makes that very
2871
+ // tab selected, which would invalidate that selector out from under a
2628
2872
  // focus check re-resolved after the click.
2629
2873
  secondTab: ".tab:nth-of-type(2)"
2630
2874
  },
@@ -2633,8 +2877,8 @@ var tabBarContract = {
2633
2877
  state: "bar",
2634
2878
  paints: {
2635
2879
  root: {
2636
- borderBottomColor: "--tabbar-bar-divider",
2637
- borderBottomWidth: "--tabbar-bar-divider-thickness",
2880
+ borderBottomColor: "--tabbar-bar-hairline-color",
2881
+ borderBottomWidth: "--tabbar-bar-hairline-width",
2638
2882
  marginTop: "--tabbar-bar-top-margin",
2639
2883
  paddingBottom: "--tabbar-bar-bottom-padding",
2640
2884
  marginBottom: "--tabbar-bar-bottom-margin",
@@ -2644,14 +2888,14 @@ var tabBarContract = {
2644
2888
  },
2645
2889
  { state: "default tab", paints: tabPaints("tab", "icon", "default", true) },
2646
2890
  { state: "hover tab", paints: tabPaints("tab", "icon", "hover", true) },
2647
- { state: "active tab", paints: tabPaints("activeTab", "activeIcon", "active", true) },
2891
+ { state: "selected tab", paints: tabPaints("tabSelected", "selectedIcon", "selected", true) },
2648
2892
  { state: "disabled tab", paints: tabPaints("disabledTab", "disabledIcon", "disabled", true) }
2649
2893
  ],
2650
2894
  states: [
2651
2895
  { state: "bar" },
2652
2896
  { state: "default tab", paints: tabPaints("tab", "icon", "default", false) },
2653
2897
  { state: "hover tab", paints: tabPaints("tab", "icon", "hover", false) },
2654
- { state: "active tab", paints: tabPaints("activeTab", "activeIcon", "active", false) },
2898
+ { state: "selected tab", paints: tabPaints("tabSelected", "selectedIcon", "selected", false) },
2655
2899
  {
2656
2900
  state: "disabled tab",
2657
2901
  attributes: { disabledTab: { disabled: "" } },
@@ -2709,11 +2953,33 @@ var tabBarContract = {
2709
2953
  }
2710
2954
  ]
2711
2955
  },
2956
+ behavior: {
2957
+ cases: [
2958
+ {
2959
+ name: "clicking a tab asks for it",
2960
+ props: { tabs: behaviorTabs, value: "one" },
2961
+ action: { kind: "click", part: "secondTab" },
2962
+ expect: { kind: "callback", prop: "onchange", args: ["two"] }
2963
+ },
2964
+ {
2965
+ name: "clicking leaves the selection where the prop put it",
2966
+ props: { tabs: behaviorTabs, value: "one" },
2967
+ action: { kind: "click", part: "secondTab" },
2968
+ expect: { kind: "text", part: "tabSelected", value: "One" }
2969
+ },
2970
+ {
2971
+ name: "a disabled tab stays silent",
2972
+ props: { tabs: [behaviorTabs[0], { ...behaviorTabs[1], disabled: true }], value: "one" },
2973
+ action: { kind: "click", part: "secondTab" },
2974
+ expect: { kind: "no-callback", prop: "onchange" }
2975
+ }
2976
+ ]
2977
+ },
2712
2978
  sketch: {
2713
2979
  style: "pencil",
2714
2980
  parts: [
2715
2981
  { part: "tab", fill: "--tabbar-default-surface", stroke: "--tabbar-default-border" },
2716
- { part: "activeTab", fill: "--tabbar-active-surface", stroke: "--tabbar-active-border" }
2982
+ { part: "tabSelected", fill: "--tabbar-selected-surface", stroke: "--tabbar-selected-border" }
2717
2983
  ]
2718
2984
  }
2719
2985
  };
@@ -2745,11 +3011,11 @@ var tableContract = {
2745
3011
  fontSize: "--table-default-header-font-size",
2746
3012
  fontWeight: "--table-default-header-font-weight",
2747
3013
  lineHeight: "--table-default-header-line-height",
2748
- borderBottomColor: "--table-default-header-divider",
2749
- borderBottomWidth: "--table-default-header-divider-width",
3014
+ borderBottomColor: "--table-default-header-hairline-color",
3015
+ borderBottomWidth: "--table-default-header-hairline-width",
2750
3016
  paddingTop: "--table-default-header-padding",
2751
- borderRightColor: "--table-default-column-divider",
2752
- borderRightWidth: "--table-default-column-divider-width"
3017
+ borderRightColor: "--table-default-column-hairline-color",
3018
+ borderRightWidth: "--table-default-column-hairline-width"
2753
3019
  },
2754
3020
  td: {
2755
3021
  backgroundColor: "--table-default-row-surface",
@@ -2759,8 +3025,8 @@ var tableContract = {
2759
3025
  fontWeight: "--table-default-cell-font-weight",
2760
3026
  lineHeight: "--table-default-cell-line-height",
2761
3027
  paddingTop: "--table-default-cell-padding",
2762
- borderBottomColor: "--table-default-row-divider",
2763
- borderBottomWidth: "--table-default-row-divider-width"
3028
+ borderBottomColor: "--table-default-row-hairline-color",
3029
+ borderBottomWidth: "--table-default-row-hairline-width"
2764
3030
  }
2765
3031
  }
2766
3032
  }
@@ -2790,7 +3056,7 @@ var tableContract = {
2790
3056
  changed: [
2791
3057
  "--table-default-border-width",
2792
3058
  "--table-default-radius",
2793
- "--table-default-header-divider-width",
3059
+ "--table-default-header-hairline-width",
2794
3060
  "--table-default-header-padding"
2795
3061
  ],
2796
3062
  unchanged: ["--table-default-header-font-size"],
@@ -2804,6 +3070,10 @@ var tableContract = {
2804
3070
  applicable: false,
2805
3071
  reason: "a styled table wrapper carries no interactive role"
2806
3072
  },
3073
+ behavior: {
3074
+ applicable: false,
3075
+ reason: "a table wrapper declares no callback prop; its rows arrive as a snippet"
3076
+ },
2807
3077
  sketch: {
2808
3078
  style: "pencil",
2809
3079
  parts: [{ part: "wrapper", fill: "--table-default-surface", stroke: "--table-default-border" }]
@@ -2826,7 +3096,7 @@ var defaultPaints = {
2826
3096
  left: "--toggle-track-padding"
2827
3097
  },
2828
3098
  label: {
2829
- color: "--toggle-label-text",
3099
+ color: "--toggle-label",
2830
3100
  fontFamily: "--toggle-label-font-family",
2831
3101
  fontSize: "--toggle-label-font-size",
2832
3102
  fontWeight: "--toggle-label-font-weight"
@@ -2879,7 +3149,7 @@ var toggleContract = {
2879
3149
  paints: {
2880
3150
  track: { backgroundColor: "--toggle-disabled-track-surface" },
2881
3151
  thumb: { backgroundColor: "--toggle-disabled-thumb-surface" },
2882
- label: { color: "--toggle-disabled-label-text" }
3152
+ label: { color: "--toggle-disabled-label" }
2883
3153
  }
2884
3154
  }
2885
3155
  ],
@@ -2926,6 +3196,39 @@ var toggleContract = {
2926
3196
  }
2927
3197
  ]
2928
3198
  },
3199
+ behavior: {
3200
+ cases: [
3201
+ {
3202
+ name: "clicking an off toggle asks for on",
3203
+ props: { checked: false },
3204
+ action: { kind: "click", part: "root" },
3205
+ expect: { kind: "callback", prop: "onchange", args: [true] }
3206
+ },
3207
+ {
3208
+ name: "clicking leaves the switch where the prop put it",
3209
+ props: { checked: false },
3210
+ action: { kind: "click", part: "root" },
3211
+ expect: { kind: "attribute", part: "root", name: "aria-checked", value: "false" }
3212
+ },
3213
+ {
3214
+ name: "clicking an on toggle asks for off",
3215
+ props: { checked: true },
3216
+ action: { kind: "click", part: "root" },
3217
+ expect: { kind: "callback", prop: "onchange", args: [false] }
3218
+ },
3219
+ {
3220
+ name: "checked drives aria-checked",
3221
+ props: { checked: true },
3222
+ expect: { kind: "attribute", part: "root", name: "aria-checked", value: "true" }
3223
+ },
3224
+ {
3225
+ name: "a disabled toggle stays silent",
3226
+ props: { checked: false, disabled: true },
3227
+ action: { kind: "click", part: "root" },
3228
+ expect: { kind: "no-callback", prop: "onchange" }
3229
+ }
3230
+ ]
3231
+ },
2929
3232
  sketch: {
2930
3233
  style: "pencil",
2931
3234
  parts: [{ part: "track", fill: "--toggle-track-surface", stroke: "--toggle-track-border" }]
@@ -2992,6 +3295,15 @@ var tooltipContract = {
2992
3295
  applicable: false,
2993
3296
  reason: "a hint carries no interactive role; visibility follows the trigger element's hover or focus, which this component does not own"
2994
3297
  },
3298
+ behavior: {
3299
+ cases: [
3300
+ {
3301
+ name: "text drives the hint",
3302
+ props: { text: "Copy to clipboard" },
3303
+ expect: { kind: "text", part: "root", value: "Copy to clipboard" }
3304
+ }
3305
+ ]
3306
+ },
2995
3307
  sketch: {
2996
3308
  style: "pencil",
2997
3309
  parts: [{ part: "root", fill: "--tooltip-surface" }]
@@ -3051,13 +3363,9 @@ async function selectedContracts(contracts = shippedContracts) {
3051
3363
  }
3052
3364
 
3053
3365
  export {
3054
- ContractViolation,
3055
- isInapplicable,
3056
- requiresInteraction,
3057
- partLocator,
3058
3366
  shippedContracts,
3059
3367
  CONTRACTS_MODULE_ENV,
3060
3368
  allContracts,
3061
3369
  selectedContracts
3062
3370
  };
3063
- //# sourceMappingURL=chunk-4JQX6WWL.js.map
3371
+ //# sourceMappingURL=chunk-ZMZQZ33J.js.map