srcdev-nuxt-components 9.4.11 → 9.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.
Files changed (623) hide show
  1. package/.claude/skills/component-aria-landmark.md +1 -1
  2. package/.claude/skills/component-dynamic-slots.md +0 -1
  3. package/.claude/skills/component-export-types.md +3 -3
  4. package/.claude/skills/component-inline-action-button.md +7 -7
  5. package/.claude/skills/component-local-style-override.md +134 -50
  6. package/.claude/skills/component-naming.md +107 -0
  7. package/.claude/skills/components/action-menu.md +18 -14
  8. package/.claude/skills/components/alert-content.md +110 -0
  9. package/.claude/skills/components/alert-mask-core.md +15 -1
  10. package/.claude/skills/components/alert-masked-content.md +95 -0
  11. package/.claude/skills/components/auto-grid.md +21 -13
  12. package/.claude/skills/components/canvas-switcher.md +3 -3
  13. package/.claude/skills/components/capture-qr-code.md +19 -9
  14. package/.claude/skills/components/carousel-flip.md +3 -3
  15. package/.claude/skills/components/container-glow.md +2 -2
  16. package/.claude/skills/components/content-docs.md +9 -5
  17. package/.claude/skills/components/cookie-consent-banner.md +16 -17
  18. package/.claude/skills/components/dashboard-quad-grid.md +4 -4
  19. package/.claude/skills/components/decode-qr-code.md +15 -9
  20. package/.claude/skills/components/display-avatar.md +16 -31
  21. package/.claude/skills/components/display-chip.md +15 -10
  22. package/.claude/skills/components/display-dialog.md +3 -1
  23. package/.claude/skills/components/display-pill.md +17 -75
  24. package/.claude/skills/components/display-prompt.md +11 -19
  25. package/.claude/skills/components/display-qr-code.md +5 -0
  26. package/.claude/skills/components/display-theme-switch.md +7 -6
  27. package/.claude/skills/components/display-toast.md +5 -6
  28. package/.claude/skills/components/entry-animation.md +2 -5
  29. package/.claude/skills/components/eyebrow-text.md +6 -4
  30. package/.claude/skills/components/form-field.md +79 -0
  31. package/.claude/skills/components/form-fieldset.md +75 -0
  32. package/.claude/skills/components/form-wrapper.md +71 -0
  33. package/.claude/skills/components/glass-panel.md +60 -51
  34. package/.claude/skills/components/grid-stack.md +8 -2
  35. package/.claude/skills/components/header-block.md +1 -1
  36. package/.claude/skills/components/hero-text.md +8 -6
  37. package/.claude/skills/components/input-button.md +72 -0
  38. package/.claude/skills/components/input-checkbox-radio.md +149 -0
  39. package/.claude/skills/components/input-checkbox.md +148 -0
  40. package/.claude/skills/components/input-description.md +102 -0
  41. package/.claude/skills/components/input-error.md +105 -0
  42. package/.claude/skills/components/input-label.md +119 -0
  43. package/.claude/skills/components/{input-number-core.md → input-number.md} +41 -36
  44. package/.claude/skills/components/input-radio.md +95 -0
  45. package/.claude/skills/components/input-range-core.md +4 -4
  46. package/.claude/skills/components/input-select-core.md +1 -1
  47. package/.claude/skills/components/input-text-core.md +8 -6
  48. package/.claude/skills/components/input-textarea-core.md +4 -4
  49. package/.claude/skills/components/layout-grid-by-cols.md +31 -43
  50. package/.claude/skills/components/link-text.md +2 -2
  51. package/.claude/skills/components/opening-hours.md +116 -0
  52. package/.claude/skills/components/page-hero-highlights.md +35 -35
  53. package/.claude/skills/components/page-row.md +1 -1
  54. package/.claude/skills/components/pending-effect.md +63 -0
  55. package/.claude/skills/components/price-list.md +72 -0
  56. package/.claude/skills/components/pricing-card.md +3 -3
  57. package/.claude/skills/components/profile-section.md +6 -4
  58. package/.claude/skills/components/samaritan-prompt.md +140 -0
  59. package/.claude/skills/components/scroll-reveal-frame.md +21 -20
  60. package/.claude/skills/components/scroll-reveal-image.md +31 -21
  61. package/.claude/skills/components/service-detail.md +2 -2
  62. package/.claude/skills/components/services-card-grid.md +5 -4
  63. package/.claude/skills/components/services-card.md +12 -10
  64. package/.claude/skills/components/site-navigation.md +20 -6
  65. package/.claude/skills/components/slider-gallery.md +88 -0
  66. package/.claude/skills/components/social-icons-list.md +12 -6
  67. package/.claude/skills/components/tab-navigation.md +1 -1
  68. package/.claude/skills/components/text-block.md +68 -0
  69. package/.claude/skills/components/toggle-switch-core.md +3 -3
  70. package/.claude/skills/components/triple-toggle-switch.md +85 -0
  71. package/.claude/skills/composable-zod-validation.md +1 -1
  72. package/.claude/skills/consumer-styles-structure.md +153 -0
  73. package/.claude/skills/icon-sets.md +3 -3
  74. package/.claude/skills/icon-sizing.md +66 -0
  75. package/.claude/skills/index.md +35 -16
  76. package/.claude/skills/new-app-scaffold.md +45 -7
  77. package/.claude/skills/pull-request-description.md +1 -0
  78. package/.claude/skills/storybook-add-story.md +53 -5
  79. package/.claude/skills/testing-add-playwright.md +1 -1
  80. package/.claude/skills/theming-colour-ramps.md +25 -3
  81. package/.claude/skills/theming-component-token-pattern.md +16 -16
  82. package/.claude/skills/theming-override-default.md +7 -0
  83. package/.claude/skills/theming-partial-override.md +1 -1
  84. package/.claude/skills/theming-typography-tokens.md +1 -1
  85. package/.claude/skills/vercel-node-version.md +1 -1
  86. package/.vscode/srcdev-component-action-menu.code-snippets +42 -0
  87. package/.vscode/srcdev-component-alert-content.code-snippets +36 -0
  88. package/.vscode/srcdev-component-alert-masked-content.code-snippets +35 -0
  89. package/.vscode/srcdev-component-auto-grid.code-snippets +39 -0
  90. package/.vscode/srcdev-component-capture-decode-qr-code.code-snippets +28 -0
  91. package/.vscode/srcdev-component-content-docs.code-snippets +4 -4
  92. package/.vscode/srcdev-component-cookie-consent-banner.code-snippets +33 -0
  93. package/.vscode/srcdev-component-display-avatar.code-snippets +28 -0
  94. package/.vscode/srcdev-component-display-chip.code-snippets +27 -0
  95. package/.vscode/srcdev-component-display-pill.code-snippets +38 -0
  96. package/.vscode/srcdev-component-display-prompt.code-snippets +10 -54
  97. package/.vscode/srcdev-component-display-qr-code.code-snippets +22 -0
  98. package/.vscode/srcdev-component-eyebrow-text.code-snippets +19 -0
  99. package/.vscode/srcdev-component-form-field.code-snippets +25 -0
  100. package/.vscode/srcdev-component-form-fieldset.code-snippets +36 -0
  101. package/.vscode/srcdev-component-form-wrapper.code-snippets +30 -0
  102. package/.vscode/srcdev-component-glass-panel.code-snippets +38 -0
  103. package/.vscode/srcdev-component-grid-stack.code-snippets +49 -0
  104. package/.vscode/srcdev-component-input-button.code-snippets +27 -0
  105. package/.vscode/srcdev-component-input-checkbox-radio.code-snippets +60 -0
  106. package/.vscode/srcdev-component-input-checkbox.code-snippets +48 -0
  107. package/.vscode/srcdev-component-input-description.code-snippets +44 -0
  108. package/.vscode/srcdev-component-input-error.code-snippets +30 -0
  109. package/.vscode/srcdev-component-input-label.code-snippets +39 -0
  110. package/.vscode/srcdev-component-input-number.code-snippets +11 -11
  111. package/.vscode/srcdev-component-input-radio.code-snippets +58 -0
  112. package/.vscode/srcdev-component-layout-grid-by-cols.code-snippets +46 -0
  113. package/.vscode/srcdev-component-link-text.code-snippets +30 -0
  114. package/.vscode/srcdev-component-opening-hours.code-snippets +40 -0
  115. package/.vscode/srcdev-component-page-hero-highlights.code-snippets +37 -0
  116. package/.vscode/srcdev-component-page-row.code-snippets +47 -0
  117. package/.vscode/srcdev-component-pending-effect.code-snippets +26 -0
  118. package/.vscode/srcdev-component-price-list.code-snippets +37 -0
  119. package/.vscode/srcdev-component-pricing-card.code-snippets +2 -2
  120. package/.vscode/srcdev-component-profile-section.code-snippets +36 -0
  121. package/.vscode/srcdev-component-samaritan-prompt.code-snippets +60 -0
  122. package/.vscode/srcdev-component-scroll-reveal-frame.code-snippets +36 -0
  123. package/.vscode/srcdev-component-scroll-reveal-image.code-snippets +46 -0
  124. package/.vscode/srcdev-component-services-card.code-snippets +4 -4
  125. package/.vscode/srcdev-component-services-grids.code-snippets +36 -0
  126. package/.vscode/srcdev-component-site-navigation.code-snippets +26 -18
  127. package/.vscode/srcdev-component-slider-gallery.code-snippets +9 -0
  128. package/.vscode/srcdev-component-social-icons-list.code-snippets +24 -0
  129. package/.vscode/srcdev-component-stepper-list.code-snippets +39 -0
  130. package/.vscode/srcdev-component-text-block.code-snippets +31 -0
  131. package/.vscode/srcdev-component-triple-toggle-switch.code-snippets +30 -0
  132. package/README.md +2 -2
  133. package/app/app.config.ts +10 -0
  134. package/app/assets/styles/setup/02.colours/_orange.css +11 -11
  135. package/app/assets/styles/setup/02.colours/_theme-params.css +2 -2
  136. package/app/assets/styles/setup/03.theming/_default.css +1 -22
  137. package/app/assets/styles/setup/03.theming/_theme-slots.css +1 -1
  138. package/app/assets/styles/setup/03.theming/_warning.css +8 -10
  139. package/app/assets/styles/setup/04.elements/forms/02.typography.css +0 -14
  140. package/app/assets/styles/setup/04.elements/forms/06.button-geometry.css +1 -1
  141. package/app/assets/styles/setup/index.css +1 -1
  142. package/app/components/01.atoms/alert-mask/AlertMaskCore.vue +23 -5
  143. package/app/components/01.atoms/alert-mask/CONSUMER-STYLING.md +23 -5
  144. package/app/components/01.atoms/alert-mask/stories/AlertMaskCore.stories.ts +45 -19
  145. package/app/components/01.atoms/alert-mask/tests/AlertMaskCore.spec.ts +35 -1
  146. package/app/components/01.atoms/animations/animated-svg-text/CONSUMER-STYLING.md +13 -0
  147. package/app/components/01.atoms/animations/clip-element/CONSUMER-STYLING.md +13 -0
  148. package/app/components/01.atoms/animations/clip-element/ClipElement.vue +2 -2
  149. package/app/components/01.atoms/animations/container-glow/CONSUMER-STYLING.md +26 -5
  150. package/app/components/01.atoms/animations/entry/.nuxt/app.config.mjs +21 -0
  151. package/app/components/01.atoms/animations/entry/.nuxt/components.d.ts +66 -0
  152. package/app/components/01.atoms/animations/entry/.nuxt/imports.d.ts +30 -0
  153. package/app/components/01.atoms/animations/entry/.nuxt/manifest/meta/test.json +1 -0
  154. package/app/components/01.atoms/animations/entry/.nuxt/types/app.config.d.ts +35 -0
  155. package/app/components/01.atoms/animations/entry/.nuxt/types/build.d.ts +23 -0
  156. package/app/components/01.atoms/animations/entry/.nuxt/types/builder-env.d.ts +1 -0
  157. package/app/components/01.atoms/animations/entry/.nuxt/types/components.d.ts +71 -0
  158. package/app/components/01.atoms/animations/entry/.nuxt/types/imports.d.ts +386 -0
  159. package/app/components/01.atoms/animations/entry/.nuxt/types/middleware.d.ts +11 -0
  160. package/app/components/01.atoms/animations/entry/.nuxt/types/modules.d.ts +79 -0
  161. package/app/components/01.atoms/animations/entry/.nuxt/types/nitro-layouts.d.ts +17 -0
  162. package/app/components/01.atoms/animations/entry/.nuxt/types/nitro-nuxt.d.ts +64 -0
  163. package/app/components/01.atoms/animations/entry/.nuxt/types/plugins.d.ts +29 -0
  164. package/app/components/01.atoms/animations/entry/.nuxt/types/runtime-config.d.ts +32 -0
  165. package/app/components/01.atoms/animations/entry/.nuxt/types/shared-imports.d.ts +10 -0
  166. package/app/components/01.atoms/animations/entry/.nuxt/types/vue-shim.d.ts +0 -0
  167. package/app/components/01.atoms/animations/entry/.nuxtrc +1 -0
  168. package/app/components/01.atoms/animations/entry/CONSUMER-STYLING.md +65 -0
  169. package/app/components/01.atoms/animations/entry/EntryAnimation.vue +6 -5
  170. package/app/components/01.atoms/animations/entry/node_modules/.cache/nuxt/chrome-workspace.json +1 -0
  171. package/app/components/01.atoms/animations/entry/node_modules/.cache/vite/client/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  172. package/app/components/01.atoms/animations/entry/stories/EntryAnimation.stories.ts +1 -1
  173. package/app/components/01.atoms/animations/entry/tests/EntryAnimation.spec.ts +25 -0
  174. package/app/components/01.atoms/animations/glowing-border/CONSUMER-STYLING.md +24 -5
  175. package/app/components/01.atoms/animations/marquee-scroller/CONSUMER-STYLING.md +20 -0
  176. package/app/components/01.atoms/animations/rotating-carousel-image/CONSUMER-STYLING.md +17 -0
  177. package/app/components/01.atoms/animations/scroll-reveal-frame/CONSUMER-STYLING.md +77 -0
  178. package/app/components/01.atoms/animations/scroll-reveal-frame/ScrollRevealFrame.vue +37 -78
  179. package/app/components/01.atoms/animations/scroll-reveal-frame/stories/ScrollRevealFrame.stories.ts +48 -0
  180. package/app/components/01.atoms/animations/scroll-reveal-frame/tests/ScrollRevealFrame.spec.ts +40 -33
  181. package/app/components/01.atoms/animations/scroll-reveal-frame/tests/__snapshots__/ScrollRevealFrame.spec.ts.snap +4 -4
  182. package/app/components/01.atoms/animations/scroll-reveal-image/CONSUMER-STYLING.md +74 -0
  183. package/app/components/01.atoms/animations/scroll-reveal-image/ScrollRevealImage.vue +14 -44
  184. package/app/components/01.atoms/animations/scroll-reveal-image/stories/ScrollRevealImage.stories.ts +50 -1
  185. package/app/components/01.atoms/animations/scroll-reveal-image/tests/ScrollRevealImage.spec.ts +27 -20
  186. package/app/components/01.atoms/animations/scroll-reveal-image/tests/__snapshots__/ScrollRevealImage.spec.ts.snap +4 -4
  187. package/app/components/01.atoms/animations/section-parallax/CONSUMER-STYLING.md +21 -4
  188. package/app/components/01.atoms/animations/view-timeline/CONSUMER-STYLING.md +25 -0
  189. package/app/components/01.atoms/banner-video/CONSUMER-STYLING.md +12 -5
  190. package/app/components/01.atoms/canvas-switcher/CONSUMER-STYLING.md +20 -7
  191. package/app/components/01.atoms/canvas-switcher/CanvasSwitcher.vue +12 -7
  192. package/app/components/01.atoms/card/CONSUMER-STYLING.md +47 -42
  193. package/app/components/01.atoms/card/CardCore.vue +7 -17
  194. package/app/components/01.atoms/clipped-panel/CONSUMER-STYLING.md +13 -0
  195. package/app/components/01.atoms/content-wrappers/docs-pages/CONSUMER-STYLING.md +127 -0
  196. package/app/components/01.atoms/content-wrappers/docs-pages/ContentDocs.vue +44 -77
  197. package/app/components/01.atoms/content-wrappers/docs-pages/stories/ContentDocs.stories.ts +3 -3
  198. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/CONSUMER-STYLING.md +14 -1
  199. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/stories/DashboardQuadGrid.stories.ts +2 -0
  200. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/CONSUMER-STYLING.md +13 -0
  201. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/stories/DashboardStatsGrid.stories.ts +2 -0
  202. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/CONSUMER-STYLING.md +72 -0
  203. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/LayoutGridByCols.vue +26 -25
  204. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/stories/LayoutGridByCols.stories.ts +91 -107
  205. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/LayoutGridByCols.spec.ts +50 -15
  206. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/__snapshots__/LayoutGridByCols.spec.ts.snap +5 -5
  207. package/app/components/01.atoms/display-banner/CONSUMER-STYLING.md +13 -0
  208. package/app/components/01.atoms/display-dialog/CONSUMER-STYLING.md +82 -54
  209. package/app/components/01.atoms/display-dialog/DisplayDialog.vue +38 -45
  210. package/app/components/01.atoms/display-dialog/stories/DisplayDialog.stories.ts +25 -0
  211. package/app/components/01.atoms/display-dialog/tests/DisplayDialog.spec.ts +21 -0
  212. package/app/components/01.atoms/display-pill/CONSUMER-STYLING.md +112 -0
  213. package/app/components/01.atoms/display-pill/DisplayPill.vue +88 -50
  214. package/app/components/01.atoms/display-pill/stories/DisplayPill.stories.ts +56 -3
  215. package/app/components/01.atoms/display-pill/tests/DisplayPill.spec.ts +104 -4
  216. package/app/components/01.atoms/display-pill/tests/__snapshots__/DisplayPill.spec.ts.snap +3 -3
  217. package/app/components/01.atoms/display-tooltip/CONSUMER-STYLING.md +22 -2
  218. package/app/components/01.atoms/display-tooltip/DisplayTooltip.vue +18 -26
  219. package/app/components/01.atoms/glass-panel/CONSUMER-STYLING.md +91 -0
  220. package/app/components/01.atoms/glass-panel/GlassPanel.vue +34 -30
  221. package/app/components/01.atoms/glass-panel/stories/GlassPanel.stories.ts +121 -0
  222. package/app/components/01.atoms/glass-panel/tests/GlassPanel.spec.ts +61 -0
  223. package/app/components/01.atoms/grids/auto-grid/AutoGrid.vue +5 -10
  224. package/app/components/01.atoms/grids/auto-grid/CONSUMER-STYLING.md +76 -0
  225. package/app/components/01.atoms/grids/auto-grid/stories/AutoGrid.stories.ts +5 -4
  226. package/app/components/01.atoms/grids/auto-grid/tests/AutoGrid.spec.ts +8 -0
  227. package/app/components/01.atoms/grids/column-flow-grid/CONSUMER-STYLING.md +11 -2
  228. package/app/components/01.atoms/grids/grid-stack/CONSUMER-STYLING.md +76 -0
  229. package/app/components/01.atoms/grids/grid-stack/GridStack.vue +6 -1
  230. package/app/components/01.atoms/grids/grid-stack/stories/GridStack.stories.ts +1 -1
  231. package/app/components/01.atoms/grids/grid-stack/tests/GridStack.spec.ts +35 -0
  232. package/app/components/01.atoms/grids/masonry-grid/CONSUMER-STYLING.md +11 -2
  233. package/app/components/01.atoms/navigation/breadcrumb/Breadcrumb.vue +5 -10
  234. package/app/components/01.atoms/navigation/breadcrumb/CONSUMER-STYLING.md +15 -0
  235. package/app/components/01.atoms/navigation/skip-links/CONSUMER-STYLING.md +13 -0
  236. package/app/components/01.atoms/navigation/tabs/CONSUMER-STYLING.md +21 -0
  237. package/app/components/01.atoms/page-row/CONSUMER-STYLING.md +46 -8
  238. package/app/components/01.atoms/page-row/PageRow.vue +17 -13
  239. package/app/components/01.atoms/page-row/stories/PageRow.stories.ts +8 -0
  240. package/app/components/01.atoms/page-row/tests/PageRow.spec.ts +7 -11
  241. package/app/components/01.atoms/pop-over/CONSUMER-STYLING.md +13 -0
  242. package/app/components/01.atoms/qr-code/CONSUMER-STYLING.md +48 -0
  243. package/app/components/01.atoms/qr-code/DisplayQrCode.vue +5 -1
  244. package/app/components/01.atoms/qr-code/stories/DisplayQrCode.stories.ts +11 -3
  245. package/app/components/01.atoms/qr-code/tests/DisplayQrCode.spec.ts +15 -0
  246. package/app/components/01.atoms/text-block/CONSUMER-STYLING.md +49 -0
  247. package/app/components/01.atoms/text-block/TextBlock.vue +13 -5
  248. package/app/components/01.atoms/text-block/stories/TextBlock.stories.ts +84 -0
  249. package/app/components/01.atoms/text-block/tests/TextBlock.spec.ts +78 -0
  250. package/app/components/01.atoms/text-block/tests/__snapshots__/TextBlock.spec.ts.snap +7 -0
  251. package/app/components/01.atoms/text-blocks/eyebrow-text/CONSUMER-STYLING.md +56 -0
  252. package/app/components/01.atoms/text-blocks/eyebrow-text/EyebrowText.vue +10 -5
  253. package/app/components/01.atoms/text-blocks/eyebrow-text/tests/EyebrowText.spec.ts +11 -0
  254. package/app/components/01.atoms/text-blocks/header-block/CONSUMER-STYLING.md +16 -1
  255. package/app/components/01.atoms/text-blocks/hero-text/CONSUMER-STYLING.md +74 -0
  256. package/app/components/01.atoms/text-blocks/hero-text/HeroText.vue +14 -9
  257. package/app/components/01.atoms/text-blocks/hero-text/tests/HeroText.spec.ts +11 -0
  258. package/app/components/01.atoms/text-blocks/link-text/CONSUMER-STYLING.md +45 -0
  259. package/app/components/01.atoms/text-blocks/link-text/LinkText.vue +15 -8
  260. package/app/components/01.atoms/text-blocks/link-text/tests/LinkText.spec.ts +11 -0
  261. package/app/components/01.atoms/ui-block-decorated/CONSUMER-STYLING.md +13 -0
  262. package/app/components/02.molecules/action-menu/ActionMenu.vue +28 -30
  263. package/app/components/02.molecules/action-menu/{ActionMenuItemCore.vue → ActionMenuItem.vue} +12 -14
  264. package/app/components/02.molecules/action-menu/CONSUMER-STYLING.md +90 -76
  265. package/app/components/02.molecules/action-menu/stories/ActionMenu.stories.ts +48 -41
  266. package/app/components/02.molecules/action-menu/tests/ActionMenu.spec.ts +46 -1
  267. package/app/components/02.molecules/action-menu/tests/{ActionMenuItemCore.spec.ts → ActionMenuItem.spec.ts} +11 -5
  268. package/app/components/02.molecules/action-menu/tests/__snapshots__/ActionMenuItem.spec.ts.snap +27 -0
  269. package/app/components/02.molecules/alert-content/AlertContent.vue +17 -8
  270. package/app/components/02.molecules/alert-content/AlertContentInner.vue +57 -30
  271. package/app/components/02.molecules/alert-content/CONSUMER-STYLING.md +84 -0
  272. package/app/components/02.molecules/alert-content/stories/AlertContent.stories.ts +39 -0
  273. package/app/components/02.molecules/alert-content/tests/AlertContent.spec.ts +32 -0
  274. package/app/components/02.molecules/alert-content/tests/AlertContentInner.spec.ts +32 -0
  275. package/app/components/02.molecules/alert-masked-content/AlertMaskedContent.vue +9 -5
  276. package/app/components/02.molecules/alert-masked-content/CONSUMER-STYLING.md +73 -0
  277. package/app/components/02.molecules/alert-masked-content/stories/AlertMaskedContent.stories.ts +91 -10
  278. package/app/components/02.molecules/alert-masked-content/tests/AlertMaskedContent.spec.ts +52 -0
  279. package/app/components/02.molecules/cookie-consent-banner/CONSUMER-STYLING.md +95 -0
  280. package/app/components/02.molecules/cookie-consent-banner/CookieConsentBanner.vue +149 -0
  281. package/app/components/{01.atoms → 02.molecules}/cookie-consent-banner/stories/CookieConsentBanner.stories.ts +22 -3
  282. package/app/components/{01.atoms → 02.molecules}/cookie-consent-banner/tests/CookieConsentBanner.spec.ts +81 -4
  283. package/app/components/02.molecules/display-avatar/CONSUMER-STYLING.md +63 -0
  284. package/app/components/02.molecules/display-avatar/DisplayAvatar.vue +120 -0
  285. package/app/components/{01.atoms → 02.molecules}/display-avatar/stories/DisplayAvatar.stories.ts +56 -14
  286. package/app/components/{01.atoms → 02.molecules}/display-avatar/tests/DisplayAvatar.spec.ts +43 -11
  287. package/app/components/02.molecules/display-avatar/tests/__snapshots__/DisplayAvatar.spec.ts.snap +11 -0
  288. package/app/components/02.molecules/display-chip/CONSUMER-STYLING.md +57 -0
  289. package/app/components/02.molecules/display-chip/DisplayChip.vue +50 -83
  290. package/app/components/02.molecules/display-chip/tests/DisplayChip.spec.ts +10 -10
  291. package/app/components/02.molecules/display-chip/tests/__snapshots__/DisplayChip.spec.ts.snap +4 -4
  292. package/app/components/02.molecules/display-theme-switch/CONSUMER-STYLING.md +25 -4
  293. package/app/components/02.molecules/display-theme-switch/DisplayThemeSwitch.vue +9 -6
  294. package/app/components/02.molecules/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +6 -1
  295. package/app/components/02.molecules/display-theme-switch/tests/DisplayThemeSwitch.spec.ts +10 -1
  296. package/app/components/02.molecules/display-tooltip-defined/CONSUMER-STYLING.md +11 -0
  297. package/app/components/02.molecules/expandable/accordian/CONSUMER-STYLING.md +11 -4
  298. package/app/components/02.molecules/expandable/expanding-panel/CONSUMER-STYLING.md +12 -5
  299. package/app/components/02.molecules/expandable/expanding-panel-classic/CONSUMER-STYLING.md +12 -5
  300. package/app/components/02.molecules/input-copy/CONSUMER-STYLING.md +12 -5
  301. package/app/components/02.molecules/input-copy/InputCopy.vue +12 -25
  302. package/app/components/02.molecules/input-copy/stories/InputCopy.stories.ts +1 -1
  303. package/app/components/02.molecules/input-copy/tests/InputCopy.spec.ts +1 -1
  304. package/app/components/02.molecules/navigation/deep-expanding-menu/CONSUMER-STYLING.md +13 -0
  305. package/app/components/02.molecules/navigation/deep-expanding-menu-classic/CONSUMER-STYLING.md +11 -0
  306. package/app/components/02.molecules/navigation/site-navigation/CONSUMER-STYLING.md +109 -0
  307. package/app/components/02.molecules/navigation/site-navigation/SiteNavigation.vue +37 -55
  308. package/app/components/02.molecules/navigation/site-navigation/stories/SiteNavigation.stories.ts +22 -1
  309. package/app/components/02.molecules/navigation/site-navigation/tests/SiteNavigation.spec.ts +41 -6
  310. package/app/components/02.molecules/navigation/tab-navigation/CONSUMER-STYLING.md +13 -8
  311. package/app/components/02.molecules/navigation/tab-navigation/TabNavigation.vue +18 -36
  312. package/app/components/02.molecules/navigation/tab-navigation/stories/TabNavigation.stories.ts +1 -1
  313. package/app/components/02.molecules/navigation/tab-navigation/tests/TabNavigation.spec.ts +1 -1
  314. package/app/components/02.molecules/opening-hours/CONSUMER-STYLING.md +134 -0
  315. package/app/components/02.molecules/opening-hours/OpeningHours.vue +352 -0
  316. package/app/components/02.molecules/opening-hours/stories/OpeningHours.stories.ts +127 -0
  317. package/app/components/02.molecules/opening-hours/tests/OpeningHours.spec.ts +228 -0
  318. package/app/components/02.molecules/opening-hours/tests/OpeningHours.structuredData.spec.ts +45 -0
  319. package/app/components/02.molecules/opening-hours/tests/__snapshots__/OpeningHours.spec.ts.snap +23 -0
  320. package/app/components/02.molecules/opening-hours/tests/buildOpeningHoursSpecification.spec.ts +52 -0
  321. package/app/components/02.molecules/price-list/CONSUMER-STYLING.md +106 -0
  322. package/app/components/02.molecules/price-list/PriceList.vue +48 -40
  323. package/app/components/02.molecules/price-list/stories/PriceList.stories.ts +15 -2
  324. package/app/components/02.molecules/price-list/tests/PriceList.spec.ts +39 -2
  325. package/app/components/02.molecules/price-list/tests/__snapshots__/PriceList.spec.ts.snap +4 -16
  326. package/app/components/02.molecules/pricing-card/CONSUMER-STYLING.md +23 -5
  327. package/app/components/02.molecules/pricing-card/PricingCard.vue +31 -61
  328. package/app/components/02.molecules/pricing-card/stories/PricingCard.stories.ts +2 -0
  329. package/app/components/02.molecules/pricing-card/tests/PricingCard.spec.ts +14 -1
  330. package/app/components/02.molecules/profile-section/CONSUMER-STYLING.md +53 -0
  331. package/app/components/02.molecules/profile-section/ProfileSection.vue +53 -66
  332. package/app/components/02.molecules/profile-section/tests/ProfileSection.spec.ts +4 -4
  333. package/app/components/02.molecules/profile-section/tests/__snapshots__/ProfileSection.spec.ts.snap +6 -12
  334. package/app/components/02.molecules/prompt/CONSUMER-STYLING.md +51 -0
  335. package/app/components/{01.atoms → 02.molecules}/prompt/DisplayPrompt.vue +23 -8
  336. package/app/components/{01.atoms → 02.molecules}/prompt/stories/DisplayPrompt.stories.ts +18 -1
  337. package/app/components/{01.atoms → 02.molecules}/prompt/tests/DisplayPrompt.spec.ts +37 -7
  338. package/app/components/02.molecules/qr-code/CONSUMER-STYLING.md +66 -0
  339. package/app/components/02.molecules/qr-code/CaptureQrCode.vue +31 -12
  340. package/app/components/02.molecules/qr-code/DecodeQrCode.vue +55 -19
  341. package/app/components/02.molecules/qr-code/stories/CaptureQrCode.stories.ts +56 -0
  342. package/app/components/02.molecules/qr-code/stories/DecodeQrCode.stories.ts +53 -0
  343. package/app/components/02.molecules/qr-code/tests/CaptureQrCode.spec.ts +68 -20
  344. package/app/components/02.molecules/qr-code/tests/DecodeQrCode.spec.ts +44 -8
  345. package/app/components/02.molecules/samaritan-prompt/CONSUMER-STYLING.md +118 -0
  346. package/app/components/02.molecules/samaritan-prompt/SamaritanPrompt.vue +108 -51
  347. package/app/components/02.molecules/samaritan-prompt/SamaritanPromptMixed.vue +63 -62
  348. package/app/components/02.molecules/samaritan-prompt/stories/SamaritanPrompt.stories.ts +129 -0
  349. package/app/components/02.molecules/samaritan-prompt/stories/SamaritanPromptMixed.stories.ts +124 -0
  350. package/app/components/02.molecules/samaritan-prompt/tests/SamaritanPrompt.spec.ts +66 -0
  351. package/app/components/02.molecules/samaritan-prompt/tests/SamaritanPromptMixed.spec.ts +95 -17
  352. package/app/components/02.molecules/select-menu/CONSUMER-STYLING.md +11 -2
  353. package/app/components/02.molecules/social-icons-list/CONSUMER-STYLING.md +43 -0
  354. package/app/components/02.molecules/social-icons-list/SocialIconsList.vue +15 -15
  355. package/app/components/02.molecules/social-icons-list/stories/SocialIconsList.stories.ts +6 -1
  356. package/app/components/02.molecules/social-icons-list/tests/SocialIconsList.spec.ts +22 -1
  357. package/app/components/02.molecules/social-icons-list/tests/__snapshots__/SocialIconsList.spec.ts.snap +3 -3
  358. package/app/components/02.molecules/stepper-list/CONSUMER-STYLING.md +44 -5
  359. package/app/components/02.molecules/stepper-list/StepperList.vue +23 -43
  360. package/app/components/02.molecules/stepper-list/tests/StepperList.spec.ts +9 -0
  361. package/app/components/{01.atoms → 02.molecules}/toast/CONSUMER-STYLING.md +14 -0
  362. package/app/components/{01.atoms → 02.molecules}/toast/DisplayToast.vue +1 -2
  363. package/app/components/{01.atoms → 02.molecules}/toast/DisplayToastProvider.vue +1 -2
  364. package/app/components/{01.atoms → 02.molecules}/toast/stories/DisplayToast.stories.ts +1 -1
  365. package/app/components/{01.atoms → 02.molecules}/toast/stories/DisplayToastProvider.stories.ts +1 -1
  366. package/app/components/03.organisms/image-galleries/carousel-flip/CONSUMER-STYLING.md +13 -0
  367. package/app/components/03.organisms/image-galleries/slider-gallery/CONSUMER-STYLING.md +137 -0
  368. package/app/components/03.organisms/image-galleries/slider-gallery/SliderGallery.vue +378 -343
  369. package/app/components/03.organisms/image-galleries/slider-gallery/stories/SliderGallery.stories.ts +26 -1
  370. package/app/components/03.organisms/image-galleries/slider-gallery/tests/SliderGallery.spec.ts +102 -23
  371. package/app/components/03.organisms/image-galleries/slider-gallery/tests/__snapshots__/SliderGallery.spec.ts.snap +44 -44
  372. package/app/components/03.organisms/responsive-header/CONSUMER-STYLING.md +12 -1
  373. package/app/components/03.organisms/responsive-header/ResponsiveHeader.vue +0 -4
  374. package/app/components/03.organisms/services/service-detail/CONSUMER-STYLING.md +24 -3
  375. package/app/components/03.organisms/services/service-detail/ServiceDetail.vue +3 -3
  376. package/app/components/03.organisms/services/service-detail/stories/ServiceDetail.stories.ts +13 -13
  377. package/app/components/03.organisms/services/service-detail/tests/__snapshots__/ServiceDetail.spec.ts.snap +1 -1
  378. package/app/components/03.organisms/services/service-summary/CONSUMER-STYLING.md +24 -7
  379. package/app/components/03.organisms/services/service-summary/ServiceSummary.vue +3 -3
  380. package/app/components/03.organisms/services/service-summary/stories/ServiceSummary.stories.ts +1 -1
  381. package/app/components/03.organisms/services/service-summary/tests/__snapshots__/ServiceSummary.spec.ts.snap +1 -1
  382. package/app/components/03.organisms/services/services-card/CONSUMER-STYLING.md +11 -2
  383. package/app/components/03.organisms/services/services-card/ServicesCard.vue +17 -26
  384. package/app/components/03.organisms/services/services-card/tests/ServicesCard.spec.ts +21 -0
  385. package/app/components/03.organisms/services/services-grids/CONSUMER-STYLING.md +50 -0
  386. package/app/components/03.organisms/services/services-grids/ServicesCardGrid.vue +9 -16
  387. package/app/components/03.organisms/services/services-grids/stories/ServicesCardGrid.stories.ts +6 -0
  388. package/app/components/03.organisms/services/services-grids/tests/ServicesCardGrid.spec.ts +18 -0
  389. package/app/components/03.organisms/services/services-grids/tests/__snapshots__/ServiceSummaryGrid.spec.ts.snap +3 -3
  390. package/app/components/03.organisms/services/services-grids/tests/__snapshots__/ServicesCardGrid.spec.ts.snap +3 -3
  391. package/app/components/03.organisms/site-header/CONSUMER-STYLING.md +12 -1
  392. package/app/components/04.templates/page-hero-highlights/CONSUMER-STYLING.md +103 -0
  393. package/app/components/04.templates/page-hero-highlights/PageHeroHighlights.vue +144 -193
  394. package/app/components/04.templates/page-hero-highlights/PageHeroHighlightsHeader.vue +27 -37
  395. package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlights.stories.ts +56 -60
  396. package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlightsHeader.stories.ts +2 -2
  397. package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlights.spec.ts +10 -10
  398. package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlightsHeader.spec.ts +7 -7
  399. package/app/components/04.templates/page-hero-highlights/tests/__snapshots__/PageHeroHighlights.spec.ts.snap +6 -6
  400. package/app/components/05.forms/form-errors/CONSUMER-STYLING.md +112 -0
  401. package/app/components/05.forms/form-errors/InputError.vue +101 -122
  402. package/app/components/05.forms/form-errors/stories/InputError.stories.ts +125 -0
  403. package/app/components/05.forms/form-errors/tests/InputError.spec.ts +82 -31
  404. package/app/components/05.forms/form-field/CONSUMER-STYLING.md +91 -0
  405. package/app/components/05.forms/form-field/FormField.vue +26 -35
  406. package/app/components/05.forms/form-field/stories/FormField.stories.ts +104 -0
  407. package/app/components/05.forms/form-field/tests/FormField.spec.ts +75 -0
  408. package/app/components/05.forms/form-fieldset/CONSUMER-STYLING.md +88 -0
  409. package/app/components/05.forms/form-fieldset/FormFieldset.vue +34 -28
  410. package/app/components/05.forms/form-fieldset/stories/FormFieldset.stories.ts +84 -0
  411. package/app/components/05.forms/form-fieldset/tests/FormFieldset.spec.ts +111 -0
  412. package/app/components/05.forms/form-wrapper/CONSUMER-STYLING.md +101 -0
  413. package/app/components/05.forms/form-wrapper/FormWrapper.vue +32 -15
  414. package/app/components/05.forms/form-wrapper/stories/FormWrapper.stories.ts +75 -0
  415. package/app/components/05.forms/form-wrapper/tests/FormWrapper.spec.ts +57 -0
  416. package/app/components/05.forms/input-button/CONSUMER-STYLING.md +52 -7
  417. package/app/components/05.forms/input-button/{InputButtonCore.vue → InputButton.vue} +60 -18
  418. package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts → input-button.playwright.ts} +5 -5
  419. package/app/components/05.forms/input-button/stories/{InputButtonCore.stories.ts → InputButton.stories.ts} +8 -10
  420. package/app/components/05.forms/input-button/tests/{InputButtonCore.spec.ts → InputButton.spec.ts} +75 -19
  421. package/app/components/05.forms/input-button/tests/__snapshots__/{InputButtonCore.spec.ts.snap → InputButton.spec.ts.snap} +18 -18
  422. package/app/components/05.forms/input-checkbox/CONSUMER-STYLING.md +93 -0
  423. package/app/components/05.forms/input-checkbox/MultipleCheckboxes.vue +19 -25
  424. package/app/components/05.forms/input-checkbox/SingleCheckbox.vue +17 -43
  425. package/app/components/05.forms/input-checkbox/stories/MultipleCheckboxes.stories.ts +104 -0
  426. package/app/components/05.forms/input-checkbox/stories/SingleCheckbox.stories.ts +75 -0
  427. package/app/components/05.forms/input-checkbox/tests/MultipleCheckboxes.spec.ts +91 -53
  428. package/app/components/05.forms/input-checkbox/tests/SingleCheckbox.spec.ts +112 -0
  429. package/app/components/05.forms/input-checkbox-radio/CONSUMER-STYLING.md +115 -35
  430. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadio.vue +158 -0
  431. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioButton.vue +102 -101
  432. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioField.vue +100 -0
  433. package/app/components/05.forms/input-checkbox-radio/stories/{InputCheckboxRadioCore.stories.ts → InputCheckboxRadio.stories.ts} +23 -8
  434. package/app/components/05.forms/input-checkbox-radio/stories/InputCheckboxRadioButton.stories.ts +60 -16
  435. package/app/components/05.forms/input-checkbox-radio/stories/InputCheckboxRadioField.stories.ts +93 -0
  436. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadio.spec.ts +174 -0
  437. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioButton.spec.ts +87 -0
  438. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioField.spec.ts +87 -0
  439. package/app/components/05.forms/input-description/CONSUMER-STYLING.md +177 -0
  440. package/app/components/05.forms/input-description/InputDescription.vue +45 -24
  441. package/app/components/05.forms/input-description/stories/InputDescription.stories.ts +160 -0
  442. package/app/components/05.forms/input-description/tests/InputDescription.spec.ts +62 -386
  443. package/app/components/05.forms/input-label/CONSUMER-STYLING.md +134 -0
  444. package/app/components/05.forms/input-label/InputLabel.vue +99 -38
  445. package/app/components/05.forms/input-label/stories/InputLabel.stories.ts +236 -0
  446. package/app/components/05.forms/input-label/tests/InputLabel.spec.ts +113 -342
  447. package/app/components/05.forms/input-number/CONSUMER-STYLING.md +16 -7
  448. package/app/components/05.forms/input-number/{InputNumberCore.vue → InputNumber.vue} +6 -6
  449. package/app/components/05.forms/input-number/{variants/InputNumberDefault.vue → InputNumberField.vue} +12 -15
  450. package/app/components/05.forms/input-number/stories/{InputNumberCore.stories.ts → InputNumber.stories.ts} +6 -6
  451. package/app/components/05.forms/input-number/{variants/stories/InputNumberDefault.stories.ts → stories/InputNumberField.stories.ts} +5 -5
  452. package/app/components/05.forms/input-number/tests/{InputNumberCore.spec.ts → InputNumber.spec.ts} +2 -2
  453. package/app/components/05.forms/input-number/{variants/tests/InputNumberDefault.spec.ts → tests/InputNumberField.spec.ts} +8 -8
  454. package/app/components/05.forms/input-radio/CONSUMER-STYLING.md +70 -0
  455. package/app/components/05.forms/input-radio/MultipleRadiobuttons.vue +19 -30
  456. package/app/components/05.forms/input-radio/stories/MultipleRadiobuttons.stories.ts +116 -0
  457. package/app/components/05.forms/input-radio/tests/MultipleRadioButtons.spec.ts +125 -74
  458. package/app/components/05.forms/input-range/CONSUMER-STYLING.md +13 -0
  459. package/app/components/05.forms/input-range/InputRangeCore.vue +1 -1
  460. package/app/components/05.forms/input-range/{variants/InputRangeDefault.vue → InputRangeDefault.vue} +7 -11
  461. package/app/components/05.forms/input-range/{variants/tests → tests}/InputRangeDefault.spec.ts +1 -1
  462. package/app/components/05.forms/input-select/CONSUMER-STYLING.md +11 -2
  463. package/app/components/05.forms/input-select/{variants/InputSelectWithLabel.vue → InputSelectWithLabel.vue} +6 -9
  464. package/app/components/05.forms/input-select/stories/InputSelectWithLabel.stories.ts +1 -1
  465. package/app/components/05.forms/input-text/CONSUMER-STYLING.md +12 -3
  466. package/app/components/05.forms/input-text/{variants/InputPasswordWithLabel.vue → InputPasswordWithLabel.vue} +3 -3
  467. package/app/components/05.forms/input-text/{variants/InputTextAsNumberWithLabel.vue → InputTextAsNumberWithLabel.vue} +12 -15
  468. package/app/components/05.forms/input-text/InputTextCore.vue +8 -11
  469. package/app/components/05.forms/input-text/{variants/InputTextWithLabel.vue → InputTextWithLabel.vue} +9 -10
  470. package/app/components/05.forms/input-text/stories/InputPasswordWithLabel.stories.ts +1 -1
  471. package/app/components/05.forms/input-text/stories/InputTextAsNumberWithLabel.stories.ts +1 -1
  472. package/app/components/05.forms/input-text/stories/InputTextWithLabel.stories.ts +1 -1
  473. package/app/components/05.forms/input-text/tests/InputPasswordWithLabel.spec.ts +2 -1
  474. package/app/components/05.forms/input-text/tests/InputTextAsNumberWithLabel.spec.ts +1 -1
  475. package/app/components/05.forms/input-text/tests/InputTextWithLabel.spec.ts +2 -1
  476. package/app/components/05.forms/input-textarea/CONSUMER-STYLING.md +11 -2
  477. package/app/components/05.forms/input-textarea/{variants/InputTextareaWithLabel.vue → InputTextareaWithLabel.vue} +3 -7
  478. package/app/components/05.forms/input-textarea/stories/InputTextareaWithLabel.stories.ts +1 -1
  479. package/app/components/05.forms/patterns/stories/ContactForm.stories.ts +9 -10
  480. package/app/components/05.forms/patterns/stories/LoginForm.stories.ts +10 -10
  481. package/app/components/05.forms/patterns/stories/MigratedFieldsForm.stories.ts +246 -101
  482. package/app/components/05.forms/pending-effect/CONSUMER-STYLING.md +92 -0
  483. package/app/components/05.forms/pending-effect/PendingEffect.vue +52 -45
  484. package/app/components/05.forms/pending-effect/stories/PendingEffect.stories.ts +132 -0
  485. package/app/components/05.forms/pending-effect/tests/PendingEffect.spec.ts +67 -0
  486. package/app/components/05.forms/toggle-switch/CONSUMER-STYLING.md +11 -2
  487. package/app/components/05.forms/toggle-switch/ToggleSwitchCore.vue +10 -29
  488. package/app/components/05.forms/toggle-switch/{variants/ToggleSwitchWithLabel.vue → ToggleSwitchWithLabel.vue} +5 -7
  489. package/app/components/05.forms/toggle-switch/{variants/ToggleSwitchWithLabelInline.vue → ToggleSwitchWithLabelInline.vue} +2 -4
  490. package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabel.stories.ts +1 -1
  491. package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabelInline.stories.ts +4 -1
  492. package/app/components/05.forms/toggle-switch/{variants/tests → tests}/ToggleSwitchWithLabel.spec.ts +26 -0
  493. package/app/components/05.forms/triple-toggle-switch/CONSUMER-STYLING.md +75 -62
  494. package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitch.vue +243 -0
  495. package/app/components/05.forms/triple-toggle-switch/stories/TripleToggleSwitch.stories.ts +104 -0
  496. package/app/components/05.forms/triple-toggle-switch/tests/TripleToggleSwitch.spec.ts +138 -0
  497. package/app/composables/tests/useCancellableTimer.spec.ts +48 -0
  498. package/app/composables/tests/useMaxChildWidth.spec.ts +67 -0
  499. package/app/composables/useCancellableTimer.ts +27 -7
  500. package/app/composables/useMaxChildWidth.ts +4 -6
  501. package/app/types/app-config.d.ts +10 -0
  502. package/app/types/components/cookie-consent-banner.d.ts +3 -0
  503. package/app/types/components/index.ts +6 -1
  504. package/app/types/components/opening-hours.d.ts +48 -0
  505. package/app/types/components/price-list.d.ts +11 -0
  506. package/app/types/components/profile-section.d.ts +6 -0
  507. package/app/types/components/samaritan-prompt.d.ts +13 -0
  508. package/app/types/components/services-card.d.ts +9 -0
  509. package/app/types/components/slider-gallery.d.ts +2 -0
  510. package/app/types/components/social-icons-list.d.ts +2 -0
  511. package/app/types/forms/types.forms.d.ts +3 -0
  512. package/app/types/forms/types.zodFormControl.d.ts +0 -3
  513. package/app/utils/opening-hours.ts +44 -0
  514. package/nuxt.config.ts +5 -1
  515. package/package.json +2 -2
  516. package/ramps.config.mjs +1 -1
  517. package/.claude/commands/create-commit-message.md +0 -13
  518. package/.claude/commands/create-release-notes.md +0 -34
  519. package/.claude/commands/migrate-component.md +0 -169
  520. package/.claude/commands/run-commit.md +0 -13
  521. package/.claude/component-ledger/artifact-url.txt +0 -1
  522. package/.claude/component-ledger/audit.json +0 -1
  523. package/.claude/component-ledger/build.mjs +0 -164
  524. package/.claude/component-ledger/output.html +0 -569
  525. package/.claude/component-ledger/template.html +0 -569
  526. package/.claude/hooks/check-component-update.sh +0 -95
  527. package/.claude/hooks/refresh-component-ledger.sh +0 -32
  528. package/.claude/settings.json +0 -134
  529. package/.claude/settings.local.json +0 -38
  530. package/.claude/skills/components/alert-content-inner.md +0 -60
  531. package/.claude/skills/components/navigation-horizontal.md +0 -99
  532. package/.claude/skills/components/samaritan-prompt-mixed.md +0 -139
  533. package/app/components/01.atoms/content-wrappers/content-columns-2/ContentColumns2.vue +0 -51
  534. package/app/components/01.atoms/content-wrappers/content-columns-2/stories/ContentColumns2.stories.ts +0 -110
  535. package/app/components/01.atoms/content-wrappers/content-columns-2/tests/ContentColumns2.spec.ts +0 -105
  536. package/app/components/01.atoms/content-wrappers/content-columns-2/tests/__snapshots__/ContentColumns2.spec.ts.snap +0 -14
  537. package/app/components/01.atoms/content-wrappers/content-width/ContentWidth.vue +0 -88
  538. package/app/components/01.atoms/content-wrappers/content-width/stories/ContentWidth.stories.ts +0 -362
  539. package/app/components/01.atoms/content-wrappers/content-width/tests/ContentWidth.spec.ts +0 -132
  540. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/__snapshots__/LayoutGrid.spec.ts.snap +0 -36
  541. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/LayoutGridByWidth.vue +0 -70
  542. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/stories/LayoutGridByWidth.stories.ts +0 -220
  543. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/LayoutGridByWidth.spec.ts +0 -174
  544. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGrid.spec.ts.snap +0 -36
  545. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGridByCols.spec.ts.snap +0 -36
  546. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGridByWidth.spec.ts.snap +0 -36
  547. package/app/components/01.atoms/cookie-consent-banner/CookieConsentBanner.vue +0 -148
  548. package/app/components/01.atoms/display-avatar/DisplayAvatar.vue +0 -130
  549. package/app/components/01.atoms/display-avatar/tests/__snapshots__/DisplayAvatar.spec.ts.snap +0 -11
  550. package/app/components/02.molecules/action-menu/tests/__snapshots__/ActionMenuItemCore.spec.ts.snap +0 -27
  551. package/app/components/02.molecules/navigation/navigation-horizontal/NavigationHorizontal.vue +0 -162
  552. package/app/components/02.molecules/navigation/navigation-horizontal/stories/NavigationHorizontal.stories.ts +0 -373
  553. package/app/components/02.molecules/navigation/navigation-horizontal/tests/NavigationHorizontal.spec.ts +0 -152
  554. package/app/components/02.molecules/navigation/navigation-horizontal/tests/__snapshots__/NavigationHorizontal.spec.ts.snap +0 -17
  555. package/app/components/02.molecules/qr-code/stories/QrCode.stories.ts +0 -101
  556. package/app/components/03.organisms/colour-finder/ColourFinder.vue +0 -1519
  557. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioCore.vue +0 -202
  558. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioWithLabel.vue +0 -105
  559. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioCore.spec.ts +0 -320
  560. package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitchCore.vue +0 -314
  561. package/app/components/05.forms/triple-toggle-switch/stories/TripleToggleSwitchCore.stories.ts +0 -63
  562. package/.vscode/{srcdev-component-dialog.code-snippets → srcdev-component-display-dialog.code-snippets} +0 -0
  563. package/app/components/{01.atoms → 02.molecules}/toast/tests/DisplayToast.spec.ts +1 -1
  564. /package/app/components/{01.atoms → 02.molecules}/toast/tests/DisplayToastProvider.spec.ts +0 -0
  565. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-secondary-chromium-darwin.png +0 -0
  566. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-secondary-firefox-darwin.png +0 -0
  567. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-secondary-webkit-darwin.png +0 -0
  568. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-tertiary-chromium-darwin.png +0 -0
  569. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-tertiary-firefox-darwin.png +0 -0
  570. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-tertiary-webkit-darwin.png +0 -0
  571. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-primary-pending-chromium-darwin.png +0 -0
  572. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-primary-pending-firefox-darwin.png +0 -0
  573. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-primary-pending-webkit-darwin.png +0 -0
  574. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-secondary-pill-chromium-darwin.png +0 -0
  575. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-secondary-pill-firefox-darwin.png +0 -0
  576. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-secondary-pill-webkit-darwin.png +0 -0
  577. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-tertiary-readonly-chromium-darwin.png +0 -0
  578. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-tertiary-readonly-firefox-darwin.png +0 -0
  579. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-tertiary-readonly-webkit-darwin.png +0 -0
  580. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-chromium-darwin.png +0 -0
  581. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-firefox-darwin.png +0 -0
  582. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-default-chromium-darwin.png +0 -0
  583. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-default-firefox-darwin.png +0 -0
  584. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-default-webkit-darwin.png +0 -0
  585. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-error-chromium-darwin.png +0 -0
  586. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-error-firefox-darwin.png +0 -0
  587. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-error-webkit-darwin.png +0 -0
  588. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-success-chromium-darwin.png +0 -0
  589. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-success-firefox-darwin.png +0 -0
  590. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-success-webkit-darwin.png +0 -0
  591. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-warning-chromium-darwin.png +0 -0
  592. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-warning-firefox-darwin.png +0 -0
  593. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-warning-webkit-darwin.png +0 -0
  594. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-primary-chromium-darwin.png +0 -0
  595. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-primary-firefox-darwin.png +0 -0
  596. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-primary-webkit-darwin.png +0 -0
  597. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-secondary-chromium-darwin.png +0 -0
  598. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-secondary-firefox-darwin.png +0 -0
  599. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-secondary-webkit-darwin.png +0 -0
  600. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-tertiary-chromium-darwin.png +0 -0
  601. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-tertiary-firefox-darwin.png +0 -0
  602. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-tertiary-webkit-darwin.png +0 -0
  603. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-webkit-darwin.png +0 -0
  604. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/nuxt-icon-only-component-chromium-darwin.png +0 -0
  605. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/nuxt-icon-only-component-firefox-darwin.png +0 -0
  606. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/nuxt-icon-only-component-webkit-darwin.png +0 -0
  607. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pending-chromium-darwin.png +0 -0
  608. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pending-firefox-darwin.png +0 -0
  609. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pending-webkit-darwin.png +0 -0
  610. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pill-chromium-darwin.png +0 -0
  611. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pill-firefox-darwin.png +0 -0
  612. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pill-webkit-darwin.png +0 -0
  613. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-readonly-chromium-darwin.png +0 -0
  614. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-readonly-firefox-darwin.png +0 -0
  615. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-readonly-webkit-darwin.png +0 -0
  616. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/with-both-nuxt-icon-components-chromium-darwin.png +0 -0
  617. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/with-both-nuxt-icon-components-firefox-darwin.png +0 -0
  618. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/with-both-nuxt-icon-components-webkit-darwin.png +0 -0
  619. /package/app/components/05.forms/input-range/{variants/stories → stories}/InputRangeDefault.stories.ts +0 -0
  620. /package/app/components/05.forms/input-select/{variants/tests → tests}/InputSelectWithLabel.spec.ts +0 -0
  621. /package/app/components/05.forms/input-textarea/{variants/tests → tests}/InputTextareaWithLabel.spec.ts +0 -0
  622. /package/app/components/05.forms/toggle-switch/{variants/tests → tests}/ToggleSwitchWithLabelInline.spec.ts +0 -0
  623. /package/app/types/components/{navigation-horizontal.d.ts → nav-item.d.ts} +0 -0
@@ -0,0 +1,116 @@
1
+ # OpeningHours Component
2
+
3
+ ## Overview
4
+
5
+ `OpeningHours` (`app/components/02.molecules/opening-hours/`) renders a business's weekly opening
6
+ hours as a `<dl>`, plus an optional "special opening times" list for bank holidays, closures etc.
7
+ Data is authored **per day**; the component groups consecutive identical days into ranges
8
+ ("Monday – Saturday") itself, so a single day change never leaves a hand-written range stale.
9
+
10
+ Covers: single sessions, split sessions (restaurant lunch/dinner), closed days, 24 hours,
11
+ by appointment, overnight sessions (closes after midnight), per-day notes, date/date-range
12
+ exceptions, today highlight, schema.org JSON-LD. Not included (yet): a live "open now" status.
13
+
14
+ ---
15
+
16
+ ## Props reference
17
+
18
+ > **Hyphenation rule**: write camelCase props hyphenated in templates (`:hour12`, `group-days`).
19
+
20
+ | Prop (template form) | Type | Default | Notes |
21
+ |---|---|---|---|
22
+ | `:days` | `OpeningDay[]` | (required) | One entry per day; missing days render as closed |
23
+ | `:exceptions` | `OpeningException[]` | `[]` | Special dates, listed under their own heading |
24
+ | `locale` | `string` | `"en-GB"` | Drives day names, dates and time format via `Intl` |
25
+ | `:hour12` | `boolean` | `false` | 12-hour am/pm times |
26
+ | `day-format` | `"long" \| "short"` | `"long"` | "Monday" vs "Mon" |
27
+ | `:group-days` | `boolean` | `true` | Collapse consecutive identical days; `false` lists all seven |
28
+ | `week-starts-on` | `"monday" \| "sunday"` | `"monday"` | Row order |
29
+ | `:highlight-today` | `boolean` | `true` | Marks today's row with `data-today` + `aria-current="date"` |
30
+ | `:hide-past-exceptions` | `boolean` | `true` | Drops exceptions whose end date has passed |
31
+ | `time-zone` | `string` | visitor's | IANA zone used to work out "today"; set to the business's zone |
32
+ | `heading-tag` | `"h2"`–`"h6"` | `"h3"` | Level of the exceptions heading |
33
+ | `exceptions-heading` | `string` | `"Special opening times"` | `""` omits the heading |
34
+ | `closed-label` | `string` | `"Closed"` | |
35
+ | `open24-hours-label` | `string` | `"Open 24 hours"` | |
36
+ | `by-appointment-label` | `string` | `"By appointment only"` | |
37
+ | `to-label` | `string` | `"to"` | Screen-reader word read in place of the visual dash |
38
+ | `:structured-data` | `OpeningHoursStructuredData` | `undefined` | When set, emits LocalBusiness JSON-LD via `useHead` (read once at setup) |
39
+ | `:style-class-passthrough` | `string \| string[]` | `[]` | Classes on the root; reactive |
40
+
41
+ All visible text is a prop or comes from `Intl`, so passing `locale` plus translated labels fully
42
+ localises it.
43
+
44
+ ### Data shape
45
+
46
+ Importable: `import type { OpeningDay, OpeningException, OpeningSession, OpeningStatus, OpeningHoursStructuredData } from "srcdev-nuxt-components"`
47
+ (source: `app/types/components/opening-hours.d.ts`).
48
+
49
+ ```ts
50
+ type OpeningWeekday = 0 | 1 | 2 | 3 | 4 | 5 | 6; // 0 = Monday, 6 = Sunday
51
+ type OpeningStatus = "open" | "closed" | "24-hours" | "by-appointment";
52
+
53
+ interface OpeningSession { opens: string; closes: string; label?: string } // 24h "HH:MM"
54
+ interface OpeningDay {
55
+ day: OpeningWeekday;
56
+ status?: OpeningStatus; // default: "open" if sessions given, else "closed"
57
+ sessions?: OpeningSession[];
58
+ note?: string;
59
+ }
60
+ interface OpeningException {
61
+ from: string; // "YYYY-MM-DD"
62
+ to?: string; // inclusive, omit for one day
63
+ label?: string; // "Christmas"
64
+ status?: OpeningStatus; // same default rule; no sessions = closed
65
+ sessions?: OpeningSession[];
66
+ note?: string;
67
+ }
68
+ interface OpeningHoursStructuredData { type?: string; name?: string; id?: string }
69
+ ```
70
+
71
+ Times are always authored as 24-hour strings; `hour12` only changes the display. A `closes`
72
+ earlier than `opens` means the session runs past midnight and is displayed as given.
73
+
74
+ ---
75
+
76
+ ## Behaviour notes
77
+
78
+ - Grouping compares status, sessions and note; only **consecutive** days (in `week-starts-on`
79
+ order) group. No wrap-around from Sunday to Monday.
80
+ - Exceptions don't alter the weekly table; they are listed separately.
81
+ - Today's highlight and past-exception hiding run in `onMounted`, never on the server, so cached
82
+ HTML can't carry a stale day. Past exceptions are briefly visible before hydration.
83
+ - **Structured data**: emits `{ "@type": structuredData.type ?? "LocalBusiness", "@id", name,
84
+ openingHoursSpecification }`. If the site already has a main business JSON-LD block, either pass
85
+ the same `id` so search engines merge the two, or skip the prop and call the auto-imported
86
+ `buildOpeningHoursSpecification(days, exceptions)` util (`app/utils/opening-hours.ts`) to add
87
+ the hours to the existing block. Closed and by-appointment weekly days are omitted; closed
88
+ exceptions use `opens = closes = "00:00"` per schema.org; 24 hours uses `00:00`–`23:59`.
89
+
90
+ ---
91
+
92
+ ## Usage
93
+
94
+ ```vue
95
+ <OpeningHours :days="openingDays" :exceptions="specialDates" time-zone="Europe/London" />
96
+ ```
97
+
98
+ Restaurant with split sessions, 12-hour display and JSON-LD:
99
+
100
+ ```vue
101
+ <OpeningHours
102
+ :days="restaurantDays"
103
+ :hour12="true"
104
+ time-zone="Europe/London"
105
+ :structured-data="{ type: 'Restaurant', name: 'The Anchor', id: 'https://example.com/#business' }"
106
+ />
107
+ ```
108
+
109
+ ```ts
110
+ const restaurantDays: OpeningDay[] = [
111
+ { day: 1, sessions: [{ opens: "12:00", closes: "14:30", label: "Lunch" }, { opens: "18:00", closes: "22:00", label: "Dinner" }] },
112
+ { day: 5, sessions: [{ opens: "18:00", closes: "01:00" }], note: "Last orders 23:30" },
113
+ ];
114
+ ```
115
+
116
+ Styling: `--opening-hours-*` tokens, see `CONSUMER-STYLING.md` next to the component.
@@ -1,5 +1,7 @@
1
1
  # PageHeroHighlights Component
2
2
 
3
+ > **Changed 2026-09-28:** styles are now in `@layer components` (they were unlayered). Every token is `--page-hero-highlights-*` with its default as a `var()` fallback, so it can be set on the component or any ancestor (previously declared on the root with generic names like `--max-width`, `--highlight-border`, so ancestor values never landed). Inner classes are prefixed (`.page-hero-highlights-header-row`, `-header-slot`, `-strip`, `-content-row`, `-content-slot`); the content-align root classes are `.content-align-start`/`.content-align-center` (were bare `.start`/`.center`); the highlight contract classes are `.page-hero-highlights-item`, `-item-title`, `-item-body` (were `.highlight`, `.title`, `.body`); PageHeroHighlightsHeader uses `.page-hero-highlights-header-start`/`-end` and `--page-hero-highlights-header-*` tokens (were `.phh-*` / `--phh-*`). Full token reference: `CONSUMER-STYLING.md` in the component folder.
4
+
3
5
  ## Overview
4
6
 
5
7
  `PageHeroHighlights` is a page-level layout template that creates a "hero + highlights strip" grid. It has:
@@ -20,7 +22,7 @@ The layout uses a 4-row CSS Grid with `subgrid` — no `translate`, negative mar
20
22
  | `widthConstrained` | `boolean` | `false` | When `true`, caps the central column at `--width-constrained` (default `1064px`). Gutters grow responsively to enforce the constraint. |
21
23
  | `contentAlign` | `"start" \| "center"` | `"center"` | When `widthConstrained` is `true`: `"center"` grows gutters equally; `"start"` pins content to the left with a fixed left gutter. |
22
24
  | `contentPanel` | `boolean` | `true` | When `true`, renders a decorative panel behind the content slot and offsets the highlights strip. Set to `false` for a flat layout with no backdrop. |
23
- | `highlightTitleBaseline`| `boolean` | `false` | When `true`, fixes the highlight title row to a set height so titles align at a common baseline. Override `--highlight-title-height` to tune. |
25
+ | `highlightTitleBaseline`| `boolean` | `false` | When `true`, fixes the highlight title row to a set height so titles align at a common baseline. Override `--page-hero-highlights-title-height` to tune. |
24
26
  | `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes on the root element |
25
27
 
26
28
  ## Slots
@@ -102,17 +104,17 @@ Located at: `app/components/04.templates/page-hero-highlights/PageHeroHighlights
102
104
  | Slot | Purpose |
103
105
  | ------- | --------------------------------------------------------- |
104
106
  | `start` | Title and description — always rendered, fills full width when `#end` is absent |
105
- | `end` | Action buttons — `.phh-end` is only mounted when this slot is provided |
107
+ | `end` | Action buttons — `.page-hero-highlights-header-end` is only mounted when this slot is provided |
106
108
 
107
109
  ### CSS tokens
108
110
 
109
111
  | Token | Default | Description |
110
112
  | -------------------------- | ---------------- | ---------------------------------------------------- |
111
- | `--phh-padding-block-mobile` | `1.6rem 3.2rem` | Block padding (start end) at mobile widths |
112
- | `--phh-padding-block-tablet` | `2.4rem 4.8rem` | Block padding (start end) at ≥768px |
113
- | `--phh-padding-block-desktop` | `3.2rem 6.4rem` | Block padding (start end) at ≥1024px |
114
- | `--phh-gap` | `1.6rem` | Gap between `#start` and `#end` areas |
115
- | `--phh-end-gap` | `0.8rem` | Gap between items within `#end` |
113
+ | `--page-hero-highlights-header-padding-block-mobile` | `1.6rem 3.2rem` | Block padding (start end) at mobile widths |
114
+ | `--page-hero-highlights-header-padding-block-tablet` | `2.4rem 4.8rem` | Block padding (start end) at ≥768px |
115
+ | `--page-hero-highlights-header-padding-block-desktop` | `3.2rem 6.4rem` | Block padding (start end) at ≥1024px |
116
+ | `--page-hero-highlights-header-gap` | `1.6rem` | Gap between `#start` and `#end` areas |
117
+ | `--page-hero-highlights-header-end-gap` | `0.8rem` | Gap between items within `#end` |
116
118
 
117
119
  ### Usage
118
120
 
@@ -219,40 +221,38 @@ See [component-local-style-override.md](../component-local-style-override.md) fo
219
221
  /* --page-hero-highlights-gutter-desktop: 32px; */
220
222
 
221
223
  /* Header zone */
222
- /* --header-row-background-colour: darkblue; */
224
+ /* --page-hero-highlights-header-background: darkblue; */
223
225
 
224
226
  /* Highlights strip */
225
- /* --highlights-row-item-gap: 1rem; */
226
- /* --highlights-row-initial-item-offset: 1.2rem; */
227
+ /* --page-hero-highlights-strip-gap: 1rem; */
228
+ /* --page-hero-highlights-strip-inset: 1.2rem; */
227
229
 
228
230
  /* Highlight cards */
229
- /* --highlight-rows-gap: 1.2rem; */
230
- /* --highlight-title-height: 1fr; */ /* see: highlight-title-baseline prop */
231
- /* --highlight-padding-block-start: 1.2rem; */
232
- /* --highlight-padding: 1.2rem; */
233
- /* --highlight-background-color: white; */
234
- /* --highlight-border: 1px solid black; */
235
- /* --highlight-border-radius: 8px; */
236
- /* --highlight-color: black; */
231
+ /* --page-hero-highlights-item-rows-gap: 1.2rem; */
232
+ /* --page-hero-highlights-title-height: 1fr; */ /* see: highlight-title-baseline prop */
233
+ /* --page-hero-highlights-item-padding-block-start: 1.2rem; */
234
+ /* --page-hero-highlights-item-padding: 1.2rem; */
235
+ /* --page-hero-highlights-item-background: white; */
236
+ /* --page-hero-highlights-item-border: 1px solid black; */
237
+ /* --page-hero-highlights-item-border-radius: 8px; */
238
+ /* --page-hero-highlights-item-colour: black; */
237
239
 
238
240
  /* Content zone */
239
- /* --content-row-background-color: var(--slate-01); */ /* transparent */
240
- /* --content-row-start-gap: 1.2rem; */
241
- /* --content-row-end-gap: 1.2rem; */
241
+ /* --page-hero-highlights-content-background: var(--slate-01); */ /* transparent */
242
+ /* --page-hero-highlights-content-start-gap: 1.2rem; */
243
+ /* --page-hero-highlights-content-end-gap: 1.2rem; */
242
244
 
243
245
  /* Content slot decorative border */
244
- /* --content-slot-margin-block-start: 2.4rem; */
245
- /* --content-slot-margin: var(--highlights-row-initial-item-offset); */
246
- /* --content-slot-background-color: var(--slate-00); */
247
- /* --content-slot-border: 1px solid var(--slate-06); */
248
- /* --content-slot-border-radius: 0.8rem; */
249
- /* --content-slot-outline: 1px solid var(--slate-02); */
246
+ /* --page-hero-highlights-content-margin-block-start: 2.4rem; */
247
+ /* --page-hero-highlights-content-margin: var(--page-hero-highlights-strip-inset); */
248
+ /* --page-hero-highlights-panel-background: var(--slate-00); */
249
+ /* --page-hero-highlights-panel-border: 1px solid var(--slate-06); */
250
+ /* --page-hero-highlights-panel-border-radius: 0.8rem; */
251
+ /* --page-hero-highlights-panel-outline: 1px solid var(--slate-02); */
250
252
 
251
253
  /* When using :highlight-title-baseline="true" */
252
- /* &.highlight-title-baseline { */
253
- /* --highlight-title-height: 4rem; */ /* proportional value preferred */
254
- /* --highlight-padding-block-start: 0; */
255
- /* } */
254
+ /* --page-hero-highlights-title-height-baseline: 4rem; */ /* proportional value preferred */
255
+ /* --page-hero-highlights-item-padding-block-start-baseline: 0; */
256
256
  }
257
257
  }
258
258
  </style>
@@ -268,14 +268,14 @@ row3: highlights bottom half
268
268
  row4: page content (never underflows highlights)
269
269
  ```
270
270
 
271
- `.header-row` spans cols 1–3, rows 1–2 (edge-to-edge bg). `.header-slot` is placed in row 1 only.
272
- `.content-row` spans cols 1–3, rows 3–4 (bg fills behind highlights; `.content-slot` is placed in row 4 only). The decorative border behind `.content-slot` is rendered via `.content-row:before` — there is no separate DOM element for it.
271
+ `.page-hero-highlights-header-row` spans cols 1–3, rows 1–2 (edge-to-edge bg). `.page-hero-highlights-header-slot` is placed in row 1 only.
272
+ `.page-hero-highlights-content-row` spans cols 1–3, rows 3–4 (bg fills behind highlights; `.page-hero-highlights-content-slot` is placed in row 4 only). The decorative border behind `.page-hero-highlights-content-slot` is rendered via `.page-hero-highlights-content-row::before` — there is no separate DOM element for it.
273
273
 
274
274
  Grid columns are determined entirely by CSS — no `v-bind`. The `widthConstrained` and `contentAlign` props add CSS classes (`width-constrained`, `start`, `center`) which select the appropriate `grid-template-columns` rule.
275
275
 
276
- ## Layout pitfall: do not use `grid-template-rows: subgrid` inside `.highlights-row`
276
+ ## Layout pitfall: do not use `grid-template-rows: subgrid` inside `.page-hero-highlights-strip`
277
277
 
278
- The `.highlights-row` element spans rows 2–3 of the parent grid (the "straddle"). If you add an inner grid to `.highlights-row` (e.g. to extend `equal-widths` behaviour) and include `grid-template-rows: subgrid`, auto-placed items will only occupy row 1 of the subgrid (= parent row 2). Parent row 3 collapses to 0-height, destroying the straddle effect — `.content-row` appears immediately below the highlights instead of overlapping it.
278
+ The `.page-hero-highlights-strip` element spans rows 2–3 of the parent grid (the "straddle"). If you add an inner grid to `.page-hero-highlights-strip` (e.g. to extend `equal-widths` behaviour) and include `grid-template-rows: subgrid`, auto-placed items will only occupy row 1 of the subgrid (= parent row 2). Parent row 3 collapses to 0-height, destroying the straddle effect — `.page-hero-highlights-content-row` appears immediately below the highlights instead of overlapping it.
279
279
 
280
280
  ```css
281
281
  /* ❌ — breaks the straddle when items are auto-placed by column flow */
@@ -20,7 +20,7 @@ no extra wrapper divs needed.
20
20
  | `variant` | `"full" \| "popout" \| "content" \| "inset-content"` | `"content"` | Grid column track this element occupies when nested in another PageRow |
21
21
  | `align` | `"start" \| "end"` | — | Bleeds one side to the viewport edge while respecting the variant boundary on the other |
22
22
  | `id` | `string` | — | `id` attribute on the root element |
23
- | `:style-class-passthrough` | `string \| string[]` | `[]` | Extra classes on the root element |
23
+ | `:style-class-passthrough` | `string \| string[]` | `[]` | Extra classes on the root element (reactive after mount) |
24
24
 
25
25
  ---
26
26
 
@@ -0,0 +1,63 @@
1
+ # PendingEffect Component
2
+
3
+ ## Overview
4
+
5
+ `PendingEffect` is a decorative SVG that draws an animated dashed line around a busy button. It
6
+ is an internal part of `InputButton`: set `has-pending-effect` on the button and toggle
7
+ `is-pending`. Don't render it on its own. Its CSS depends on the host having `.pending-effect`
8
+ (and `position: relative`, which that rule provides), plus `.is-pending` to show and animate it.
9
+
10
+ ```vue
11
+ <InputButton button-text="Submit" type="submit" has-pending-effect :is-pending="submitting" />
12
+ ```
13
+
14
+ ---
15
+
16
+ ## Props reference
17
+
18
+ | Prop (template form) | Type | Default | Notes |
19
+ |------|------|---------|-------|
20
+ | `theme` | `"default" \| "success" \| "error" \| "warning"` | `"default"` | Set as `data-theme` on the SVG, so the `--theme-surface` colour defaults follow the theme. `InputButton` passes its own `theme`. |
21
+ | `:style-class-passthrough` | `string \| string[]` | `[]` | Extra classes on the SVG. Not forwarded by `InputButton`. |
22
+
23
+ No slots, no events.
24
+
25
+ ---
26
+
27
+ ## Behaviour
28
+
29
+ - Hidden (`opacity: 0`) until the host has `.is-pending`.
30
+ - The host must not clip overflow: the line is drawn outside the host's edge. `InputButton`
31
+ sets `overflow: hidden` on buttons generally, and switches it to `visible` when
32
+ `.pending-effect` is present. Before 2026-09-26 it didn't, so the effect never rendered at all.
33
+ - Under `prefers-reduced-motion: reduce` it never shows, since the animation is the whole effect.
34
+ - `aria-hidden="true"` and `focusable="false"`: it is decorative. Busy state for assistive tech
35
+ is the host button's responsibility.
36
+ - The dash animation runs on the SVG's own rects. It used to run on the host button, and because
37
+ `stroke-dashoffset` is inherited, it also animated the stroke of any SVG icon inside the button.
38
+
39
+ ---
40
+
41
+ ## Styling
42
+
43
+ Full table in `app/components/05.forms/pending-effect/CONSUMER-STYLING.md`. Public tokens:
44
+ `--pending-effect-line-color|line-thickness|line-length`, `--pending-effect-blur-color|blur-size`,
45
+ `--pending-effect-offset`, `--pending-effect-border-radius|border-radius-icon-only`,
46
+ `--pending-effect-animation-duration`. All read with fallbacks at the point of use, so they can
47
+ be set on any ancestor.
48
+
49
+ ---
50
+
51
+ ## History
52
+
53
+ **Migrated 2026-09-26** (0/5 → full compliance):
54
+
55
+ - Tokens renamed to `--pending-effect-*` (were `--pending-line-*`, `--pending-blur-*`,
56
+ `--pending-offset`, and the generic `--animation-speed`). They used to be declared on the host
57
+ button, which blocked any override set on a parent. No consumer overrode the old names.
58
+ - Inner classes prefixed (`.pending-effect-container|blur|line`), keyframes renamed from the
59
+ generic `stroke-dashoffset` to `pending-effect-dash`.
60
+ - Animation moved from the host button to the rects (see Behaviour).
61
+ - Corner radius became a public token; removed a dead base `stroke: black; stroke-width: 0.5rem`
62
+ that both rects always overrode.
63
+ - SVG is now `aria-hidden`; `styleClassPassthrough` changes after mount are picked up.
@@ -0,0 +1,72 @@
1
+ # PriceList Component
2
+
3
+ ## Overview
4
+
5
+ `PriceList` (`app/components/02.molecules/price-list/`) renders a service/menu-style price list:
6
+ one or more columns, each with a heading (optional icon) and a `<dl>` of description/price rows.
7
+ Columns stack below `48em` and sit two-up above it. Not a SaaS plan comparison, use `PricingCard`
8
+ for that.
9
+
10
+ ---
11
+
12
+ ## Props reference
13
+
14
+ > **Hyphenation rule**: write camelCase props hyphenated in templates (`:price-list-data`).
15
+
16
+ | Prop (template form) | Type | Default | Notes |
17
+ |---|---|---|---|
18
+ | `:price-list-data` | `PriceListData[]` | (required) | One entry per column |
19
+ | `heading-tag` | `"h2" \| "h3" \| "h4" \| "h5" \| "h6"` | `"h2"` | Heading level for column titles; match the page outline |
20
+ | `from-label` | `string` | `"from"` | Text before a price whose item has `from: true`. Pass a translated string for i18n |
21
+ | `:style-class-passthrough` | `string \| string[]` | `[]` | Classes on the root; reactive |
22
+
23
+ ### Data shape
24
+
25
+ Importable: `import type { PriceListData, PriceItem } from "srcdev-nuxt-components"`
26
+ (source: `app/types/components/price-list.d.ts`).
27
+
28
+ ```ts
29
+ interface PriceItem {
30
+ description: string;
31
+ price: string; // pre-formatted, e.g. "£45"
32
+ from?: boolean; // prefix with fromLabel
33
+ }
34
+
35
+ interface PriceListData {
36
+ headingtext: string; // note: lower-case "t"
37
+ headingIcon?: string; // Iconify name, e.g. "lucide:sparkles"
38
+ items: PriceItem[];
39
+ }
40
+ ```
41
+
42
+ No slots, no events.
43
+
44
+ ---
45
+
46
+ ## Semantics
47
+
48
+ - Column titles are `HeroText` headings at `heading-tag`. Prices are plain `<span>`s inside `<dd>`,
49
+ not headings (before 2026-09-27 each price was an `<h2>`, which flooded the heading outline).
50
+ - Rows are `<div>`-wrapped `<dt>`/`<dd>` pairs, valid inside `<dl>`.
51
+
52
+ ---
53
+
54
+ ## Styling
55
+
56
+ All tokens are `--price-list-*`; full table in `CONSUMER-STYLING.md` next to the component.
57
+ Common ones: `--price-list-divider-colour`, `--price-list-divider-opacity`,
58
+ `--price-list-price-font-size`, `--price-list-heading-margin-block-end`.
59
+
60
+ ---
61
+
62
+ ## Usage
63
+
64
+ ```vue
65
+ <PriceList :price-list-data="priceListData" :style-class-passthrough="['mbe-20']" />
66
+ ```
67
+
68
+ Nested under an existing `h2` section heading:
69
+
70
+ ```vue
71
+ <PriceList :price-list-data="priceListData" heading-tag="h3" from-label="ab" />
72
+ ```
@@ -49,7 +49,7 @@ Override the default feature list rendering. Receives no slot scope.
49
49
 
50
50
  ### #cta slot
51
51
 
52
- Customize the CTA button. Default renders `InputButtonCore` with theme support.
52
+ Customize the CTA button. Default renders `InputButton` with theme support.
53
53
 
54
54
  **Slot scope:**
55
55
  - `ctaText: string` — button label from `:cta-text` prop
@@ -60,7 +60,7 @@ Customize the CTA button. Default renders `InputButtonCore` with theme support.
60
60
  ```vue
61
61
  <PricingCard plan-name="Pro" :price="99" @select="handleSelect">
62
62
  <template #cta="{ ctaText, isDisabled, onSelect }">
63
- <InputButtonCore
63
+ <InputButton
64
64
  :button-text="ctaText"
65
65
  variant="secondary"
66
66
  theme="custom"
@@ -127,7 +127,7 @@ All `--pricing-card-*` tokens can be overridden at global, page, or instance sco
127
127
  @select="handleSelect"
128
128
  >
129
129
  <template #cta="{ ctaText, isDisabled, onSelect }">
130
- <InputButtonCore
130
+ <InputButton
131
131
  :button-text="ctaText"
132
132
  variant="primary"
133
133
  :readonly="isDisabled"
@@ -6,6 +6,8 @@ type: reference
6
6
 
7
7
  # ProfileSection
8
8
 
9
+ > **Classes renamed 2026-09-27:** `.picture` → `.profile-section-picture`, `.profile-picture` → `.profile-section-image`, `.profile-info` → `.profile-section-info`, `.profile-info-content` → `.profile-section-info-content`, `.profile-info-block` → `.profile-section-info-block`, `.profile-links` → `.profile-section-links`.
10
+
9
11
  ## Overview
10
12
 
11
13
  `ProfileSection` is a molecule that renders a practitioner/author profile: a header area (eyebrow + heading), a profile picture, and a flexible set of bio/info blocks alongside optional profile links. It is landmark-aware — when `tag` is `section`, `article`, or `aside`, the root element automatically gets `aria-labelledby` wired to the heading inside the `#heroText` slot (**you must bind `headingId` yourself, and a console warning fires if you forget** — see [component-aria-landmark.md](../component-aria-landmark.md)). `tag="main"` is never auto-labelled.
@@ -14,7 +16,7 @@ type: reference
14
16
 
15
17
  | Prop | Type | Default | Description |
16
18
  |------|------|---------|-------------|
17
- | `profilePicture` | `{ src: string; alt: string }` | — | **Required.** Path and alt text for the profile image. Rendered via `NuxtImg`. |
19
+ | `profilePicture` | `ProfilePicture` (`{ src; alt; width?; height? }`, exported from the layer types) | — | **Required.** Rendered via `NuxtImg` with `width`/`height` defaulting to `828`/`1104` (3:4, a Vercel-allowed width). |
18
20
  | `tag` | `"div" \| "section" \| "article" \| "main"` | `"div"` | HTML element rendered as the root. |
19
21
  | `profileInfoCount` | `number` | `3` | Number of `profile-info-N` slots to generate when none are explicitly provided. |
20
22
  | `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes applied to the root element. |
@@ -70,7 +72,7 @@ type: reference
70
72
  The `profile-info-N` slots are discovered at runtime by filtering `useSlots()` for keys matching `/^profile-info-\d+$/`. The slots are rendered in ascending numeric order.
71
73
 
72
74
  - If you provide `#profile-info-1`, `#profile-info-2`, `#profile-info-3` — all three render in order.
73
- - If you provide no `profile-info-*` slots, the component generates `profileInfoCount` empty placeholder blocks.
75
+ - If you provide no `profile-info-*` slots, the component renders `profileInfoCount` empty blocks (they used to contain visible placeholder text, removed 2026-09-27). Slot discovery runs every render, so slots added after mount appear.
74
76
  - Gaps are supported — you can provide `#profile-info-1` and `#profile-info-3` without `#profile-info-2`; they sort correctly.
75
77
 
76
78
  ## heroText slot prop
@@ -88,8 +90,8 @@ If you use a different heading component, bind `headingId` to whatever prop rend
88
90
  ## Layout
89
91
 
90
92
  - **Mobile**: single column — picture stacked above info.
91
- - **768px+**: two columns — `384px` picture column, `1fr` info column, `4rem` gap.
92
- - Picture frame: `aspect-ratio: 3/4`, `border-radius: 8px`, `overflow: hidden`. The `NuxtImg` fills the frame with `object-fit: cover`.
93
+ - **768px+**: two columns — `--profile-section-picture-width` (`384px`) picture column, `1fr` info column, `--profile-section-gap-wide` (`4rem`) gap (`--profile-section-gap`, `2rem`, below 768px).
94
+ - Picture frame (`.profile-section-picture`): `--profile-section-picture-aspect-ratio` (`3 / 4`), `--profile-section-picture-border-radius` (`8px`), `overflow: hidden`. Full token list: `CONSUMER-STYLING.md` in the component folder. The `NuxtImg` fills the frame with `object-fit: cover`.
93
95
  - Profile links: `align-items: end; justify-content: flex-end` — right-aligned to the bottom of the info column.
94
96
 
95
97
  ## CSS notes
@@ -0,0 +1,140 @@
1
+ ---
2
+ name: SamaritanPrompt
3
+ description: SamaritanPrompt and SamaritanPromptMixed animated text prompts — props, MessageConfig API, typewriter/word-pulse effects, pause on hover, aria-live announcements, cursor slot, CSS tokens
4
+ type: reference
5
+ ---
6
+
7
+ # SamaritanPrompt / SamaritanPromptMixed
8
+
9
+ ## Overview
10
+
11
+ Two components in `02.molecules/samaritan-prompt/` that loop through messages with animated text
12
+ effects, styled as a monospace line over an underline with a pulsing cursor glyph below:
13
+
14
+ - **`SamaritanPrompt`** — a list of plain strings, one effect and one set of timings for all of them.
15
+ - **`SamaritanPromptMixed`** — a list of `SamaritanPromptMessageConfig` objects, each able to pick its
16
+ own effect and override any timing. Adds an `introDelay` before each loop.
17
+
18
+ Effects:
19
+
20
+ - `typewriter` — characters typed one by one, held, deleted one by one.
21
+ - `word-pulse` — the whole message fades in, holds, fades out.
22
+
23
+ Both use `useCancellableTimer` for all timing, so the loop exits cleanly on unmount.
24
+
25
+ ## Accessibility
26
+
27
+ - The visual content (`.samaritan-prompt__content`) and the cursor are `aria-hidden="true"`, so
28
+ screen readers never hear partial text.
29
+ - A visually hidden `aria-live="polite"` `aria-atomic="true"` span announces each full message when
30
+ it's fully shown (typewriter: once typed; word-pulse: once faded in) and is cleared before it
31
+ deletes or fades out, so a repeated message announces again.
32
+ - **Pause on hover** (WCAG 2.2.2): pointer over the root pauses the sequence where it is and the
33
+ cursor pulse; leaving resumes. The root gets `data-paused` while paused.
34
+ - `prefers-reduced-motion: reduce` removes the cursor pulse and the word-pulse fade transition. The
35
+ text sequence keeps running (it's the content).
36
+
37
+ > **Changed 2026-09-27**: `SamaritanPrompt` previously had no live region (the visible text was read
38
+ > character by character, if at all) and no reduced-motion handling; both now match
39
+ > `SamaritanPromptMixed`. Pause on hover is new on both.
40
+
41
+ ## Props — SamaritanPrompt
42
+
43
+ | Prop | Type | Default | Description |
44
+ |------|------|---------|-------------|
45
+ | `messages` | `string[]` | — | Messages to cycle through. **Required.** |
46
+ | `effect` | `"typewriter" \| "word-pulse"` | `"typewriter"` | Effect for all messages. Changing it restarts the loop. |
47
+ | `typeSpeed` | `number` | `80` | ms per character typed. |
48
+ | `deleteSpeed` | `number` | `40` | ms per character deleted. |
49
+ | `holdDuration` | `number` | `2000` | ms the typed text holds before deleting. |
50
+ | `pauseDuration` | `number` | `500` | Typewriter: ms between messages. Word-pulse: ms before each full cycle. |
51
+ | `wordDuration` | `number` | `1200` | ms a word-pulse message stays fully visible. |
52
+ | `fadeDuration` | `number` | `400` | ms for the word-pulse fade in/out. |
53
+ | `hideCursorInCycle` | `boolean` | `true` | Hide the cursor while text animates, show it during pauses. |
54
+ | `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes on the root. Reactive. |
55
+
56
+ ## Props — SamaritanPromptMixed
57
+
58
+ | Prop | Type | Default | Description |
59
+ |------|------|---------|-------------|
60
+ | `messageConfigs` | `SamaritanPromptMessageConfig[]` | — | Messages. **Required.** |
61
+ | `effect` | `"typewriter" \| "word-pulse"` | `"typewriter"` | Default effect. |
62
+ | `typeSpeed` | `number` | `80` | ms per character typed. |
63
+ | `deleteSpeed` | `number` | `40` | ms per character deleted. |
64
+ | `holdDuration` | `number` | `7000` | ms the typed text holds before deleting. |
65
+ | `pauseDuration` | `number` | `1000` | ms pause after each message. |
66
+ | `wordDuration` | `number` | `1200` | ms a word-pulse message stays fully visible. |
67
+ | `fadeDuration` | `number` | `400` | ms for the word-pulse fade in/out. |
68
+ | `introDelay` | `number` | `2000` | ms before the first message of every loop. `0` starts immediately. |
69
+ | `hideCursorInCycle` | `boolean` | `true` | Hide the cursor while text animates. |
70
+ | `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes on the root. Reactive. |
71
+
72
+ Note the different defaults for `holdDuration` and `pauseDuration` between the two components.
73
+
74
+ ### SamaritanPromptMessageConfig
75
+
76
+ ```ts
77
+ import type { SamaritanPromptMessageConfig } from "srcdev-nuxt-components";
78
+
79
+ interface SamaritanPromptMessageConfig {
80
+ text: string;
81
+ effect?: "typewriter" | "word-pulse";
82
+ typeSpeed?: number;
83
+ deleteSpeed?: number;
84
+ holdDuration?: number;
85
+ pauseDuration?: number;
86
+ wordDuration?: number;
87
+ fadeDuration?: number;
88
+ hideCursorInCycle?: boolean;
89
+ }
90
+ ```
91
+
92
+ Omitted fields fall back to the matching component prop. `SamaritanPromptEffect` is exported too.
93
+
94
+ > **Changed 2026-09-27**: this type was `MessageConfig`, exported from inside
95
+ > `SamaritanPromptMixed.vue`. It now lives in `app/types/components/samaritan-prompt.d.ts`.
96
+
97
+ ## Slots
98
+
99
+ | Slot | Default | Description |
100
+ |------|---------|-------------|
101
+ | `cursor` | `▲` | Cursor glyph. Rendered inside `aria-hidden` `.samaritan-prompt__cursor`, so keep it decorative. |
102
+
103
+ ## Usage
104
+
105
+ ```vue
106
+ <SamaritanPrompt :messages="['Can you hear me?', 'Surveillance active']" />
107
+
108
+ <SamaritanPrompt effect="word-pulse" :word-duration="2000" :messages="['Stand by']" />
109
+
110
+ <SamaritanPromptMixed
111
+ :intro-delay="0"
112
+ :message-configs="[
113
+ { text: 'Initialising system', effect: 'typewriter', holdDuration: 3000 },
114
+ { text: 'Stand by', effect: 'word-pulse', wordDuration: 2000 },
115
+ ]"
116
+ />
117
+ ```
118
+
119
+ Inside a `messageConfigs` object literal, keys are camelCase (`holdDuration`), not hyphenated; only
120
+ props on the component tag are hyphenated.
121
+
122
+ ## Styling
123
+
124
+ Full token list and class hooks: `app/components/02.molecules/samaritan-prompt/CONSUMER-STYLING.md`.
125
+ Tokens are `--samaritan-prompt-*` (text/underline/cursor colours, font, sizes, gaps, pulse
126
+ duration). Defaults are white text on the assumption of a dark page; for a light or theme-switching
127
+ page set `--samaritan-prompt-text-colour` and `--samaritan-prompt-underline-colour` (e.g. to
128
+ `var(--theme-text)`).
129
+
130
+ The component brings no page layout; centre it from its parent.
131
+
132
+ > **Changed 2026-09-27**: tokens renamed from `--samaritan-*` / `color` to `--samaritan-prompt-*` /
133
+ > `colour`. `SamaritanPromptMixed` no longer needs (or styles) a `.samaritan-stage` ancestor.
134
+
135
+ ## Notes
136
+
137
+ - `SamaritanPromptMixed` reads `messageConfigs` at the start of each loop, so prop changes land on
138
+ the next loop. `SamaritanPrompt` restarts only when `effect` changes.
139
+ - The `Mono MMM 5` font is declared with `@font-face` in each component's unscoped style from
140
+ `/fonts/monoMMM_5.ttf` (`font-display: swap` in `SamaritanPrompt`, `optional` in `SamaritanPromptMixed`).