@openreachtech/furo-vue 1.3.1

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 (310) hide show
  1. package/LICENSE +9 -0
  2. package/README.ja.md +334 -0
  3. package/README.md +333 -0
  4. package/index.js +11 -0
  5. package/lib/assets/css/furo/0010.variables-palette-color-scale.css +298 -0
  6. package/lib/assets/css/furo/0020.variables-z-index.css +10 -0
  7. package/lib/assets/css/furo/0030.variables-semantic-color.css +178 -0
  8. package/lib/assets/css/furo/0035.variables-semantic-dimension.css +104 -0
  9. package/lib/assets/css/furo/0040.variables-component-furo.css +28 -0
  10. package/lib/assets/css/furo/0050.furo-editor-content.css +22 -0
  11. package/lib/assets/css/furo.css +15 -0
  12. package/lib/components/atoms/FuroAvatar/FuroAvatar.vue +135 -0
  13. package/lib/components/atoms/FuroAvatar/FuroAvatarContext.js +147 -0
  14. package/lib/components/atoms/FuroBadge/FuroBadge.vue +240 -0
  15. package/lib/components/atoms/FuroBadge/FuroBadgeContext.js +298 -0
  16. package/lib/components/atoms/FuroButton/ButtonEmitPayload.js +44 -0
  17. package/lib/components/atoms/FuroButton/FuroButton.vue +301 -0
  18. package/lib/components/atoms/FuroButton/FuroButtonContext.js +328 -0
  19. package/lib/components/atoms/FuroCheckbox/CheckboxEmitPayload.js +106 -0
  20. package/lib/components/atoms/FuroCheckbox/FuroCheckbox.vue +173 -0
  21. package/lib/components/atoms/FuroCheckbox/FuroCheckboxContext.js +682 -0
  22. package/lib/components/atoms/FuroEmailField/EmailFieldEmitPayload.js +74 -0
  23. package/lib/components/atoms/FuroEmailField/FuroEmailField.vue +119 -0
  24. package/lib/components/atoms/FuroEmailField/FuroEmailFieldContext.js +311 -0
  25. package/lib/components/atoms/FuroFileField/FileFieldEmitPayload.js +80 -0
  26. package/lib/components/atoms/FuroFileField/FuroFileField.vue +128 -0
  27. package/lib/components/atoms/FuroFileField/FuroFileFieldContext.js +195 -0
  28. package/lib/components/atoms/FuroIcon/FuroIcon.vue +74 -0
  29. package/lib/components/atoms/FuroIcon/FuroIconContext.js +293 -0
  30. package/lib/components/atoms/FuroIcon/FuroIconRegistry.js +617 -0
  31. package/lib/components/atoms/FuroIcon/FuroIconifyRendererContext.js +101 -0
  32. package/lib/components/atoms/FuroIcon/furoIconData.js +164 -0
  33. package/lib/components/atoms/FuroIcon/iconRenderers.js +62 -0
  34. package/lib/components/atoms/FuroIcon/icons.js +7 -0
  35. package/lib/components/atoms/FuroNumberField/FuroNumberField.vue +213 -0
  36. package/lib/components/atoms/FuroNumberField/FuroNumberFieldContext.js +442 -0
  37. package/lib/components/atoms/FuroNumberField/NumberFieldEmitPayload.js +162 -0
  38. package/lib/components/atoms/FuroPasswordField/FuroPasswordField.vue +119 -0
  39. package/lib/components/atoms/FuroPasswordField/FuroPasswordFieldContext.js +311 -0
  40. package/lib/components/atoms/FuroPasswordField/PasswordFieldEmitPayload.js +74 -0
  41. package/lib/components/atoms/FuroRadio/FuroRadio.vue +193 -0
  42. package/lib/components/atoms/FuroRadio/FuroRadioContext.js +557 -0
  43. package/lib/components/atoms/FuroRadio/RadioEmitPayload.js +72 -0
  44. package/lib/components/atoms/FuroSwitch/FuroSwitch.vue +165 -0
  45. package/lib/components/atoms/FuroSwitch/FuroSwitchContext.js +440 -0
  46. package/lib/components/atoms/FuroSwitch/SwitchEmitPayload.js +86 -0
  47. package/lib/components/atoms/FuroTextField/FuroTextField.vue +119 -0
  48. package/lib/components/atoms/FuroTextField/FuroTextFieldContext.js +311 -0
  49. package/lib/components/atoms/FuroTextField/TextFieldEmitPayload.js +83 -0
  50. package/lib/components/atoms/FuroTextarea/FuroTextarea.vue +121 -0
  51. package/lib/components/atoms/FuroTextarea/FuroTextareaContext.js +322 -0
  52. package/lib/components/atoms/FuroTextarea/TextareaEmitPayload.js +83 -0
  53. package/lib/components/atoms/FuroToggle/FuroToggle.vue +172 -0
  54. package/lib/components/atoms/FuroToggle/FuroToggleContext.js +410 -0
  55. package/lib/components/atoms/FuroToggle/ToggleEmitPayload.js +86 -0
  56. package/lib/components/molecules/FuroAccordion/AccordionEmitPayload.js +80 -0
  57. package/lib/components/molecules/FuroAccordion/FuroAccordion.vue +219 -0
  58. package/lib/components/molecules/FuroAccordion/FuroAccordionContext.js +547 -0
  59. package/lib/components/molecules/FuroAttachment/FuroAttachment.vue +376 -0
  60. package/lib/components/molecules/FuroAttachment/FuroAttachmentContext.js +628 -0
  61. package/lib/components/molecules/FuroAutocompleteField/AutocompleteEmitPayload.js +225 -0
  62. package/lib/components/molecules/FuroAutocompleteField/FuroAutocompleteField.vue +669 -0
  63. package/lib/components/molecules/FuroAutocompleteField/FuroAutocompleteFieldContext.js +1525 -0
  64. package/lib/components/molecules/FuroAvatarGroup/FuroAvatarGroup.vue +126 -0
  65. package/lib/components/molecules/FuroAvatarGroup/FuroAvatarGroupContext.js +245 -0
  66. package/lib/components/molecules/FuroBreadcrumb/FuroBreadcrumb.vue +219 -0
  67. package/lib/components/molecules/FuroBreadcrumb/FuroBreadcrumbContext.js +257 -0
  68. package/lib/components/molecules/FuroCollapsible/CollapsibleEmitPayload.js +69 -0
  69. package/lib/components/molecules/FuroCollapsible/FuroCollapsible.vue +177 -0
  70. package/lib/components/molecules/FuroCollapsible/FuroCollapsibleContext.js +389 -0
  71. package/lib/components/molecules/FuroControlBlock/FuroControlBlock.vue +149 -0
  72. package/lib/components/molecules/FuroControlBlock/FuroControlBlockContext.js +81 -0
  73. package/lib/components/molecules/FuroDatePicker/DatePickerEmitPayload.js +74 -0
  74. package/lib/components/molecules/FuroDatePicker/FuroDatePicker.vue +661 -0
  75. package/lib/components/molecules/FuroDatePicker/FuroDatePickerContext.js +1038 -0
  76. package/lib/components/molecules/FuroDateTimePicker/DateTimePickerEmitPayload.js +96 -0
  77. package/lib/components/molecules/FuroDateTimePicker/FuroDateTimePicker.vue +153 -0
  78. package/lib/components/molecules/FuroDateTimePicker/FuroDateTimePickerContext.js +840 -0
  79. package/lib/components/molecules/FuroDropdownMenu/DropdownMenuOptionSelectEmitPayload.js +100 -0
  80. package/lib/components/molecules/FuroDropdownMenu/FuroDropdownMenu.vue +348 -0
  81. package/lib/components/molecules/FuroDropdownMenu/FuroDropdownMenuContext.js +714 -0
  82. package/lib/components/molecules/FuroDropdownMenu/FuroDropdownMenuOptionRows.vue +222 -0
  83. package/lib/components/molecules/FuroEditableField/EditableEmitPayload.js +89 -0
  84. package/lib/components/molecules/FuroEditableField/FuroEditableField.vue +314 -0
  85. package/lib/components/molecules/FuroEditableField/FuroEditableFieldContext.js +1018 -0
  86. package/lib/components/molecules/FuroEditableField/processors/EditorCollisionProcessor.js +236 -0
  87. package/lib/components/molecules/FuroEditableField/processors/ObjectProcessor.js +101 -0
  88. package/lib/components/molecules/FuroEmptyState/FuroEmptyState.vue +124 -0
  89. package/lib/components/molecules/FuroEmptyState/FuroEmptyStateContext.js +42 -0
  90. package/lib/components/molecules/FuroErrorState/FuroErrorState.vue +125 -0
  91. package/lib/components/molecules/FuroErrorState/FuroErrorStateContext.js +42 -0
  92. package/lib/components/molecules/FuroPagination/FuroPagination.vue +246 -0
  93. package/lib/components/molecules/FuroPagination/FuroPaginationContext.js +489 -0
  94. package/lib/components/molecules/FuroPopover/FuroPopover.vue +171 -0
  95. package/lib/components/molecules/FuroPopover/FuroPopoverContext.js +279 -0
  96. package/lib/components/molecules/FuroScrollArea/FuroScrollArea.vue +181 -0
  97. package/lib/components/molecules/FuroScrollArea/FuroScrollAreaContext.js +149 -0
  98. package/lib/components/molecules/FuroSearchField/FuroSearchField.vue +155 -0
  99. package/lib/components/molecules/FuroSearchField/FuroSearchFieldContext.js +231 -0
  100. package/lib/components/molecules/FuroSectionHeader/FuroSectionHeader.vue +140 -0
  101. package/lib/components/molecules/FuroSectionHeader/FuroSectionHeaderContext.js +204 -0
  102. package/lib/components/molecules/FuroSelect/FuroSelect.vue +474 -0
  103. package/lib/components/molecules/FuroSelect/FuroSelectContext.js +743 -0
  104. package/lib/components/molecules/FuroSelect/SelectEmitPayload.js +181 -0
  105. package/lib/components/molecules/FuroSeparator/FuroSeparator.vue +88 -0
  106. package/lib/components/molecules/FuroSeparator/FuroSeparatorContext.js +40 -0
  107. package/lib/components/molecules/FuroSkeleton/FuroSkeleton.vue +101 -0
  108. package/lib/components/molecules/FuroSkeleton/FuroSkeletonContext.js +82 -0
  109. package/lib/components/molecules/FuroSplitter/FuroSplitter.vue +237 -0
  110. package/lib/components/molecules/FuroSplitter/FuroSplitterContext.js +429 -0
  111. package/lib/components/molecules/FuroSplitter/SplitterEmitPayload.js +69 -0
  112. package/lib/components/molecules/FuroTimeField/FuroTimeField.vue +251 -0
  113. package/lib/components/molecules/FuroTimeField/FuroTimeFieldContext.js +1138 -0
  114. package/lib/components/molecules/FuroTimeField/TimeFieldEmitPayload.js +74 -0
  115. package/lib/components/molecules/FuroToggleGroup/FuroToggleGroup.vue +211 -0
  116. package/lib/components/molecules/FuroToggleGroup/FuroToggleGroupContext.js +551 -0
  117. package/lib/components/molecules/FuroToggleGroup/ToggleGroupEmitPayload.js +80 -0
  118. package/lib/components/molecules/FuroToolBar/FuroToolBar.vue +91 -0
  119. package/lib/components/molecules/FuroToolBar/FuroToolBarContext.js +75 -0
  120. package/lib/components/molecules/FuroTooltip/FuroTooltip.vue +183 -0
  121. package/lib/components/molecules/FuroTooltip/FuroTooltipContext.js +290 -0
  122. package/lib/components/organisms/FuroAlertDialog/FuroAlertDialog.vue +324 -0
  123. package/lib/components/organisms/FuroAlertDialog/FuroAlertDialogContext.js +608 -0
  124. package/lib/components/organisms/FuroDialog/FuroDialog.vue +362 -0
  125. package/lib/components/organisms/FuroDialog/FuroDialogContext.js +535 -0
  126. package/lib/components/organisms/FuroDrawer/FuroDrawer.vue +618 -0
  127. package/lib/components/organisms/FuroDrawer/FuroDrawerContext.js +676 -0
  128. package/lib/components/organisms/FuroEditor/FuroEditor.vue +613 -0
  129. package/lib/components/organisms/FuroEditor/FuroEditorCommandContext.js +420 -0
  130. package/lib/components/organisms/FuroEditor/FuroEditorContext.js +2048 -0
  131. package/lib/components/organisms/FuroEditor/FuroEditorMentionMenu.vue +120 -0
  132. package/lib/components/organisms/FuroEditor/FuroEditorMentionMenuContext.js +261 -0
  133. package/lib/components/organisms/FuroEditor/PreserveNewlinesPasteExtension.js +267 -0
  134. package/lib/components/organisms/FuroEditor/build-editor-extensions.js +97 -0
  135. package/lib/components/organisms/FuroEditor/mention-suggestion.js +320 -0
  136. package/lib/components/organisms/FuroEditor/paste-link-segments.js +124 -0
  137. package/lib/components/organisms/FuroSidebar/FuroSidebar.vue +473 -0
  138. package/lib/components/organisms/FuroSidebar/FuroSidebarContext.js +1014 -0
  139. package/lib/components/organisms/FuroStepper/FuroStepper.vue +345 -0
  140. package/lib/components/organisms/FuroStepper/FuroStepperContext.js +481 -0
  141. package/lib/components/organisms/FuroTable/FuroTable.vue +707 -0
  142. package/lib/components/organisms/FuroTable/FuroTableContext.js +1965 -0
  143. package/lib/components/organisms/FuroTable/FuroTableRowItemContext.js +111 -0
  144. package/lib/components/organisms/FuroTabs/FuroTabs.vue +403 -0
  145. package/lib/components/organisms/FuroTabs/FuroTabsContext.js +846 -0
  146. package/lib/components/organisms/FuroToast/FuroToast.vue +624 -0
  147. package/lib/components/organisms/FuroToast/FuroToastContext.js +1089 -0
  148. package/lib/components/organisms/FuroToast/FuroToaster.vue +44 -0
  149. package/lib/components/organisms/FuroToast/FuroToasterContext.js +113 -0
  150. package/lib/components/organisms/FuroToast/ToastQueue.js +325 -0
  151. package/lib/components/organisms/FuroToast/toast.js +64 -0
  152. package/lib/contexts/BaseFuroContext.js +318 -0
  153. package/lib/contexts/BaseFuroContextAccessor.js +47 -0
  154. package/lib/emit-payload/BaseEmitPayload.js +91 -0
  155. package/lib/index.components.js +61 -0
  156. package/lib/index.core.js +18 -0
  157. package/lib/tools/TimerClerk.js +75 -0
  158. package/nuxt/index.js +109 -0
  159. package/nuxt/runtime/furo-icon-renderer.js +24 -0
  160. package/package.json +137 -0
  161. package/public/furo-vue/components.json +4619 -0
  162. package/public/furo-vue/llms.txt +66 -0
  163. package/types/furo-nuxt.d.ts +48 -0
  164. package/types/generated/components/atoms/FuroAvatar/FuroAvatar.vue.d.ts +74 -0
  165. package/types/generated/components/atoms/FuroAvatar/FuroAvatarContext.d.ts +82 -0
  166. package/types/generated/components/atoms/FuroBadge/FuroBadge.vue.d.ts +12 -0
  167. package/types/generated/components/atoms/FuroBadge/FuroBadgeContext.d.ts +160 -0
  168. package/types/generated/components/atoms/FuroButton/ButtonEmitPayload.d.ts +19 -0
  169. package/types/generated/components/atoms/FuroButton/FuroButton.vue.d.ts +53 -0
  170. package/types/generated/components/atoms/FuroButton/FuroButtonContext.d.ts +156 -0
  171. package/types/generated/components/atoms/FuroCheckbox/CheckboxEmitPayload.d.ts +55 -0
  172. package/types/generated/components/atoms/FuroCheckbox/FuroCheckbox.vue.d.ts +87 -0
  173. package/types/generated/components/atoms/FuroCheckbox/FuroCheckboxContext.d.ts +342 -0
  174. package/types/generated/components/atoms/FuroEmailField/EmailFieldEmitPayload.d.ts +46 -0
  175. package/types/generated/components/atoms/FuroEmailField/FuroEmailField.vue.d.ts +458 -0
  176. package/types/generated/components/atoms/FuroEmailField/FuroEmailFieldContext.d.ts +161 -0
  177. package/types/generated/components/atoms/FuroFileField/FileFieldEmitPayload.d.ts +46 -0
  178. package/types/generated/components/atoms/FuroFileField/FuroFileField.vue.d.ts +454 -0
  179. package/types/generated/components/atoms/FuroFileField/FuroFileFieldContext.d.ts +109 -0
  180. package/types/generated/components/atoms/FuroIcon/FuroIcon.vue.d.ts +14 -0
  181. package/types/generated/components/atoms/FuroIcon/FuroIconContext.d.ts +152 -0
  182. package/types/generated/components/atoms/FuroIcon/FuroIconRegistry.d.ts +457 -0
  183. package/types/generated/components/atoms/FuroIcon/FuroIconifyRendererContext.d.ts +65 -0
  184. package/types/generated/components/atoms/FuroIcon/furoIconData.d.ts +154 -0
  185. package/types/generated/components/atoms/FuroIcon/iconRenderers.d.ts +6 -0
  186. package/types/generated/components/atoms/FuroIcon/icons.d.ts +6 -0
  187. package/types/generated/components/atoms/FuroNumberField/FuroNumberField.vue.d.ts +500 -0
  188. package/types/generated/components/atoms/FuroNumberField/FuroNumberFieldContext.d.ts +243 -0
  189. package/types/generated/components/atoms/FuroNumberField/NumberFieldEmitPayload.d.ts +74 -0
  190. package/types/generated/components/atoms/FuroPasswordField/FuroPasswordField.vue.d.ts +458 -0
  191. package/types/generated/components/atoms/FuroPasswordField/FuroPasswordFieldContext.d.ts +161 -0
  192. package/types/generated/components/atoms/FuroPasswordField/PasswordFieldEmitPayload.d.ts +46 -0
  193. package/types/generated/components/atoms/FuroRadio/FuroRadio.vue.d.ts +96 -0
  194. package/types/generated/components/atoms/FuroRadio/FuroRadioContext.d.ts +290 -0
  195. package/types/generated/components/atoms/FuroRadio/RadioEmitPayload.d.ts +39 -0
  196. package/types/generated/components/atoms/FuroSwitch/FuroSwitch.vue.d.ts +74 -0
  197. package/types/generated/components/atoms/FuroSwitch/FuroSwitchContext.d.ts +218 -0
  198. package/types/generated/components/atoms/FuroSwitch/SwitchEmitPayload.d.ts +42 -0
  199. package/types/generated/components/atoms/FuroTextField/FuroTextField.vue.d.ts +458 -0
  200. package/types/generated/components/atoms/FuroTextField/FuroTextFieldContext.d.ts +161 -0
  201. package/types/generated/components/atoms/FuroTextField/TextFieldEmitPayload.d.ts +52 -0
  202. package/types/generated/components/atoms/FuroTextarea/FuroTextarea.vue.d.ts +422 -0
  203. package/types/generated/components/atoms/FuroTextarea/FuroTextareaContext.d.ts +161 -0
  204. package/types/generated/components/atoms/FuroTextarea/TextareaEmitPayload.d.ts +52 -0
  205. package/types/generated/components/atoms/FuroToggle/FuroToggle.vue.d.ts +51 -0
  206. package/types/generated/components/atoms/FuroToggle/FuroToggleContext.d.ts +191 -0
  207. package/types/generated/components/atoms/FuroToggle/ToggleEmitPayload.d.ts +42 -0
  208. package/types/generated/components/molecules/FuroAccordion/AccordionEmitPayload.d.ts +41 -0
  209. package/types/generated/components/molecules/FuroAccordion/FuroAccordion.vue.d.ts +133 -0
  210. package/types/generated/components/molecules/FuroAccordion/FuroAccordionContext.d.ts +279 -0
  211. package/types/generated/components/molecules/FuroAttachment/FuroAttachment.vue.d.ts +79 -0
  212. package/types/generated/components/molecules/FuroAttachment/FuroAttachmentContext.d.ts +363 -0
  213. package/types/generated/components/molecules/FuroAutocompleteField/AutocompleteEmitPayload.d.ts +129 -0
  214. package/types/generated/components/molecules/FuroAutocompleteField/FuroAutocompleteField.vue.d.ts +751 -0
  215. package/types/generated/components/molecules/FuroAutocompleteField/FuroAutocompleteFieldContext.d.ts +722 -0
  216. package/types/generated/components/molecules/FuroAvatarGroup/FuroAvatarGroup.vue.d.ts +84 -0
  217. package/types/generated/components/molecules/FuroAvatarGroup/FuroAvatarGroupContext.d.ts +150 -0
  218. package/types/generated/components/molecules/FuroBreadcrumb/FuroBreadcrumb.vue.d.ts +24 -0
  219. package/types/generated/components/molecules/FuroBreadcrumb/FuroBreadcrumbContext.d.ts +152 -0
  220. package/types/generated/components/molecules/FuroCollapsible/CollapsibleEmitPayload.d.ts +36 -0
  221. package/types/generated/components/molecules/FuroCollapsible/FuroCollapsible.vue.d.ts +98 -0
  222. package/types/generated/components/molecules/FuroCollapsible/FuroCollapsibleContext.d.ts +191 -0
  223. package/types/generated/components/molecules/FuroControlBlock/FuroControlBlock.vue.d.ts +30 -0
  224. package/types/generated/components/molecules/FuroControlBlock/FuroControlBlockContext.d.ts +57 -0
  225. package/types/generated/components/molecules/FuroDatePicker/DatePickerEmitPayload.d.ts +41 -0
  226. package/types/generated/components/molecules/FuroDatePicker/FuroDatePicker.vue.d.ts +456 -0
  227. package/types/generated/components/molecules/FuroDatePicker/FuroDatePickerContext.d.ts +516 -0
  228. package/types/generated/components/molecules/FuroDateTimePicker/DateTimePickerEmitPayload.d.ts +55 -0
  229. package/types/generated/components/molecules/FuroDateTimePicker/FuroDateTimePicker.vue.d.ts +1365 -0
  230. package/types/generated/components/molecules/FuroDateTimePicker/FuroDateTimePickerContext.d.ts +435 -0
  231. package/types/generated/components/molecules/FuroDropdownMenu/DropdownMenuOptionSelectEmitPayload.d.ts +48 -0
  232. package/types/generated/components/molecules/FuroDropdownMenu/FuroDropdownMenu.vue.d.ts +773 -0
  233. package/types/generated/components/molecules/FuroDropdownMenu/FuroDropdownMenuContext.d.ts +380 -0
  234. package/types/generated/components/molecules/FuroDropdownMenu/FuroDropdownMenuOptionRows.vue.d.ts +261 -0
  235. package/types/generated/components/molecules/FuroEditableField/EditableEmitPayload.d.ts +39 -0
  236. package/types/generated/components/molecules/FuroEditableField/FuroEditableField.vue.d.ts +646 -0
  237. package/types/generated/components/molecules/FuroEditableField/FuroEditableFieldContext.d.ts +477 -0
  238. package/types/generated/components/molecules/FuroEditableField/processors/EditorCollisionProcessor.d.ts +121 -0
  239. package/types/generated/components/molecules/FuroEditableField/processors/ObjectProcessor.d.ts +45 -0
  240. package/types/generated/components/molecules/FuroEmptyState/FuroEmptyState.vue.d.ts +21 -0
  241. package/types/generated/components/molecules/FuroEmptyState/FuroEmptyStateContext.d.ts +32 -0
  242. package/types/generated/components/molecules/FuroErrorState/FuroErrorState.vue.d.ts +21 -0
  243. package/types/generated/components/molecules/FuroErrorState/FuroErrorStateContext.d.ts +32 -0
  244. package/types/generated/components/molecules/FuroPagination/FuroPagination.vue.d.ts +534 -0
  245. package/types/generated/components/molecules/FuroPagination/FuroPaginationContext.d.ts +271 -0
  246. package/types/generated/components/molecules/FuroPopover/FuroPopover.vue.d.ts +513 -0
  247. package/types/generated/components/molecules/FuroPopover/FuroPopoverContext.d.ts +160 -0
  248. package/types/generated/components/molecules/FuroScrollArea/FuroScrollArea.vue.d.ts +124 -0
  249. package/types/generated/components/molecules/FuroScrollArea/FuroScrollAreaContext.d.ts +86 -0
  250. package/types/generated/components/molecules/FuroSearchField/FuroSearchField.vue.d.ts +487 -0
  251. package/types/generated/components/molecules/FuroSearchField/FuroSearchFieldContext.d.ts +137 -0
  252. package/types/generated/components/molecules/FuroSectionHeader/FuroSectionHeader.vue.d.ts +49 -0
  253. package/types/generated/components/molecules/FuroSectionHeader/FuroSectionHeaderContext.d.ts +121 -0
  254. package/types/generated/components/molecules/FuroSelect/FuroSelect.vue.d.ts +719 -0
  255. package/types/generated/components/molecules/FuroSelect/FuroSelectContext.d.ts +402 -0
  256. package/types/generated/components/molecules/FuroSelect/SelectEmitPayload.d.ts +102 -0
  257. package/types/generated/components/molecules/FuroSeparator/FuroSeparator.vue.d.ts +39 -0
  258. package/types/generated/components/molecules/FuroSeparator/FuroSeparatorContext.d.ts +31 -0
  259. package/types/generated/components/molecules/FuroSkeleton/FuroSkeleton.vue.d.ts +27 -0
  260. package/types/generated/components/molecules/FuroSkeleton/FuroSkeletonContext.d.ts +61 -0
  261. package/types/generated/components/molecules/FuroSplitter/FuroSplitter.vue.d.ts +139 -0
  262. package/types/generated/components/molecules/FuroSplitter/FuroSplitterContext.d.ts +226 -0
  263. package/types/generated/components/molecules/FuroSplitter/SplitterEmitPayload.d.ts +41 -0
  264. package/types/generated/components/molecules/FuroTimeField/FuroTimeField.vue.d.ts +498 -0
  265. package/types/generated/components/molecules/FuroTimeField/FuroTimeFieldContext.d.ts +555 -0
  266. package/types/generated/components/molecules/FuroTimeField/TimeFieldEmitPayload.d.ts +41 -0
  267. package/types/generated/components/molecules/FuroToggleGroup/FuroToggleGroup.vue.d.ts +70 -0
  268. package/types/generated/components/molecules/FuroToggleGroup/FuroToggleGroupContext.d.ts +270 -0
  269. package/types/generated/components/molecules/FuroToggleGroup/ToggleGroupEmitPayload.d.ts +41 -0
  270. package/types/generated/components/molecules/FuroToolBar/FuroToolBar.vue.d.ts +30 -0
  271. package/types/generated/components/molecules/FuroToolBar/FuroToolBarContext.d.ts +48 -0
  272. package/types/generated/components/molecules/FuroTooltip/FuroTooltip.vue.d.ts +524 -0
  273. package/types/generated/components/molecules/FuroTooltip/FuroTooltipContext.d.ts +166 -0
  274. package/types/generated/components/organisms/FuroAlertDialog/FuroAlertDialog.vue.d.ts +651 -0
  275. package/types/generated/components/organisms/FuroAlertDialog/FuroAlertDialogContext.d.ts +299 -0
  276. package/types/generated/components/organisms/FuroDialog/FuroDialog.vue.d.ts +583 -0
  277. package/types/generated/components/organisms/FuroDialog/FuroDialogContext.d.ts +264 -0
  278. package/types/generated/components/organisms/FuroDrawer/FuroDrawer.vue.d.ts +635 -0
  279. package/types/generated/components/organisms/FuroDrawer/FuroDrawerContext.d.ts +347 -0
  280. package/types/generated/components/organisms/FuroEditor/FuroEditor.vue.d.ts +2487 -0
  281. package/types/generated/components/organisms/FuroEditor/FuroEditorCommandContext.d.ts +192 -0
  282. package/types/generated/components/organisms/FuroEditor/FuroEditorContext.d.ts +904 -0
  283. package/types/generated/components/organisms/FuroEditor/FuroEditorMentionMenu.vue.d.ts +43 -0
  284. package/types/generated/components/organisms/FuroEditor/FuroEditorMentionMenuContext.d.ts +159 -0
  285. package/types/generated/components/organisms/FuroEditor/PreserveNewlinesPasteExtension.d.ts +43 -0
  286. package/types/generated/components/organisms/FuroEditor/build-editor-extensions.d.ts +22 -0
  287. package/types/generated/components/organisms/FuroEditor/mention-suggestion.d.ts +25 -0
  288. package/types/generated/components/organisms/FuroEditor/paste-link-segments.d.ts +31 -0
  289. package/types/generated/components/organisms/FuroSidebar/FuroSidebar.vue.d.ts +898 -0
  290. package/types/generated/components/organisms/FuroSidebar/FuroSidebarContext.d.ts +596 -0
  291. package/types/generated/components/organisms/FuroStepper/FuroStepper.vue.d.ts +589 -0
  292. package/types/generated/components/organisms/FuroStepper/FuroStepperContext.d.ts +266 -0
  293. package/types/generated/components/organisms/FuroTable/FuroTable.vue.d.ts +528 -0
  294. package/types/generated/components/organisms/FuroTable/FuroTableContext.d.ts +1035 -0
  295. package/types/generated/components/organisms/FuroTable/FuroTableRowItemContext.d.ts +62 -0
  296. package/types/generated/components/organisms/FuroTabs/FuroTabs.vue.d.ts +515 -0
  297. package/types/generated/components/organisms/FuroTabs/FuroTabsContext.d.ts +438 -0
  298. package/types/generated/components/organisms/FuroToast/FuroToast.vue.d.ts +725 -0
  299. package/types/generated/components/organisms/FuroToast/FuroToastContext.d.ts +543 -0
  300. package/types/generated/components/organisms/FuroToast/FuroToaster.vue.d.ts +729 -0
  301. package/types/generated/components/organisms/FuroToast/FuroToasterContext.d.ts +62 -0
  302. package/types/generated/components/organisms/FuroToast/ToastQueue.d.ts +201 -0
  303. package/types/generated/components/organisms/FuroToast/toast.d.ts +23 -0
  304. package/types/generated/contexts/BaseFuroContext.d.ts +207 -0
  305. package/types/generated/contexts/BaseFuroContextAccessor.d.ts +28 -0
  306. package/types/generated/emit-payload/BaseEmitPayload.d.ts +62 -0
  307. package/types/generated/index.components.d.ts +50 -0
  308. package/types/generated/index.core.d.ts +6 -0
  309. package/types/generated/tools/TimerClerk.d.ts +50 -0
  310. package/types/index.d.ts +12 -0
@@ -0,0 +1,4619 @@
1
+ {
2
+ "library": "@openreachtech/furo-vue",
3
+ "version": "1.3.1",
4
+ "generatedFrom": "app/docs/component-registry.js",
5
+ "layers": [
6
+ "foundation",
7
+ "atom",
8
+ "molecule",
9
+ "organism"
10
+ ],
11
+ "components": [
12
+ {
13
+ "slug": "design-tokens",
14
+ "name": "Design Tokens",
15
+ "layer": "foundation",
16
+ "summary": "Palette scales, semantic colors, and dimension tokens that power every component.",
17
+ "import": null,
18
+ "docs": "docs/design-tokens.md",
19
+ "props": [],
20
+ "parcel": [],
21
+ "events": [],
22
+ "slots": [],
23
+ "features": []
24
+ },
25
+ {
26
+ "slug": "button",
27
+ "name": "FuroButton",
28
+ "layer": "atom",
29
+ "summary": "Action trigger atom with variants, sizes, loading, and asChild composition.",
30
+ "import": "import { FuroButton } from '@openreachtech/furo-vue'",
31
+ "docs": "docs/furo-button.md",
32
+ "props": [
33
+ {
34
+ "name": "parcel",
35
+ "type": "FuroButtonParcel | null",
36
+ "default": "null",
37
+ "description": "Furo behavior object. The only public prop; HTML attributes pass through."
38
+ }
39
+ ],
40
+ "parcel": [
41
+ {
42
+ "name": "variant",
43
+ "type": "FuroButtonVariant",
44
+ "default": "'default'",
45
+ "description": "Visual style preset."
46
+ },
47
+ {
48
+ "name": "size",
49
+ "type": "FuroButtonSize",
50
+ "default": "'default'",
51
+ "description": "Size preset."
52
+ },
53
+ {
54
+ "name": "disabled",
55
+ "type": "boolean",
56
+ "default": "false",
57
+ "description": "Disables interaction; also respects a fallthrough disabled attribute."
58
+ },
59
+ {
60
+ "name": "loading",
61
+ "type": "boolean",
62
+ "default": "false",
63
+ "description": "Shows the loading slot and blocks the click emit."
64
+ },
65
+ {
66
+ "name": "asChild",
67
+ "type": "boolean",
68
+ "default": "false",
69
+ "description": "Merge props and behavior onto a single child element."
70
+ },
71
+ {
72
+ "name": "type",
73
+ "type": "'button' | 'submit' | 'reset'",
74
+ "default": "'button'",
75
+ "description": "Native button type when not asChild."
76
+ }
77
+ ],
78
+ "events": [
79
+ {
80
+ "name": "click",
81
+ "payload": "ButtonEmitPayload",
82
+ "description": "User activates the button. Not fired while disabled or loading."
83
+ }
84
+ ],
85
+ "slots": [
86
+ {
87
+ "name": "default",
88
+ "scopedProps": "—",
89
+ "description": "Button label or icon content."
90
+ },
91
+ {
92
+ "name": "loading",
93
+ "scopedProps": "—",
94
+ "description": "Custom spinner in the loading overlay (default: ph:circle-notch)."
95
+ }
96
+ ],
97
+ "features": [
98
+ "Six visual variants: default, secondary, destructive, outline, ghost, link.",
99
+ "Four sizes: default, sm, lg, and a square icon size.",
100
+ "Disabled and loading states block the click emit and set aria-disabled / aria-busy.",
101
+ "Loading overlay keeps the label in layout, so the button width never shifts.",
102
+ "asChild composition merges button styling onto a single child (anchors, menu triggers).",
103
+ "Click emit carries a typed ButtonEmitPayload built from the native event."
104
+ ]
105
+ },
106
+ {
107
+ "slug": "checkbox",
108
+ "name": "FuroCheckbox",
109
+ "layer": "atom",
110
+ "summary": "Boolean form control with checked, indeterminate, and invalid states.",
111
+ "import": "import { FuroCheckbox } from '@openreachtech/furo-vue'",
112
+ "docs": "docs/furo-checkbox.md",
113
+ "props": [
114
+ {
115
+ "name": "parcel",
116
+ "type": "FuroCheckboxParcel | null",
117
+ "default": "null",
118
+ "description": "Furo behavior object. The only public prop; HTML attributes pass through."
119
+ }
120
+ ],
121
+ "parcel": [
122
+ {
123
+ "name": "value",
124
+ "type": "FuroCheckboxValue",
125
+ "default": "—",
126
+ "description": "Controlled checked state. Presence of this key (Object.hasOwn) enables controlled mode."
127
+ },
128
+ {
129
+ "name": "indeterminate",
130
+ "type": "boolean",
131
+ "default": "false",
132
+ "description": "When true, shows the [-] indicator; value still reflects the checked boolean."
133
+ },
134
+ {
135
+ "name": "invalid",
136
+ "type": "boolean",
137
+ "default": "false",
138
+ "description": ".invalid class plus aria-invalid on the checkbox root."
139
+ },
140
+ {
141
+ "name": "disabled",
142
+ "type": "boolean",
143
+ "default": "false",
144
+ "description": "Disables interaction; also respects a fallthrough disabled attribute."
145
+ },
146
+ {
147
+ "name": "required",
148
+ "type": "boolean",
149
+ "default": "false",
150
+ "description": "Forwarded to the root; also respects a fallthrough required attribute."
151
+ },
152
+ {
153
+ "name": "size",
154
+ "type": "string",
155
+ "default": "'1.125rem'",
156
+ "description": "Box width and height; the icon uses 8/9 of the box."
157
+ }
158
+ ],
159
+ "events": [
160
+ {
161
+ "name": "change-value",
162
+ "payload": "CheckboxEmitPayload",
163
+ "description": "Fired on each committed toggle from the checkbox root."
164
+ },
165
+ {
166
+ "name": "update:value",
167
+ "payload": "FuroCheckboxValue",
168
+ "description": "Checked boolean after a toggle (v-model:value)."
169
+ },
170
+ {
171
+ "name": "update:indeterminate",
172
+ "payload": "boolean",
173
+ "description": "Indeterminate flag after a toggle (v-model:indeterminate)."
174
+ }
175
+ ],
176
+ "slots": [
177
+ {
178
+ "name": "indicator",
179
+ "scopedProps": "—",
180
+ "description": "Checked indicator. Default: ph:check-bold when value is true."
181
+ },
182
+ {
183
+ "name": "indeterminate-indicator",
184
+ "scopedProps": "—",
185
+ "description": "Indeterminate indicator. Default: ph:minus-bold when indeterminate."
186
+ }
187
+ ],
188
+ "features": [
189
+ "Public SFC prop is parcel only; HTML and form attributes pass through to the checkbox root.",
190
+ "Boolean checked model via parcel.value or v-model:value, with controlled and uncontrolled modes.",
191
+ "Indeterminate is a separate boolean channel through parcel.indeterminate or v-model:indeterminate.",
192
+ "invalid, disabled, and required map to the .invalid class and aria-invalid / disabled / required.",
193
+ "parcel.size accepts any CSS length and drives --furo-checkbox-size and the icon size.",
194
+ "Default indicators render ph:check-bold when checked and ph:minus-bold when indeterminate."
195
+ ]
196
+ },
197
+ {
198
+ "slug": "text-field",
199
+ "name": "FuroTextField",
200
+ "layer": "atom",
201
+ "summary": "Single-line text input atom with the shared parcel and value contract.",
202
+ "import": "import { FuroTextField } from '@openreachtech/furo-vue'",
203
+ "docs": "docs/furo-text-field.md",
204
+ "props": [
205
+ {
206
+ "name": "parcel",
207
+ "type": "FuroTextFieldParcel | null",
208
+ "default": "null",
209
+ "description": "Behavior-controlling props as one object. Native HTML attributes pass through."
210
+ }
211
+ ],
212
+ "parcel": [
213
+ {
214
+ "name": "value",
215
+ "type": "string | number | null",
216
+ "default": "null",
217
+ "description": "Controlled value, synced to the internal ref."
218
+ },
219
+ {
220
+ "name": "invalid",
221
+ "type": "boolean",
222
+ "default": "false",
223
+ "description": "Applies the invalid / error visual state."
224
+ }
225
+ ],
226
+ "events": [
227
+ {
228
+ "name": "change-value",
229
+ "payload": "TextFieldEmitPayload",
230
+ "description": "Emitted on every input event (each keystroke)."
231
+ },
232
+ {
233
+ "name": "commit-value",
234
+ "payload": "TextFieldEmitPayload",
235
+ "description": "Emitted on blur or Enter key press."
236
+ },
237
+ {
238
+ "name": "update:value",
239
+ "payload": "string | null",
240
+ "description": "Raw string value emitted alongside change-value and commit-value for v-model:value."
241
+ }
242
+ ],
243
+ "slots": [],
244
+ "features": [
245
+ "Opinionated abstraction over a native <input type=\"text\"> with internal state management.",
246
+ "Two input mechanisms: parcel for behavior, fallthrough attributes for native HTML attributes.",
247
+ "Controlled via parcel.value or v-model:value, or uncontrolled when value is omitted.",
248
+ "change-value fires on every keystroke; commit-value fires on blur or Enter.",
249
+ "A watcher inside the component syncs parcel.value and the value attribute, so no parent watcher is needed.",
250
+ "TextFieldEmitPayload exposes trimmed-value and emptiness helpers for parent-side validation."
251
+ ]
252
+ },
253
+ {
254
+ "slug": "textarea",
255
+ "name": "FuroTextarea",
256
+ "layer": "atom",
257
+ "summary": "Multi-line text input atom following the form-control contract.",
258
+ "import": "import { FuroTextarea } from '@openreachtech/furo-vue'",
259
+ "docs": "docs/furo-textarea.md",
260
+ "props": [
261
+ {
262
+ "name": "parcel",
263
+ "type": "FuroTextareaParcel | null",
264
+ "default": "null",
265
+ "description": "Behavior-controlling props as one object. Native textarea attributes pass through."
266
+ }
267
+ ],
268
+ "parcel": [
269
+ {
270
+ "name": "value",
271
+ "type": "string | null",
272
+ "default": "null",
273
+ "description": "Controlled value, synced to the internal ref."
274
+ },
275
+ {
276
+ "name": "invalid",
277
+ "type": "boolean",
278
+ "default": "false",
279
+ "description": "Applies the invalid / error visual state."
280
+ }
281
+ ],
282
+ "events": [
283
+ {
284
+ "name": "change-value",
285
+ "payload": "TextareaEmitPayload",
286
+ "description": "Emitted on every input event (each edit)."
287
+ },
288
+ {
289
+ "name": "commit-value",
290
+ "payload": "TextareaEmitPayload",
291
+ "description": "Emitted on blur only; Enter inserts a newline instead."
292
+ },
293
+ {
294
+ "name": "update:value",
295
+ "payload": "string | null",
296
+ "description": "Raw string value emitted alongside the above for v-model:value."
297
+ }
298
+ ],
299
+ "slots": [],
300
+ "features": [
301
+ "Multiline abstraction over a native <textarea>, mirroring the FuroTextField contract.",
302
+ "Two input mechanisms: parcel for behavior, fallthrough attributes for native textarea attributes.",
303
+ "commit-value fires on blur only; Enter inserts a newline and is not treated as a commit.",
304
+ "parcel.value is string-only (multiline text); there is no numeric shortcut.",
305
+ "Controlled via parcel.value or v-model:value, or uncontrolled when value is omitted.",
306
+ "TextareaEmitPayload exposes the same trimmed-value and emptiness helpers as text-field payloads."
307
+ ]
308
+ },
309
+ {
310
+ "slug": "email-field",
311
+ "name": "FuroEmailField",
312
+ "layer": "atom",
313
+ "summary": "Email input atom with type-email semantics and the shared field contract.",
314
+ "import": "import { FuroEmailField } from '@openreachtech/furo-vue'",
315
+ "docs": "docs/furo-email-field.md",
316
+ "props": [
317
+ {
318
+ "name": "parcel",
319
+ "type": "FuroEmailFieldParcel | null",
320
+ "default": "null",
321
+ "description": "Behavior-controlling props as one object. Native HTML attributes pass through."
322
+ }
323
+ ],
324
+ "parcel": [
325
+ {
326
+ "name": "value",
327
+ "type": "string | null",
328
+ "default": "null",
329
+ "description": "Controlled value, synced to the internal ref."
330
+ },
331
+ {
332
+ "name": "invalid",
333
+ "type": "boolean",
334
+ "default": "false",
335
+ "description": "Applies the invalid / error visual state."
336
+ }
337
+ ],
338
+ "events": [
339
+ {
340
+ "name": "change-value",
341
+ "payload": "EmailFieldEmitPayload",
342
+ "description": "Emitted on every input event (each keystroke)."
343
+ },
344
+ {
345
+ "name": "commit-value",
346
+ "payload": "EmailFieldEmitPayload",
347
+ "description": "Emitted on blur or Enter key press."
348
+ },
349
+ {
350
+ "name": "update:value",
351
+ "payload": "string | null",
352
+ "description": "Raw string value emitted alongside the above for v-model:value."
353
+ }
354
+ ],
355
+ "slots": [],
356
+ "features": [
357
+ "Follows the FuroTextField architecture: parcel for behavior, fallthrough for native attributes.",
358
+ "Always renders type=\"email\", enabling native format hints and constraint validation.",
359
+ "Root CSS class is .unit-form-control.email.",
360
+ "parcel.value is string-only; numeric values are not supported.",
361
+ "EmailFieldEmitPayload matches the shared text-field helper surface.",
362
+ "Format, domain, and uniqueness rules stay in the parent Context."
363
+ ]
364
+ },
365
+ {
366
+ "slug": "password-field",
367
+ "name": "FuroPasswordField",
368
+ "layer": "atom",
369
+ "summary": "Password input atom with reveal toggle and the shared field contract.",
370
+ "import": "import { FuroPasswordField } from '@openreachtech/furo-vue'",
371
+ "docs": "docs/furo-password-field.md",
372
+ "props": [
373
+ {
374
+ "name": "parcel",
375
+ "type": "FuroPasswordFieldParcel | null",
376
+ "default": "null",
377
+ "description": "Behavior-controlling props as one object. Native HTML attributes pass through."
378
+ }
379
+ ],
380
+ "parcel": [
381
+ {
382
+ "name": "value",
383
+ "type": "string | null",
384
+ "default": "null",
385
+ "description": "Controlled value, synced to the internal ref."
386
+ },
387
+ {
388
+ "name": "invalid",
389
+ "type": "boolean",
390
+ "default": "false",
391
+ "description": "Applies the invalid / error visual state."
392
+ }
393
+ ],
394
+ "events": [
395
+ {
396
+ "name": "change-value",
397
+ "payload": "PasswordFieldEmitPayload",
398
+ "description": "Emitted on every input event (each keystroke)."
399
+ },
400
+ {
401
+ "name": "commit-value",
402
+ "payload": "PasswordFieldEmitPayload",
403
+ "description": "Emitted on blur or Enter key press."
404
+ },
405
+ {
406
+ "name": "update:value",
407
+ "payload": "string | null",
408
+ "description": "Raw string value emitted alongside the above for v-model:value."
409
+ }
410
+ ],
411
+ "slots": [],
412
+ "features": [
413
+ "Follows the FuroTextField architecture: parcel for behavior, fallthrough for native attributes.",
414
+ "Always renders type=\"password\"; the type fallthrough attribute is excluded.",
415
+ "Root CSS class is .unit-form-control.password.",
416
+ "parcel.value is string-only; numeric values are not supported.",
417
+ "PasswordFieldEmitPayload matches the shared text-field helper surface."
418
+ ]
419
+ },
420
+ {
421
+ "slug": "radio",
422
+ "name": "FuroRadio",
423
+ "layer": "atom",
424
+ "summary": "Single-choice group where the options are declared as data.",
425
+ "import": "import { FuroRadio } from '@openreachtech/furo-vue'",
426
+ "docs": "docs/furo-radio.md",
427
+ "props": [
428
+ {
429
+ "name": "parcel",
430
+ "type": "FuroRadioParcel | null",
431
+ "default": "null",
432
+ "description": "Furo behavior object. The only public prop; HTML attributes pass through."
433
+ }
434
+ ],
435
+ "parcel": [
436
+ {
437
+ "name": "value",
438
+ "type": "FuroRadioValue | null",
439
+ "default": "—",
440
+ "description": "Chosen option value. Presence of this key (Object.hasOwn) enables controlled mode, even when it holds null."
441
+ },
442
+ {
443
+ "name": "options",
444
+ "type": "Array<FuroRadioOption>",
445
+ "default": "[]",
446
+ "description": "The choices to render, in order."
447
+ },
448
+ {
449
+ "name": "invalid",
450
+ "type": "boolean",
451
+ "default": "false",
452
+ "description": ".invalid class plus aria-invalid on the group root."
453
+ },
454
+ {
455
+ "name": "disabled",
456
+ "type": "boolean",
457
+ "default": "false",
458
+ "description": "Disables every option; also respects a fallthrough disabled attribute."
459
+ },
460
+ {
461
+ "name": "required",
462
+ "type": "boolean",
463
+ "default": "false",
464
+ "description": "Forwarded to the root; also respects a fallthrough required attribute."
465
+ },
466
+ {
467
+ "name": "size",
468
+ "type": "string",
469
+ "default": "'1.125rem'",
470
+ "description": "Diameter of one circle; the dot uses 4/9 of it."
471
+ }
472
+ ],
473
+ "events": [
474
+ {
475
+ "name": "change-value",
476
+ "payload": "RadioEmitPayload",
477
+ "description": "Fired when the user chooses an option."
478
+ },
479
+ {
480
+ "name": "update:value",
481
+ "payload": "FuroRadioValue | null",
482
+ "description": "Chosen option value after a change (v-model:value)."
483
+ }
484
+ ],
485
+ "slots": [
486
+ {
487
+ "name": "option-label",
488
+ "scopedProps": "{ option }",
489
+ "description": "Replaces the default label text for every option. Default: the option label in a span."
490
+ }
491
+ ],
492
+ "features": [
493
+ "Public SFC prop is parcel only; HTML and form attributes pass through to the group root.",
494
+ "Ships as the whole group, because the exclusivity that separates a radio from a checkbox only exists across a set.",
495
+ "Options are declared as data through parcel.options, the way FuroSelect declares its choices.",
496
+ "The chosen option value travels through parcel.value or v-model:value, with controlled and uncontrolled modes.",
497
+ "A parcel that owns a value key is controlled even when that key holds null, matching FuroCheckbox.",
498
+ "An option carries its own disabled, additive to the group disabled.",
499
+ "parcel.size accepts any CSS length and drives --furo-radio-size and the dot size.",
500
+ "Colour comes from the --color-selected family, so overriding one role re-themes every selection control."
501
+ ]
502
+ },
503
+ {
504
+ "slug": "number-field",
505
+ "name": "FuroNumberField",
506
+ "layer": "atom",
507
+ "summary": "Numeric input atom with stepper buttons and locale-aware formatting.",
508
+ "import": "import { FuroNumberField } from '@openreachtech/furo-vue'",
509
+ "docs": "docs/furo-number-field.md",
510
+ "props": [
511
+ {
512
+ "name": "parcel",
513
+ "type": "FuroNumberFieldParcel | null",
514
+ "default": "null",
515
+ "description": "The only declared prop; v-bind spread onto the root plus Furo extensions. Other attributes are read from attrs."
516
+ }
517
+ ],
518
+ "parcel": [
519
+ {
520
+ "name": "value",
521
+ "type": "number | null",
522
+ "default": "null",
523
+ "description": "Controlled value, watched and synced into an internal ref."
524
+ },
525
+ {
526
+ "name": "invalid",
527
+ "type": "boolean",
528
+ "default": "false",
529
+ "description": "Applies the invalid / error visual state and aria-invalid."
530
+ },
531
+ {
532
+ "name": "min",
533
+ "type": "number",
534
+ "default": "—",
535
+ "description": "Smallest value allowed; also reflected on the inner input as the min attribute."
536
+ },
537
+ {
538
+ "name": "max",
539
+ "type": "number",
540
+ "default": "—",
541
+ "description": "Largest value allowed; also reflected on the inner input as the max attribute."
542
+ },
543
+ {
544
+ "name": "step",
545
+ "type": "number",
546
+ "default": "(primitive default)",
547
+ "description": "Step for increment and decrement."
548
+ },
549
+ {
550
+ "name": "stepSnapping",
551
+ "type": "boolean",
552
+ "default": "—",
553
+ "description": "When false, avoids snapping to step increments."
554
+ },
555
+ {
556
+ "name": "formatOptions",
557
+ "type": "Intl.NumberFormatOptions",
558
+ "default": "—",
559
+ "description": "Formatting for the displayed value (currency, percent, decimals)."
560
+ },
561
+ {
562
+ "name": "locale",
563
+ "type": "string",
564
+ "default": "—",
565
+ "description": "BCP 47 locale tag for formatting (e.g. 'en-US', 'ja-JP')."
566
+ },
567
+ {
568
+ "name": "inputParcel",
569
+ "type": "object",
570
+ "default": "—",
571
+ "description": "Props and HTML attributes passed to the input part."
572
+ },
573
+ {
574
+ "name": "decrementParcel",
575
+ "type": "object",
576
+ "default": "—",
577
+ "description": "Props passed to the decrement part."
578
+ },
579
+ {
580
+ "name": "incrementParcel",
581
+ "type": "object",
582
+ "default": "—",
583
+ "description": "Props passed to the increment part."
584
+ }
585
+ ],
586
+ "events": [
587
+ {
588
+ "name": "change-value",
589
+ "payload": "NumberFieldEmitPayload",
590
+ "description": "Emitted when the model updates: typing, stepping, arrow keys, or wheel."
591
+ },
592
+ {
593
+ "name": "commit-value",
594
+ "payload": "NumberFieldEmitPayload",
595
+ "description": "Emitted on blur of the inner input or on Enter."
596
+ },
597
+ {
598
+ "name": "update:value",
599
+ "payload": "number | null",
600
+ "description": "Bare number or null emitted alongside change-value and commit-value for v-model:value."
601
+ }
602
+ ],
603
+ "slots": [
604
+ {
605
+ "name": "decrement",
606
+ "scopedProps": "{ value }",
607
+ "description": "Replaces the default decrement icon. Default: ph:minus."
608
+ },
609
+ {
610
+ "name": "increment",
611
+ "scopedProps": "{ value }",
612
+ "description": "Replaces the default increment icon. Default: ph:plus."
613
+ }
614
+ ],
615
+ "features": [
616
+ "Composite spinbutton structure: decrement button, formatted input, and increment button.",
617
+ "Keyboard (Arrow Up/Down, Page Up/Down) and mouse wheel control come from the underlying primitive.",
618
+ "parcel carries value, bounds (min/max/step), and Intl formatting via formatOptions and locale.",
619
+ "change-value fires on every model update; commit-value fires on blur or Enter.",
620
+ "NumberFieldEmitPayload reads the DOM min/max attributes for range helpers.",
621
+ "decrement and increment slots replace the default minus/plus icons."
622
+ ]
623
+ },
624
+ {
625
+ "slug": "file-field",
626
+ "name": "FuroFileField",
627
+ "layer": "atom",
628
+ "summary": "File input atom with selection display and the shared field contract.",
629
+ "import": "import { FuroFileField } from '@openreachtech/furo-vue'",
630
+ "docs": "docs/furo-file-field.md",
631
+ "props": [
632
+ {
633
+ "name": "parcel",
634
+ "type": "FuroFileFieldParcel | null",
635
+ "default": "null",
636
+ "description": "Behavior-controlling props as one object. No value key. Native HTML attributes pass through."
637
+ }
638
+ ],
639
+ "parcel": [
640
+ {
641
+ "name": "invalid",
642
+ "type": "boolean",
643
+ "default": "false",
644
+ "description": "Applies the invalid / error visual state."
645
+ }
646
+ ],
647
+ "events": [
648
+ {
649
+ "name": "change-value",
650
+ "payload": "FileFieldEmitPayload",
651
+ "description": "Emitted when the set of selected files changes (native change event)."
652
+ }
653
+ ],
654
+ "slots": [],
655
+ "features": [
656
+ "Follows the FuroTextField split: parcel for behavior, fallthrough for native attributes.",
657
+ "Always renders type=\"file\" with the root CSS class .unit-form-control.file.",
658
+ "No parcel.value: browsers forbid scripting a file input value, so selection is read via the payload.",
659
+ "multiple is a fallthrough HTML attribute, not a parcel key.",
660
+ "change-value fires when the selection changes; there is no commit-value or v-model:value.",
661
+ "FileFieldEmitPayload exposes the selected FileList and selection helpers."
662
+ ]
663
+ },
664
+ {
665
+ "slug": "toggle",
666
+ "name": "FuroToggle",
667
+ "layer": "atom",
668
+ "summary": "Two-state pressed toggle atom for toolbars and inline switches.",
669
+ "import": "import { FuroToggle } from '@openreachtech/furo-vue'",
670
+ "docs": "docs/furo-toggle.md",
671
+ "props": [
672
+ {
673
+ "name": "parcel",
674
+ "type": "FuroToggleParcel | null",
675
+ "default": "null",
676
+ "description": "Reactive data object holding the pressed value, variant, size, and disabled flag."
677
+ }
678
+ ],
679
+ "parcel": [
680
+ {
681
+ "name": "value",
682
+ "type": "boolean",
683
+ "default": "—",
684
+ "description": "Controlled pressed state. Present means controlled; absent means uncontrolled (starts released)."
685
+ },
686
+ {
687
+ "name": "variant",
688
+ "type": "'default' | 'outline'",
689
+ "default": "'default'",
690
+ "description": "default is borderless and fills the accent surface when pressed; outline adds a border."
691
+ },
692
+ {
693
+ "name": "size",
694
+ "type": "'default' | 'sm' | 'lg'",
695
+ "default": "'default'",
696
+ "description": "Control height and padding."
697
+ },
698
+ {
699
+ "name": "disabled",
700
+ "type": "boolean",
701
+ "default": "false",
702
+ "description": "Blocks interaction; also honored from a fallthrough disabled attribute."
703
+ }
704
+ ],
705
+ "events": [
706
+ {
707
+ "name": "change-value",
708
+ "payload": "ToggleEmitPayload",
709
+ "description": "Fired on every press / release; wraps a CustomEvent exposing value and the control element."
710
+ },
711
+ {
712
+ "name": "update:value",
713
+ "payload": "boolean",
714
+ "description": "v-model sync of the pressed state."
715
+ }
716
+ ],
717
+ "slots": [
718
+ {
719
+ "name": "default",
720
+ "scopedProps": "{ pressed }",
721
+ "description": "Toggle label or icon. pressed reflects the current state for conditional content."
722
+ }
723
+ ],
724
+ "features": [
725
+ "Two-state pressed / unpressed button for toolbars and inline switches.",
726
+ "Built on a headless toggle primitive that owns aria-pressed and data-state semantics.",
727
+ "Boolean pressed state via parcel.value or v-model:value, the same surface as other Furo controls.",
728
+ "Controlled when parcel.value is present; uncontrolled (starts released) otherwise.",
729
+ "default and outline variants plus default, sm, and lg sizes.",
730
+ "Building block for FuroToggleGroup and FuroToolBar."
731
+ ]
732
+ },
733
+ {
734
+ "slug": "avatar",
735
+ "name": "FuroAvatar",
736
+ "layer": "atom",
737
+ "summary": "Image avatar atom with a graceful text fallback and circle or square shape.",
738
+ "import": "import { FuroAvatar } from '@openreachtech/furo-vue'",
739
+ "docs": "docs/furo-avatar.md",
740
+ "props": [
741
+ {
742
+ "name": "parcel",
743
+ "type": "FuroAvatarParcel | null",
744
+ "default": "null",
745
+ "description": "Reactive data object holding the image source, fallback, and shape."
746
+ }
747
+ ],
748
+ "parcel": [
749
+ {
750
+ "name": "imageSource",
751
+ "type": "string",
752
+ "default": "unset",
753
+ "description": "Image URL. When unset, only the fallback renders."
754
+ },
755
+ {
756
+ "name": "imageAlternativeText",
757
+ "type": "string",
758
+ "default": "''",
759
+ "description": "Alternative text applied to the image."
760
+ },
761
+ {
762
+ "name": "fallbackText",
763
+ "type": "string",
764
+ "default": "''",
765
+ "description": "Text shown while the image is absent or loading (e.g. initials)."
766
+ },
767
+ {
768
+ "name": "fallbackDelay",
769
+ "type": "number",
770
+ "default": "unset",
771
+ "description": "Milliseconds to wait before showing the fallback, avoiding a flash on fast loads."
772
+ },
773
+ {
774
+ "name": "shape",
775
+ "type": "'circle' | 'square'",
776
+ "default": "'circle'",
777
+ "description": "Avatar shape; circle is fully rounded, square uses the medium radius."
778
+ }
779
+ ],
780
+ "events": [],
781
+ "slots": [
782
+ {
783
+ "name": "fallback",
784
+ "scopedProps": "—",
785
+ "description": "Custom fallback content; overrides fallbackText (e.g. an icon)."
786
+ }
787
+ ],
788
+ "features": [
789
+ "Renders an image avatar with a graceful text fallback (e.g. initials).",
790
+ "fallbackDelay holds the fallback back briefly to avoid a flash on fast image loads.",
791
+ "Circle (default) or square shape.",
792
+ "Fills its own box; size is controlled by the --furo-avatar-size custom property.",
793
+ "Carries no value and emits nothing."
794
+ ]
795
+ },
796
+ {
797
+ "slug": "badge",
798
+ "name": "FuroBadge",
799
+ "layer": "atom",
800
+ "summary": "Label for a record's state, in text, count, state and dot shapes.",
801
+ "import": "import { FuroBadge } from '@openreachtech/furo-vue'",
802
+ "docs": "docs/furo-badge.md",
803
+ "props": [
804
+ {
805
+ "name": "parcel",
806
+ "type": "FuroBadgeParcel | null",
807
+ "default": "null",
808
+ "description": "Furo behavior object. The only public prop; HTML attributes pass through."
809
+ }
810
+ ],
811
+ "parcel": [
812
+ {
813
+ "name": "label",
814
+ "type": "string",
815
+ "default": "''",
816
+ "description": "Text shown inside the badge. Ignored by the dot shape."
817
+ },
818
+ {
819
+ "name": "count",
820
+ "type": "number",
821
+ "default": "null",
822
+ "description": "Number shown by the count shape, read instead of label there. A count shape with no count renders 0."
823
+ },
824
+ {
825
+ "name": "shape",
826
+ "type": "FuroBadgeShape",
827
+ "default": "'text'",
828
+ "description": "text, count, state or dot."
829
+ },
830
+ {
831
+ "name": "tone",
832
+ "type": "FuroBadgeTone",
833
+ "default": "'accent'",
834
+ "description": "accent, neutral, success, warning or error. Selects a semantic role, not a colour."
835
+ },
836
+ {
837
+ "name": "emphasis",
838
+ "type": "FuroBadgeEmphasis",
839
+ "default": "'solid'",
840
+ "description": "solid, subtle or outline. Meaningful for the text and count shapes only."
841
+ },
842
+ {
843
+ "name": "size",
844
+ "type": "FuroBadgeSize",
845
+ "default": "'medium'",
846
+ "description": "large, medium or small. The count shape has two steps, so large renders the medium geometry."
847
+ }
848
+ ],
849
+ "events": [],
850
+ "slots": [
851
+ {
852
+ "name": "default",
853
+ "scopedProps": "{ text }",
854
+ "description": "Replaces the rendered text. Not rendered for the dot shape."
855
+ }
856
+ ],
857
+ "features": [
858
+ "Public SFC prop is parcel only; HTML attributes pass through to the root.",
859
+ "Purely presentational: it carries no value and emits nothing.",
860
+ "One component covers the four shapes the design draws separately: text, count, state and dot.",
861
+ "tone selects a semantic role rather than a colour, so overriding the role re-themes the badge.",
862
+ "emphasis selects solid, subtle or outline; it applies to the text and count shapes.",
863
+ "A single-digit count renders as a circle; two or more digits widen into a pill.",
864
+ "The default slot replaces the rendered text, so an icon or tabular figures can sit beside the state."
865
+ ]
866
+ },
867
+ {
868
+ "slug": "icon",
869
+ "name": "FuroIcon",
870
+ "layer": "atom",
871
+ "summary": "Icon atom rendering the glyphs the library ships, resolved offline.",
872
+ "import": "import { FuroIcon } from '@openreachtech/furo-vue'",
873
+ "docs": "docs/furo-icon.md",
874
+ "props": [
875
+ {
876
+ "name": "name",
877
+ "type": "string",
878
+ "default": "required",
879
+ "description": "Icon name including its collection prefix, for example ph:check. Must be one of the icons the library registers, since an unregistered name cannot be resolved offline."
880
+ },
881
+ {
882
+ "name": "size",
883
+ "type": "string | number | null",
884
+ "default": "null",
885
+ "description": "One CSS length applied to both axes. When unset, the glyph is 1em and scales with the surrounding text."
886
+ }
887
+ ],
888
+ "parcel": [],
889
+ "events": [],
890
+ "slots": [],
891
+ "features": [
892
+ "Renders one of the icons the library ships, with no request to a remote icon API.",
893
+ "Icon data is registered when the module loads, so a built-in icon resolves before the first render and none flickers in.",
894
+ "Takes the icon name as a plain name prop, matching the property name a framework icon module uses.",
895
+ "Every other Furo component renders its own icons through this atom, and exposes a slot so they can be replaced.",
896
+ "Carries no value and emits nothing."
897
+ ]
898
+ },
899
+ {
900
+ "slug": "switch",
901
+ "name": "FuroSwitch",
902
+ "layer": "atom",
903
+ "summary": "Boolean selection control drawn as a track with a sliding knob.",
904
+ "import": "import { FuroSwitch } from '@openreachtech/furo-vue'",
905
+ "docs": "docs/furo-switch.md",
906
+ "props": [
907
+ {
908
+ "name": "parcel",
909
+ "type": "FuroSwitchParcel | null",
910
+ "default": "null",
911
+ "description": "Furo behavior object. The only public prop; HTML attributes pass through."
912
+ }
913
+ ],
914
+ "parcel": [
915
+ {
916
+ "name": "value",
917
+ "type": "boolean",
918
+ "default": "false",
919
+ "description": "On/off model. Declaring the key makes the switch controlled."
920
+ },
921
+ {
922
+ "name": "size",
923
+ "type": "FuroSwitchSize",
924
+ "default": "'medium'",
925
+ "description": "medium or small. The design draws two steps, a 20px track and a 16px one."
926
+ },
927
+ {
928
+ "name": "disabled",
929
+ "type": "boolean",
930
+ "default": "false",
931
+ "description": "Blocks interaction and repaints the track with the disabled colour."
932
+ },
933
+ {
934
+ "name": "required",
935
+ "type": "boolean",
936
+ "default": "false",
937
+ "description": "Marks the control required for the surrounding form."
938
+ }
939
+ ],
940
+ "events": [
941
+ {
942
+ "name": "change-value",
943
+ "payload": "SwitchEmitPayload",
944
+ "description": "Emitted on every flip. The payload carries the new value and the root element."
945
+ },
946
+ {
947
+ "name": "update:value",
948
+ "payload": "boolean",
949
+ "description": "v-model:value sync, emitted alongside change-value."
950
+ }
951
+ ],
952
+ "slots": [],
953
+ "features": [
954
+ "Public SFC prop is parcel only; HTML attributes pass through to the root.",
955
+ "Binds parcel plus v-model:value with a boolean model, the same contract the checkbox and the radio use.",
956
+ "Passing parcel.value makes it controlled: it follows the parent and never flips on its own.",
957
+ "Omitting parcel.value makes it uncontrolled: it flips itself and reports the new value.",
958
+ "The track reads the --color-selected family, so overriding that role re-themes it with the other selection controls.",
959
+ "The disabled track carries a colour of its own rather than a dimmed copy of the live one.",
960
+ "size selects the medium or the small step; the knob and its travel follow the track."
961
+ ]
962
+ },
963
+ {
964
+ "slug": "attachment",
965
+ "name": "FuroAttachment",
966
+ "layer": "molecule",
967
+ "summary": "File on a record, as a row with a type glyph or as an image preview.",
968
+ "import": "import { FuroAttachment } from '@openreachtech/furo-vue'",
969
+ "docs": "docs/furo-attachment.md",
970
+ "props": [
971
+ {
972
+ "name": "parcel",
973
+ "type": "FuroAttachmentParcel | null",
974
+ "default": "null",
975
+ "description": "Furo behavior object. The only public prop; HTML attributes pass through."
976
+ }
977
+ ],
978
+ "parcel": [
979
+ {
980
+ "name": "fileName",
981
+ "type": "string",
982
+ "default": "''",
983
+ "description": "Name shown on the row, and the accessible name of the preview when no alternative text is given."
984
+ },
985
+ {
986
+ "name": "fileSize",
987
+ "type": "string",
988
+ "default": "''",
989
+ "description": "Size shown under the name, already formatted for reading. Hidden while uploading."
990
+ },
991
+ {
992
+ "name": "imageSource",
993
+ "type": "string",
994
+ "default": "null",
995
+ "description": "Preview source. Setting it turns on the image shape; a load failure falls back to the row."
996
+ },
997
+ {
998
+ "name": "imageAlternativeText",
999
+ "type": "string",
1000
+ "default": "the file name",
1001
+ "description": "Alternative text for the preview."
1002
+ },
1003
+ {
1004
+ "name": "iconName",
1005
+ "type": "string",
1006
+ "default": "'ph:file'",
1007
+ "description": "Glyph the row shows in place of a preview."
1008
+ },
1009
+ {
1010
+ "name": "uploading",
1011
+ "type": "boolean",
1012
+ "default": "false",
1013
+ "description": "Reports the file as still being sent."
1014
+ },
1015
+ {
1016
+ "name": "uploadProgress",
1017
+ "type": "number | null",
1018
+ "default": "null",
1019
+ "description": "Share of the upload already sent, nought through one hundred. Values outside the range are clamped. null means the size is unknown."
1020
+ },
1021
+ {
1022
+ "name": "downloadable",
1023
+ "type": "boolean",
1024
+ "default": "true",
1025
+ "description": "Whether the download action renders. It is withheld during an upload regardless."
1026
+ },
1027
+ {
1028
+ "name": "removable",
1029
+ "type": "boolean",
1030
+ "default": "true",
1031
+ "description": "Whether the remove action renders. During an upload of a file with no preview it cancels."
1032
+ },
1033
+ {
1034
+ "name": "downloadLabel",
1035
+ "type": "string",
1036
+ "default": "'Download'",
1037
+ "description": "Accessible name of the download action."
1038
+ },
1039
+ {
1040
+ "name": "removeLabel",
1041
+ "type": "string",
1042
+ "default": "'Remove'",
1043
+ "description": "Accessible name of the remove action."
1044
+ },
1045
+ {
1046
+ "name": "uploadingLabel",
1047
+ "type": "string",
1048
+ "default": "'Uploading'",
1049
+ "description": "Accessible name of the upload bar, which an indeterminate bar relies on because it announces no share."
1050
+ }
1051
+ ],
1052
+ "events": [
1053
+ {
1054
+ "name": "download",
1055
+ "payload": "{ fileName: string }",
1056
+ "description": "The download action was activated. The component does not fetch anything itself."
1057
+ },
1058
+ {
1059
+ "name": "remove",
1060
+ "payload": "{ fileName: string }",
1061
+ "description": "The remove action was activated, which cancels an upload in flight."
1062
+ }
1063
+ ],
1064
+ "slots": [
1065
+ {
1066
+ "name": "glyph",
1067
+ "scopedProps": "—",
1068
+ "description": "Replaces the type glyph on the row. Default: the icon named by iconName."
1069
+ },
1070
+ {
1071
+ "name": "actions",
1072
+ "scopedProps": "—",
1073
+ "description": "Replaces the whole action cluster. Default: download, remove, and the upload spinner."
1074
+ }
1075
+ ],
1076
+ "features": [
1077
+ "Public SFC prop is parcel only; HTML attributes pass through to the root.",
1078
+ "One component covers both shapes the design draws: a file row with a type glyph, and the same file as an image preview.",
1079
+ "Setting imageSource turns on the preview, which always renders at one size and crop.",
1080
+ "A preview that fails to load falls back to the file row and its glyph, never to a broken image.",
1081
+ "Changing imageSource clears the failure, so a retried upload gets a fresh attempt.",
1082
+ "uploading swaps the size caption for a progress bar, and veils the preview with a spinner instead.",
1083
+ "uploadProgress is clamped to nought through one hundred, so a fill can never outrun its track.",
1084
+ "uploadProgress: null, which an absent key also means, draws the bar as indeterminate: no aria-valuenow, no inline width, a sweeping fill.",
1085
+ "The download and remove actions appear on hover and on keyboard focus, and emit rather than acting."
1086
+ ]
1087
+ },
1088
+ {
1089
+ "slug": "autocomplete",
1090
+ "name": "FuroAutocompleteField",
1091
+ "layer": "molecule",
1092
+ "summary": "Text field with an async-friendly suggestion list and keyboard navigation.",
1093
+ "import": "import { FuroAutocompleteField } from '@openreachtech/furo-vue'",
1094
+ "docs": "docs/furo-autocomplete-field.md",
1095
+ "props": [
1096
+ {
1097
+ "name": "parcel",
1098
+ "type": "FuroAutocompleteFieldParcel | null",
1099
+ "default": "null",
1100
+ "description": "Furo behavior. The only public prop; HTML / form attributes pass through to the root."
1101
+ }
1102
+ ],
1103
+ "parcel": [
1104
+ {
1105
+ "name": "value",
1106
+ "type": "FuroAutocompleteOption | FuroAcceptableValue | Array | null",
1107
+ "default": "—",
1108
+ "description": "Controlled selection; synced to the internal value, with fallthrough value as fallback."
1109
+ },
1110
+ {
1111
+ "name": "options",
1112
+ "type": "Array<FuroAutocompleteOption | FuroAcceptableValue>",
1113
+ "default": "[]",
1114
+ "description": "List rows (groups and leaves)."
1115
+ },
1116
+ {
1117
+ "name": "optionLabel",
1118
+ "type": "string | ((option) => string)",
1119
+ "default": "uses option.label",
1120
+ "description": "Key name or function that selects each option's display label; also drives local filtering. When unset, the option's own label is used."
1121
+ },
1122
+ {
1123
+ "name": "optionValue",
1124
+ "type": "string | ((option) => value)",
1125
+ "default": "whole option object",
1126
+ "description": "Key name or function that selects each option's model value. When unset, update:value emits the whole option object (the historical default); when set, it emits that key's value or the function's result."
1127
+ },
1128
+ {
1129
+ "name": "maxVisibleChips",
1130
+ "type": "number",
1131
+ "default": "null",
1132
+ "description": "In multiple mode, render only the first N selected chips, then a +{count} overflow indicator. null means no cap."
1133
+ },
1134
+ {
1135
+ "name": "chipOverflow",
1136
+ "type": "'wrap' | 'ellipsis'",
1137
+ "default": "'wrap'",
1138
+ "description": "How selected chips behave when they exceed the trigger width: wrap flows onto multiple lines; ellipsis keeps a single line and truncates."
1139
+ },
1140
+ {
1141
+ "name": "placeholder",
1142
+ "type": "string",
1143
+ "default": "'Select an option'",
1144
+ "description": "Input placeholder."
1145
+ },
1146
+ {
1147
+ "name": "loading",
1148
+ "type": "boolean",
1149
+ "default": "false",
1150
+ "description": "Input spinner; filtered list returns empty and the empty state is suppressed."
1151
+ },
1152
+ {
1153
+ "name": "invalid",
1154
+ "type": "boolean",
1155
+ "default": "false",
1156
+ "description": "Root invalid class."
1157
+ },
1158
+ {
1159
+ "name": "disabled",
1160
+ "type": "boolean",
1161
+ "default": "false",
1162
+ "description": "Disables the combobox."
1163
+ },
1164
+ {
1165
+ "name": "textDirection",
1166
+ "type": "'toRight' | 'toLeft'",
1167
+ "default": "'toRight'",
1168
+ "description": "Maps to the primitive's dir (ltr / rtl)."
1169
+ },
1170
+ {
1171
+ "name": "multiple",
1172
+ "type": "boolean",
1173
+ "default": "false",
1174
+ "description": "Multi-select; chips in the anchor."
1175
+ },
1176
+ {
1177
+ "name": "showClear",
1178
+ "type": "boolean",
1179
+ "default": "true",
1180
+ "description": "Clear control shown when a value is selected."
1181
+ },
1182
+ {
1183
+ "name": "localCompare",
1184
+ "type": "boolean",
1185
+ "default": "true",
1186
+ "description": "true filters on the client; false uses the parent-owned options."
1187
+ },
1188
+ {
1189
+ "name": "debounceMilliseconds",
1190
+ "type": "number",
1191
+ "default": "300",
1192
+ "description": "Debounce for search-keyword (TimerClerk)."
1193
+ },
1194
+ {
1195
+ "name": "openOnClick",
1196
+ "type": "boolean",
1197
+ "default": "true",
1198
+ "description": "Passed through to the root."
1199
+ },
1200
+ {
1201
+ "name": "showSelectAll",
1202
+ "type": "boolean",
1203
+ "default": "false",
1204
+ "description": "Multi only; sentinel select-all row."
1205
+ },
1206
+ {
1207
+ "name": "selectAllText",
1208
+ "type": "string",
1209
+ "default": "'Select All'",
1210
+ "description": "Select-all row label."
1211
+ },
1212
+ {
1213
+ "name": "emptyText",
1214
+ "type": "string",
1215
+ "default": "'No options.'",
1216
+ "description": "Default empty-slot copy."
1217
+ },
1218
+ {
1219
+ "name": "creatable",
1220
+ "type": "boolean",
1221
+ "default": "false",
1222
+ "description": "Show a create row when the trimmed keyword has no exact label/value match."
1223
+ },
1224
+ {
1225
+ "name": "createOptionText",
1226
+ "type": "string",
1227
+ "default": "'Create \"{keyword}\"'",
1228
+ "description": "Create-row text template; {keyword} is replaced with the trimmed keyword."
1229
+ },
1230
+ {
1231
+ "name": "searchKeyword",
1232
+ "type": "string",
1233
+ "default": "—",
1234
+ "description": "Partial: parent to internal input via watch; no update:search-keyword."
1235
+ },
1236
+ {
1237
+ "name": "open",
1238
+ "type": "boolean",
1239
+ "default": "—",
1240
+ "description": "Not implemented; the template open uses the internal popover ref."
1241
+ }
1242
+ ],
1243
+ "events": [
1244
+ {
1245
+ "name": "change-value",
1246
+ "payload": "AutocompleteEmitPayload",
1247
+ "description": "Select option, select-all, clear, or chip remove."
1248
+ },
1249
+ {
1250
+ "name": "update:value",
1251
+ "payload": "Option object, array, or null",
1252
+ "description": "Same gesture as change-value; suitable for v-model:value."
1253
+ },
1254
+ {
1255
+ "name": "search-keyword",
1256
+ "payload": "string",
1257
+ "description": "After debounce while the popover is open; also '' on clear."
1258
+ },
1259
+ {
1260
+ "name": "create-option",
1261
+ "payload": "AutocompleteEmitPayload",
1262
+ "description": "Select the create row (creatable); read the typed value via extractTrimmedSearchKeyword()."
1263
+ }
1264
+ ],
1265
+ "slots": [
1266
+ {
1267
+ "name": "trigger-left",
1268
+ "scopedProps": "—",
1269
+ "description": "Optional leading anchor content."
1270
+ },
1271
+ {
1272
+ "name": "trigger-right",
1273
+ "scopedProps": "—",
1274
+ "description": "Caret icon inside the trigger part."
1275
+ },
1276
+ {
1277
+ "name": "select-all",
1278
+ "scopedProps": "—",
1279
+ "description": "Select-all label text (scoped checked / indeterminate / disabled not wired)."
1280
+ },
1281
+ {
1282
+ "name": "group",
1283
+ "scopedProps": "{ group, groupIndex }",
1284
+ "description": "Group and its children."
1285
+ },
1286
+ {
1287
+ "name": "group-label",
1288
+ "scopedProps": "{ group, groupIndex }",
1289
+ "description": "Group header text."
1290
+ },
1291
+ {
1292
+ "name": "option",
1293
+ "scopedProps": "{ option, optionIndex, group?, groupIndex? }",
1294
+ "description": "Row and indicator."
1295
+ },
1296
+ {
1297
+ "name": "option-text",
1298
+ "scopedProps": "{ option, optionIndex }",
1299
+ "description": "Label text."
1300
+ },
1301
+ {
1302
+ "name": "empty",
1303
+ "scopedProps": "{ searchKeyword, loading }",
1304
+ "description": "Shown when the filtered list is empty and not loading; defaults to emptyText."
1305
+ },
1306
+ {
1307
+ "name": "loading",
1308
+ "scopedProps": "{ searchKeyword }",
1309
+ "description": "Spinner shown in the list."
1310
+ },
1311
+ {
1312
+ "name": "create-option",
1313
+ "scopedProps": "{ searchKeyword }",
1314
+ "description": "createOptionText with {keyword} replaced; shown only when creatable and no exact match."
1315
+ }
1316
+ ],
1317
+ "features": [
1318
+ "Single and multi-select with groups, separators, and per-option icons; the model stores full leaf option objects, not bare values.",
1319
+ "optionLabel / optionValue map arbitrary option shapes (e.g. { id, name }) to the display / filter label and the emitted model value.",
1320
+ "maxVisibleChips + chipOverflow cap and lay out selected chips in multiple mode (wrap onto lines or ellipsis on one line).",
1321
+ "Client-side filter via localCompare, or parent-owned options (localCompare: false) for API-driven lists.",
1322
+ "Debounced search-keyword emit (default 300ms) using TimerClerk, fired only while the popover is open.",
1323
+ "Loading, invalid, disabled, and multiple states drive the trigger UI and visible list.",
1324
+ "Creatable rows surface a create option when the trimmed keyword has no exact match; the parent owns appending it.",
1325
+ "Rich slot surface for trigger, group, option, indicator, separator, empty, loading, and create-option states."
1326
+ ]
1327
+ },
1328
+ {
1329
+ "slug": "avatar-group",
1330
+ "name": "FuroAvatarGroup",
1331
+ "layer": "molecule",
1332
+ "summary": "Row of overlapping people that collapses past a configurable count.",
1333
+ "import": "import { FuroAvatarGroup } from '@openreachtech/furo-vue'",
1334
+ "docs": "docs/furo-avatar-group.md",
1335
+ "props": [
1336
+ {
1337
+ "name": "parcel",
1338
+ "type": "FuroAvatarGroupParcel | null",
1339
+ "default": "null",
1340
+ "description": "Furo behavior object. The only public prop; HTML attributes pass through."
1341
+ }
1342
+ ],
1343
+ "parcel": [
1344
+ {
1345
+ "name": "avatars",
1346
+ "type": "Array<FuroAvatarGroupEntry>",
1347
+ "default": "[]",
1348
+ "description": "The people, in the order they render."
1349
+ },
1350
+ {
1351
+ "name": "maxVisibleAvatars",
1352
+ "type": "number",
1353
+ "default": "5",
1354
+ "description": "How many render before the rest become a count. Values below one are raised to one."
1355
+ },
1356
+ {
1357
+ "name": "spacing",
1358
+ "type": "'wide' | 'narrow'",
1359
+ "default": "'wide'",
1360
+ "description": "How far the avatars overlap: eight pixels for wide, twelve for narrow."
1361
+ },
1362
+ {
1363
+ "name": "size",
1364
+ "type": "string",
1365
+ "default": "'1.5rem'",
1366
+ "description": "Diameter of one avatar, fed to --furo-avatar-group-size."
1367
+ }
1368
+ ],
1369
+ "events": [],
1370
+ "slots": [
1371
+ {
1372
+ "name": "overflow",
1373
+ "scopedProps": "{ avatars, count }",
1374
+ "description": "Replaces the count, receiving the hidden entries and how many there are. Default: +N."
1375
+ }
1376
+ ],
1377
+ "features": [
1378
+ "Public SFC prop is parcel only; HTML attributes pass through to the root.",
1379
+ "Purely presentational: it carries no value and emits nothing.",
1380
+ "Renders up to maxVisibleAvatars people and turns the rest into one count.",
1381
+ "Two spacings, wide and narrow, matching the two overlaps the design draws.",
1382
+ "Every avatar is pinned to a circle, because overlapping squares read as a stack of cards.",
1383
+ "Each avatar carries a ring so an overlap still reads as two people rather than one clipped shape.",
1384
+ "The overflow slot receives both the hidden entries and their count."
1385
+ ]
1386
+ },
1387
+ {
1388
+ "slug": "breadcrumb",
1389
+ "name": "FuroBreadcrumb",
1390
+ "layer": "molecule",
1391
+ "summary": "Trail showing where a record sits, with a collapsed form for deep trees.",
1392
+ "import": "import { FuroBreadcrumb } from '@openreachtech/furo-vue'",
1393
+ "docs": "docs/furo-breadcrumb.md",
1394
+ "props": [
1395
+ {
1396
+ "name": "parcel",
1397
+ "type": "FuroBreadcrumbParcel | null",
1398
+ "default": "null",
1399
+ "description": "Furo behavior object. The only public prop; HTML attributes pass through."
1400
+ }
1401
+ ],
1402
+ "parcel": [
1403
+ {
1404
+ "name": "items",
1405
+ "type": "Array<FuroBreadcrumbItem>",
1406
+ "default": "[]",
1407
+ "description": "The trail, root first. The last entry is the current one."
1408
+ },
1409
+ {
1410
+ "name": "maxVisibleItems",
1411
+ "type": "number",
1412
+ "default": "4",
1413
+ "description": "How many entries show before the trail collapses. Values below two are raised to two."
1414
+ }
1415
+ ],
1416
+ "events": [],
1417
+ "slots": [
1418
+ {
1419
+ "name": "crumb",
1420
+ "scopedProps": "{ crumb }",
1421
+ "description": "Replaces one entry, for a router link or an icon. Default: the entry label."
1422
+ },
1423
+ {
1424
+ "name": "overflow",
1425
+ "scopedProps": "{ items }",
1426
+ "description": "Replaces the overflow marker, receiving the entries it stands for. Default: an ellipsis icon."
1427
+ },
1428
+ {
1429
+ "name": "separator",
1430
+ "scopedProps": "—",
1431
+ "description": "Replaces the mark between entries. Default: a right caret icon."
1432
+ }
1433
+ ],
1434
+ "features": [
1435
+ "Public SFC prop is parcel only; HTML attributes pass through to the nav root.",
1436
+ "Purely presentational: it carries no value and emits nothing.",
1437
+ "The last entry is the current one, by position rather than by a flag.",
1438
+ "The current entry renders as text even when it carries a destination, and is announced with aria-current=\"page\".",
1439
+ "A trail deeper than maxVisibleItems collapses to the root, an overflow marker, and the tail.",
1440
+ "The overflow slot receives the entries the marker stands for, so a menu can hang off it.",
1441
+ "An entry marked disabled renders as text and is announced with aria-disabled."
1442
+ ]
1443
+ },
1444
+ {
1445
+ "slug": "search-field",
1446
+ "name": "FuroSearchField",
1447
+ "layer": "molecule",
1448
+ "summary": "Single-line search entry point with a leading magnifier and the shared field contract.",
1449
+ "import": "import { FuroSearchField } from '@openreachtech/furo-vue'",
1450
+ "docs": "docs/furo-search-field.md",
1451
+ "props": [
1452
+ {
1453
+ "name": "parcel",
1454
+ "type": "FuroSearchFieldParcel | null",
1455
+ "default": "null",
1456
+ "description": "Furo behavior object. The only public prop; HTML attributes pass through to the inner input."
1457
+ }
1458
+ ],
1459
+ "parcel": [
1460
+ {
1461
+ "name": "value",
1462
+ "type": "string | number | null",
1463
+ "default": "null",
1464
+ "description": "The search text."
1465
+ },
1466
+ {
1467
+ "name": "invalid",
1468
+ "type": "boolean",
1469
+ "default": "false",
1470
+ "description": "Draws the field in its error tone."
1471
+ }
1472
+ ],
1473
+ "events": [
1474
+ {
1475
+ "name": "change-value",
1476
+ "payload": "SearchFieldPayload",
1477
+ "description": "Fires on every keystroke."
1478
+ },
1479
+ {
1480
+ "name": "commit-value",
1481
+ "payload": "SearchFieldPayload",
1482
+ "description": "Fires on blur and on Enter."
1483
+ },
1484
+ {
1485
+ "name": "update:value",
1486
+ "payload": "string | null",
1487
+ "description": "Rides alongside both of the above, which is what makes v-model:value work."
1488
+ }
1489
+ ],
1490
+ "slots": [
1491
+ {
1492
+ "name": "icon",
1493
+ "scopedProps": "—",
1494
+ "description": "Replaces the leading mark. Default: a magnifier icon."
1495
+ },
1496
+ {
1497
+ "name": "trailing",
1498
+ "scopedProps": "—",
1499
+ "description": "Content after the control, for a clear button, a shortcut hint, or a result count."
1500
+ }
1501
+ ],
1502
+ "features": [
1503
+ "Public SFC prop is parcel only, with the same value and invalid keys as FuroTextField.",
1504
+ "class and style land on the wrapper; every other HTML attribute reaches the inner input.",
1505
+ "Emits change-value on every keystroke and commit-value on blur and Enter, both with the field payload.",
1506
+ "update:value rides alongside both, so v-model:value works without a handler.",
1507
+ "Composes FuroTextField and FuroIcon rather than restyling an input.",
1508
+ "The trailing slot takes a clear button, a shortcut hint, or a result count.",
1509
+ "The magnifier is aria-hidden, so it is not announced."
1510
+ ]
1511
+ },
1512
+ {
1513
+ "slug": "section-header",
1514
+ "name": "FuroSectionHeader",
1515
+ "layer": "molecule",
1516
+ "summary": "Named boundary between the groups of a long form or a detail panel.",
1517
+ "import": "import { FuroSectionHeader } from '@openreachtech/furo-vue'",
1518
+ "docs": "docs/furo-section-header.md",
1519
+ "props": [
1520
+ {
1521
+ "name": "parcel",
1522
+ "type": "FuroSectionHeaderParcel | null",
1523
+ "default": "null",
1524
+ "description": "Furo behavior object. The only public prop; HTML attributes pass through."
1525
+ }
1526
+ ],
1527
+ "parcel": [
1528
+ {
1529
+ "name": "title",
1530
+ "type": "string",
1531
+ "default": "''",
1532
+ "description": "Text the heading renders."
1533
+ },
1534
+ {
1535
+ "name": "headingLevel",
1536
+ "type": "number",
1537
+ "default": "2",
1538
+ "description": "Depth of the heading in the consumer's document outline. Clamped to one through six."
1539
+ },
1540
+ {
1541
+ "name": "size",
1542
+ "type": "'large' | 'medium'",
1543
+ "default": "'large'",
1544
+ "description": "Type step the title renders at."
1545
+ },
1546
+ {
1547
+ "name": "divided",
1548
+ "type": "boolean",
1549
+ "default": "true",
1550
+ "description": "Whether a rule closes the header off from what follows it."
1551
+ }
1552
+ ],
1553
+ "events": [],
1554
+ "slots": [
1555
+ {
1556
+ "name": "leading",
1557
+ "scopedProps": "—",
1558
+ "description": "Content before the heading, for example a back control."
1559
+ },
1560
+ {
1561
+ "name": "title",
1562
+ "scopedProps": "—",
1563
+ "description": "Replaces the heading's text. Default: parcel.title."
1564
+ },
1565
+ {
1566
+ "name": "actions",
1567
+ "scopedProps": "—",
1568
+ "description": "The trailing region. Dropped entirely when the slot is empty."
1569
+ }
1570
+ ],
1571
+ "features": [
1572
+ "Public SFC prop is parcel only; HTML attributes pass through to the root.",
1573
+ "Purely presentational: it carries no value and emits nothing.",
1574
+ "The title renders as a real h1 to h6, chosen by headingLevel, never as a styled div.",
1575
+ "Levels outside one to six are clamped to the nearest level HTML defines.",
1576
+ "The rule is FuroSeparator across the block-end edge, not a border, so every rule in the library is the same object.",
1577
+ "The rule is decorative: the heading already tells a screen reader where the boundary is.",
1578
+ "Two type steps, large and medium, matching the two the design draws.",
1579
+ "The trailing region is a slot and is dropped entirely when it is empty."
1580
+ ]
1581
+ },
1582
+ {
1583
+ "slug": "select",
1584
+ "name": "FuroSelect",
1585
+ "layer": "molecule",
1586
+ "summary": "Select molecule with grouped options, multi-select, and rich slots.",
1587
+ "import": "import { FuroSelect } from '@openreachtech/furo-vue'",
1588
+ "docs": "docs/furo-select.md",
1589
+ "props": [
1590
+ {
1591
+ "name": "parcel",
1592
+ "type": "object | null",
1593
+ "default": "null",
1594
+ "description": "Root behavior and Furo fields."
1595
+ },
1596
+ {
1597
+ "name": "triggerParcel",
1598
+ "type": "object | null",
1599
+ "default": "null",
1600
+ "description": "Extra attributes applied to the trigger part."
1601
+ },
1602
+ {
1603
+ "name": "portalParcel",
1604
+ "type": "object | null",
1605
+ "default": "null",
1606
+ "description": "Extra attributes applied to the portal part."
1607
+ },
1608
+ {
1609
+ "name": "contentParcel",
1610
+ "type": "object | null",
1611
+ "default": "null",
1612
+ "description": "Extra attributes applied to the content part (side-offset defaults to 4)."
1613
+ }
1614
+ ],
1615
+ "parcel": [
1616
+ {
1617
+ "name": "value",
1618
+ "type": "string | number | object | null",
1619
+ "default": "null",
1620
+ "description": "Controlled value; an array when multiple. Objects are supported."
1621
+ },
1622
+ {
1623
+ "name": "defaultValue",
1624
+ "type": "same as value",
1625
+ "default": "—",
1626
+ "description": "Uncontrolled initial value."
1627
+ },
1628
+ {
1629
+ "name": "options",
1630
+ "type": "Array<FuroSelectOption>",
1631
+ "default": "[]",
1632
+ "description": "Unified list of groups and leaf rows."
1633
+ },
1634
+ {
1635
+ "name": "optionLabel",
1636
+ "type": "string | ((option) => string)",
1637
+ "default": "uses option.label",
1638
+ "description": "Key name or function that selects each option's display label. When unset, the option's own label is used."
1639
+ },
1640
+ {
1641
+ "name": "optionValue",
1642
+ "type": "string | ((option) => value)",
1643
+ "default": "uses option.value",
1644
+ "description": "Key name or function that selects each option's model value — what update:value emits and what the bound value matches against. When unset, the option's own value (a primitive) is used."
1645
+ },
1646
+ {
1647
+ "name": "invalid",
1648
+ "type": "boolean",
1649
+ "default": "false",
1650
+ "description": "Invalid visual state plus aria-invalid on the trigger."
1651
+ },
1652
+ {
1653
+ "name": "loading",
1654
+ "type": "boolean",
1655
+ "default": "false",
1656
+ "description": "Loading state on the trigger; suppresses the empty row."
1657
+ },
1658
+ {
1659
+ "name": "placeholder",
1660
+ "type": "string",
1661
+ "default": "''",
1662
+ "description": "Placeholder shown in the value display."
1663
+ },
1664
+ {
1665
+ "name": "textDirection",
1666
+ "type": "'toRight' | 'toLeft'",
1667
+ "default": "'toRight'",
1668
+ "description": "Maps to the root dir (ltr / rtl)."
1669
+ },
1670
+ {
1671
+ "name": "multiple",
1672
+ "type": "boolean",
1673
+ "default": "false",
1674
+ "description": "Enables multi-select on the root."
1675
+ },
1676
+ {
1677
+ "name": "disabled",
1678
+ "type": "boolean",
1679
+ "default": "false",
1680
+ "description": "Disables the whole control; may also be set as a fallthrough attribute."
1681
+ }
1682
+ ],
1683
+ "events": [
1684
+ {
1685
+ "name": "change-value",
1686
+ "payload": "SelectEmitPayload",
1687
+ "description": "Fired on selection."
1688
+ },
1689
+ {
1690
+ "name": "commit-value",
1691
+ "payload": "SelectEmitPayload",
1692
+ "description": "Same gesture as change-value; selection is the commit point."
1693
+ },
1694
+ {
1695
+ "name": "update:value",
1696
+ "payload": "value | Array<value> | null",
1697
+ "description": "A single value in single mode; the full array of selected values in multiple mode. Values reflect optionValue when set."
1698
+ }
1699
+ ],
1700
+ "slots": [
1701
+ {
1702
+ "name": "trigger-content",
1703
+ "scopedProps": "—",
1704
+ "description": "Value display and trigger icon area."
1705
+ },
1706
+ {
1707
+ "name": "group",
1708
+ "scopedProps": "{ group, groupIndex }",
1709
+ "description": "Group label and its child options."
1710
+ },
1711
+ {
1712
+ "name": "option",
1713
+ "scopedProps": "{ option, optionIndex, group?, groupIndex? }",
1714
+ "description": "Option row text and indicator."
1715
+ },
1716
+ {
1717
+ "name": "empty",
1718
+ "scopedProps": "—",
1719
+ "description": "Shown when options is empty and not loading. Default text: No options."
1720
+ }
1721
+ ],
1722
+ "features": [
1723
+ "Single unified options array renders both group headers and leaf rows.",
1724
+ "Controlled via parcel.value or v-model:value, or uncontrolled via parcel.defaultValue.",
1725
+ "Multiple selection through parcel.multiple: update:value emits the full array of selected values and the selection persists across re-open.",
1726
+ "optionLabel / optionValue map arbitrary option shapes (e.g. { id, name }) to the display label and model value.",
1727
+ "Object option values resolve their option by deep equality in the context.",
1728
+ "Loading and invalid states drive the trigger UI and aria-invalid.",
1729
+ "Selection is the commit point, so change-value and commit-value fire together.",
1730
+ "Rich slot surface for trigger, group, option, indicator, separator, and empty states."
1731
+ ]
1732
+ },
1733
+ {
1734
+ "slug": "date-picker",
1735
+ "name": "FuroDatePicker",
1736
+ "layer": "molecule",
1737
+ "summary": "Calendar-backed date picker composed from atoms.",
1738
+ "import": "import { FuroDatePicker } from '@openreachtech/furo-vue'",
1739
+ "docs": "docs/furo-date-picker.md",
1740
+ "props": [
1741
+ {
1742
+ "name": "parcel",
1743
+ "type": "DatePickerParcel | null",
1744
+ "default": "null",
1745
+ "description": "Reactive data object. Furo-only keys are stripped before passthrough to the underlying primitive."
1746
+ },
1747
+ {
1748
+ "name": "triggerParcel",
1749
+ "type": "Record<string, unknown> | null",
1750
+ "default": "null",
1751
+ "description": "Passed to the date field / trigger via v-bind."
1752
+ },
1753
+ {
1754
+ "name": "contentParcel",
1755
+ "type": "Record<string, unknown> | null",
1756
+ "default": "null",
1757
+ "description": "Passed to the popover content via v-bind."
1758
+ }
1759
+ ],
1760
+ "parcel": [
1761
+ {
1762
+ "name": "value",
1763
+ "type": "string | null",
1764
+ "default": "—",
1765
+ "description": "Currently selected date as YYYY-MM-DD or null."
1766
+ },
1767
+ {
1768
+ "name": "invalid",
1769
+ "type": "boolean",
1770
+ "default": "—",
1771
+ "description": "Shows error chrome and sets aria-invalid."
1772
+ },
1773
+ {
1774
+ "name": "placeholder",
1775
+ "type": "string | null",
1776
+ "default": "—",
1777
+ "description": "Placeholder text for the date field."
1778
+ },
1779
+ {
1780
+ "name": "disabled",
1781
+ "type": "boolean",
1782
+ "default": "—",
1783
+ "description": "Disables all interaction."
1784
+ },
1785
+ {
1786
+ "name": "minValue",
1787
+ "type": "string | null",
1788
+ "default": "—",
1789
+ "description": "Minimum selectable date (YYYY-MM-DD). Earlier dates are non-interactive."
1790
+ },
1791
+ {
1792
+ "name": "maxValue",
1793
+ "type": "string | null",
1794
+ "default": "—",
1795
+ "description": "Maximum selectable date (YYYY-MM-DD). Later dates are non-interactive."
1796
+ },
1797
+ {
1798
+ "name": "displayFormat",
1799
+ "type": "string | null",
1800
+ "default": "—",
1801
+ "description": "Reserved for v1.1 localized display format (not yet applied)."
1802
+ },
1803
+ {
1804
+ "name": "timezone",
1805
+ "type": "string | null",
1806
+ "default": "null",
1807
+ "description": "IANA timezone identifier. Interprets Date object inputs before normalization; no effect on YYYY-MM-DD strings."
1808
+ },
1809
+ {
1810
+ "name": "closeOnSelect",
1811
+ "type": "boolean | null",
1812
+ "default": "true",
1813
+ "description": "Whether the popover closes when a date is selected."
1814
+ },
1815
+ {
1816
+ "name": "locale",
1817
+ "type": "string | null",
1818
+ "default": "browser locale",
1819
+ "description": "Drives the date field's segment order; falls back to 'en' outside the browser."
1820
+ },
1821
+ {
1822
+ "name": "preventDeselect",
1823
+ "type": "boolean | null",
1824
+ "default": "true",
1825
+ "description": "When true, re-selecting the selected date keeps it instead of clearing."
1826
+ },
1827
+ {
1828
+ "name": "todayButtonText",
1829
+ "type": "string | null",
1830
+ "default": "'Today'",
1831
+ "description": "Label for the footer Today button; pass null to hide it."
1832
+ },
1833
+ {
1834
+ "name": "clearButtonText",
1835
+ "type": "string | null",
1836
+ "default": "'Clear'",
1837
+ "description": "Label for the footer Clear button; pass null to hide it."
1838
+ }
1839
+ ],
1840
+ "events": [
1841
+ {
1842
+ "name": "change-value",
1843
+ "payload": "DatePickerEmitPayload",
1844
+ "description": "Fired when the user selects a date."
1845
+ },
1846
+ {
1847
+ "name": "commit-value",
1848
+ "payload": "DatePickerEmitPayload",
1849
+ "description": "Fired on the same selection event (single-date close-on-select UX)."
1850
+ },
1851
+ {
1852
+ "name": "update:value",
1853
+ "payload": "string | null",
1854
+ "description": "ISO YYYY-MM-DD string or null. Suitable for v-model:value."
1855
+ }
1856
+ ],
1857
+ "slots": [
1858
+ {
1859
+ "name": "trigger-icon",
1860
+ "scopedProps": "—",
1861
+ "description": "Replaces the default calendar icon inside the trigger."
1862
+ },
1863
+ {
1864
+ "name": "prev-icon",
1865
+ "scopedProps": "—",
1866
+ "description": "Replaces the left-arrow icon in the calendar header."
1867
+ },
1868
+ {
1869
+ "name": "next-icon",
1870
+ "scopedProps": "—",
1871
+ "description": "Replaces the right-arrow icon in the calendar header."
1872
+ },
1873
+ {
1874
+ "name": "field-suffix",
1875
+ "scopedProps": "—",
1876
+ "description": "Custom content inside the trigger field, after the segments and before the trigger icon."
1877
+ },
1878
+ {
1879
+ "name": "content-footer",
1880
+ "scopedProps": "—",
1881
+ "description": "Custom content inside the popover, below the calendar."
1882
+ }
1883
+ ],
1884
+ "features": [
1885
+ "Inline date field with month / day / year segments plus a calendar popover.",
1886
+ "Calendar navigation uses month and year dropdown selects alongside Prev / Next buttons.",
1887
+ "Wire format is a YYYY-MM-DD ISO string or null; the context normalizes Date and CalendarDate inputs at the boundary.",
1888
+ "minValue / maxValue bound the selectable range; out-of-range dates are non-interactive.",
1889
+ "Configurable timezone (IANA) interprets Date object inputs on the correct calendar day.",
1890
+ "Footer Today and Clear buttons with overridable labels, plus locale-driven segment order."
1891
+ ]
1892
+ },
1893
+ {
1894
+ "slug": "time-field",
1895
+ "name": "FuroTimeField",
1896
+ "layer": "molecule",
1897
+ "summary": "Segmented time input with locale-aware formatting.",
1898
+ "import": "import { FuroTimeField } from '@openreachtech/furo-vue'",
1899
+ "docs": "docs/furo-time-field.md",
1900
+ "props": [
1901
+ {
1902
+ "name": "parcel",
1903
+ "type": "TimeFieldParcel | null",
1904
+ "default": "null",
1905
+ "description": "Reactive data object. Furo-only keys are stripped before passthrough to the underlying primitive."
1906
+ }
1907
+ ],
1908
+ "parcel": [
1909
+ {
1910
+ "name": "value",
1911
+ "type": "string | null",
1912
+ "default": "—",
1913
+ "description": "Current time as HH:MM:SS (or HH:MM) or null. The context also accepts Date / Time at the boundary."
1914
+ },
1915
+ {
1916
+ "name": "invalid",
1917
+ "type": "boolean",
1918
+ "default": "—",
1919
+ "description": "Forces error chrome and aria-invalid (external validation)."
1920
+ },
1921
+ {
1922
+ "name": "placeholder",
1923
+ "type": "string | null",
1924
+ "default": "—",
1925
+ "description": "Placeholder text for the time field."
1926
+ },
1927
+ {
1928
+ "name": "disabled",
1929
+ "type": "boolean",
1930
+ "default": "—",
1931
+ "description": "Disables all interaction."
1932
+ },
1933
+ {
1934
+ "name": "readonly",
1935
+ "type": "boolean",
1936
+ "default": "—",
1937
+ "description": "Segments are focusable but not editable."
1938
+ },
1939
+ {
1940
+ "name": "minValue",
1941
+ "type": "string | null",
1942
+ "default": "—",
1943
+ "description": "Minimum time (HH:MM:SS). Out-of-range values are flagged, not clamped."
1944
+ },
1945
+ {
1946
+ "name": "maxValue",
1947
+ "type": "string | null",
1948
+ "default": "—",
1949
+ "description": "Maximum time (HH:MM:SS). Out-of-range values are flagged, not clamped."
1950
+ },
1951
+ {
1952
+ "name": "timeFormat",
1953
+ "type": "number | null",
1954
+ "default": "locale default",
1955
+ "description": "12 or 24. When unset, the locale default applies."
1956
+ },
1957
+ {
1958
+ "name": "granularity",
1959
+ "type": "'hour' | 'minute' | 'second' | null",
1960
+ "default": "'minute'",
1961
+ "description": "Controls visible segments."
1962
+ },
1963
+ {
1964
+ "name": "step",
1965
+ "type": "number | null",
1966
+ "default": "1",
1967
+ "description": "Step amount for arrow edits and the buttons; the unit follows granularity. Forwarded as native step."
1968
+ },
1969
+ {
1970
+ "name": "stepSnapping",
1971
+ "type": "boolean | null",
1972
+ "default": "—",
1973
+ "description": "Optional stepSnapping. Forwarded only when explicitly set."
1974
+ },
1975
+ {
1976
+ "name": "timezone",
1977
+ "type": "string | null",
1978
+ "default": "null",
1979
+ "description": "IANA timezone; normalizes Date inputs to wall-clock parts in that zone. Never forwarded to the primitive."
1980
+ },
1981
+ {
1982
+ "name": "decrementLabel",
1983
+ "type": "string",
1984
+ "default": "'Decrement time'",
1985
+ "description": "Accessible name of the decrement button. Set it to translate the control."
1986
+ },
1987
+ {
1988
+ "name": "incrementLabel",
1989
+ "type": "string",
1990
+ "default": "'Increment time'",
1991
+ "description": "Accessible name of the increment button. Set it to translate the control."
1992
+ }
1993
+ ],
1994
+ "events": [
1995
+ {
1996
+ "name": "change-value",
1997
+ "payload": "TimeFieldEmitPayload",
1998
+ "description": "Fired when the user edits a segment."
1999
+ },
2000
+ {
2001
+ "name": "commit-value",
2002
+ "payload": "TimeFieldEmitPayload",
2003
+ "description": "Fired on the same edit event (inline single-region UX)."
2004
+ },
2005
+ {
2006
+ "name": "update:value",
2007
+ "payload": "string | null",
2008
+ "description": "HH:MM:SS string or null. Suitable for v-model:value."
2009
+ }
2010
+ ],
2011
+ "slots": [],
2012
+ "features": [
2013
+ "Inline segmented time control (hour / minute, optionally seconds and AM/PM) edited in place; no popover or portal.",
2014
+ "Wire format is always HH:MM:SS via Time#toString(); HH:MM is accepted on input and padded.",
2015
+ "Granularity (hour / minute / second) and 12 or 24 hour format are configurable via parcel.",
2016
+ "Customizable step drives arrow-key edits and the native increment / decrement buttons, with the unit following granularity.",
2017
+ "minValue / maxValue flag out-of-range entries with aria-invalid; the stepper buttons clamp instead.",
2018
+ "Configurable timezone (IANA) normalizes Date inputs to wall-clock parts in that zone."
2019
+ ]
2020
+ },
2021
+ {
2022
+ "slug": "date-time-picker",
2023
+ "name": "FuroDateTimePicker",
2024
+ "layer": "molecule",
2025
+ "summary": "Composes the date picker and time field into one control.",
2026
+ "import": "import { FuroDateTimePicker } from '@openreachtech/furo-vue'",
2027
+ "docs": "docs/furo-date-time-picker.md",
2028
+ "props": [
2029
+ {
2030
+ "name": "parcel",
2031
+ "type": "DateTimePickerParcel | null",
2032
+ "default": "null",
2033
+ "description": "Reactive data object. Molecule-only keys are consumed here and used to derive the child parcels."
2034
+ }
2035
+ ],
2036
+ "parcel": [
2037
+ {
2038
+ "name": "value",
2039
+ "type": "string | null",
2040
+ "default": "—",
2041
+ "description": "Combined value as YYYY-MM-DDTHH:MM:SS or null. Split into date/time parts and recombined on change."
2042
+ },
2043
+ {
2044
+ "name": "invalid",
2045
+ "type": "boolean",
2046
+ "default": "—",
2047
+ "description": "Shows error chrome and aria-invalid on the unit shell; also forwarded to both atoms."
2048
+ },
2049
+ {
2050
+ "name": "placeholder",
2051
+ "type": "string | null",
2052
+ "default": "—",
2053
+ "description": "Placeholder text for the date field."
2054
+ },
2055
+ {
2056
+ "name": "disabled",
2057
+ "type": "boolean",
2058
+ "default": "—",
2059
+ "description": "Disables all interaction."
2060
+ },
2061
+ {
2062
+ "name": "minValue",
2063
+ "type": "string | null",
2064
+ "default": "—",
2065
+ "description": "Minimum selectable datetime (YYYY-MM-DDTHH:MM:SS). See cross-field rule."
2066
+ },
2067
+ {
2068
+ "name": "maxValue",
2069
+ "type": "string | null",
2070
+ "default": "—",
2071
+ "description": "Maximum selectable datetime (YYYY-MM-DDTHH:MM:SS). See cross-field rule."
2072
+ },
2073
+ {
2074
+ "name": "timezone",
2075
+ "type": "string | null",
2076
+ "default": "null",
2077
+ "description": "IANA timezone identifier forwarded to both atoms."
2078
+ },
2079
+ {
2080
+ "name": "granularity",
2081
+ "type": "'hour' | 'minute' | 'second' | null",
2082
+ "default": "—",
2083
+ "description": "Visible time segments. Does not change the wire format (always second precision)."
2084
+ },
2085
+ {
2086
+ "name": "step",
2087
+ "type": "number | null",
2088
+ "default": "—",
2089
+ "description": "Step amount for the time field's increment / decrement buttons."
2090
+ },
2091
+ {
2092
+ "name": "timeFormat",
2093
+ "type": "number | null",
2094
+ "default": "locale default",
2095
+ "description": "12 or 24. When unset, the locale default applies."
2096
+ }
2097
+ ],
2098
+ "events": [
2099
+ {
2100
+ "name": "change-value",
2101
+ "payload": "DateTimePickerEmitPayload",
2102
+ "description": "Fired when either the date or time part changes."
2103
+ },
2104
+ {
2105
+ "name": "commit-value",
2106
+ "payload": "DateTimePickerEmitPayload",
2107
+ "description": "Fired on the same change event."
2108
+ },
2109
+ {
2110
+ "name": "update:value",
2111
+ "payload": "string | null",
2112
+ "description": "Combined YYYY-MM-DDTHH:MM:SS string. Selecting a date fabricates 12:00:00; null only while no date is set."
2113
+ }
2114
+ ],
2115
+ "slots": [],
2116
+ "features": [
2117
+ "Composes FuroDatePicker and FuroTimeField into a single popover; the calendar stays single-sourced.",
2118
+ "Combined value is a canonical YYYY-MM-DDTHH:MM:SS ISO string or null, always second-precision.",
2119
+ "Selecting a date fabricates a default time of 12:00:00 so a complete value is produced and the popover stays open.",
2120
+ "Cross-field min/max: minimum time applies only on the minimum date, maximum time only on the maximum date.",
2121
+ "Changing the date keeps the current time part and vice versa (preserve-on-change).",
2122
+ "A directly editable inline time field in the trigger stays in sync with the footer time field."
2123
+ ]
2124
+ },
2125
+ {
2126
+ "slug": "dropdown-menu",
2127
+ "name": "FuroDropdownMenu",
2128
+ "layer": "molecule",
2129
+ "summary": "Trigger plus floating menu with items, separators, and keyboard support.",
2130
+ "import": "import { FuroDropdownMenu } from '@openreachtech/furo-vue'",
2131
+ "docs": "docs/furo-dropdown-menu.md",
2132
+ "props": [
2133
+ {
2134
+ "name": "parcel",
2135
+ "type": "FuroDropdownMenuParcel | null",
2136
+ "default": "null",
2137
+ "description": "Menu behavior and declarative rows."
2138
+ },
2139
+ {
2140
+ "name": "triggerParcel",
2141
+ "type": "object | null",
2142
+ "default": "null",
2143
+ "description": "Default trigger appearance tokens (variant, size) aligned with FuroButton. Set triggerParcel.asChild: true to make the #trigger slot element the trigger itself (no wrapper button, no forced .unit-button styling); default false renders the styled native button."
2144
+ }
2145
+ ],
2146
+ "parcel": [
2147
+ {
2148
+ "name": "open",
2149
+ "type": "boolean",
2150
+ "default": "uncontrolled",
2151
+ "description": "Controlled open state; omit for internal state."
2152
+ },
2153
+ {
2154
+ "name": "disabled",
2155
+ "type": "boolean",
2156
+ "default": "false",
2157
+ "description": "Disables trigger and menu."
2158
+ },
2159
+ {
2160
+ "name": "side",
2161
+ "type": "'top' | 'right' | 'bottom' | 'left'",
2162
+ "default": "'bottom'",
2163
+ "description": "Which edge of the trigger the menu opens against."
2164
+ },
2165
+ {
2166
+ "name": "align",
2167
+ "type": "'start' | 'center' | 'end'",
2168
+ "default": "'start'",
2169
+ "description": "How the menu aligns along that edge."
2170
+ },
2171
+ {
2172
+ "name": "sideOffset",
2173
+ "type": "number",
2174
+ "default": "4",
2175
+ "description": "Gap between trigger and menu, in rem-equivalent pixels."
2176
+ },
2177
+ {
2178
+ "name": "options",
2179
+ "type": "Array<FuroDropdownMenuOption>",
2180
+ "default": "[]",
2181
+ "description": "Declarative menu rows."
2182
+ }
2183
+ ],
2184
+ "events": [
2185
+ {
2186
+ "name": "open:change",
2187
+ "payload": "{ open: boolean }",
2188
+ "description": "Menu open state changes."
2189
+ },
2190
+ {
2191
+ "name": "option:select",
2192
+ "payload": "DropdownMenuOptionSelectEmitPayload",
2193
+ "description": "User selects an enabled action row."
2194
+ },
2195
+ {
2196
+ "name": "option:checked-change",
2197
+ "payload": "{ option: FuroDropdownMenuOption, checked: boolean }",
2198
+ "description": "User toggles a checkbox row."
2199
+ }
2200
+ ],
2201
+ "slots": [
2202
+ {
2203
+ "name": "trigger",
2204
+ "scopedProps": "—",
2205
+ "description": "Native button labeled \"Menu\" (FuroButton-compatible styling). Override with label content."
2206
+ },
2207
+ {
2208
+ "name": "option-label",
2209
+ "scopedProps": "{ option, index }",
2210
+ "description": "Override row label rendering. Defaults to option.label text."
2211
+ },
2212
+ {
2213
+ "name": "default",
2214
+ "scopedProps": "—",
2215
+ "description": "Append custom menu content (advanced)."
2216
+ }
2217
+ ],
2218
+ "features": [
2219
+ "Declarative options array renders action, checkbox, submenu, and separator rows.",
2220
+ "Row kind resolves by priority: separator, then submenu, then checkbox, then default action.",
2221
+ "Action rows close the menu unless keepOpen is set; checkbox rows keep the menu open on toggle.",
2222
+ "No v-model: the menu emits selection and checkbox events, and the parent owns persistent checked state.",
2223
+ "triggerParcel tunes the default native trigger appearance (variant, size) aligned with FuroButton.",
2224
+ "triggerParcel.asChild lets the #trigger slot element become the trigger itself, with no wrapper button or forced .unit-button styling.",
2225
+ "Custom trigger slot accepts label content (text, icons) without nesting another button."
2226
+ ]
2227
+ },
2228
+ {
2229
+ "slug": "editable-field",
2230
+ "name": "FuroEditableField",
2231
+ "layer": "molecule",
2232
+ "summary": "Inline read-to-edit field with commit and cancel handling.",
2233
+ "import": "import { FuroEditableField } from '@openreachtech/furo-vue'",
2234
+ "docs": "docs/furo-editable-field.md",
2235
+ "props": [
2236
+ {
2237
+ "name": "parcel",
2238
+ "type": "FuroEditableFieldParcel | null",
2239
+ "default": "null",
2240
+ "description": "Furo behavior and forwarded edit-lifecycle keys. The only public prop; attributes pass through."
2241
+ }
2242
+ ],
2243
+ "parcel": [
2244
+ {
2245
+ "name": "value",
2246
+ "type": "FuroEditableValue",
2247
+ "default": "—",
2248
+ "description": "Committed value. The parent should update this after commit-value."
2249
+ },
2250
+ {
2251
+ "name": "invalid",
2252
+ "type": "boolean",
2253
+ "default": "false",
2254
+ "description": "Passed to the default FuroTextField; use #editor for custom invalid UI."
2255
+ },
2256
+ {
2257
+ "name": "disabled",
2258
+ "type": "boolean",
2259
+ "default": "false",
2260
+ "description": "Also respected from the fallthrough disabled attribute."
2261
+ },
2262
+ {
2263
+ "name": "required",
2264
+ "type": "boolean",
2265
+ "default": "false",
2266
+ "description": "Also respected from the fallthrough required attribute."
2267
+ },
2268
+ {
2269
+ "name": "readonly",
2270
+ "type": "boolean",
2271
+ "default": "false",
2272
+ "description": "Forwarded to the root."
2273
+ },
2274
+ {
2275
+ "name": "placeholder",
2276
+ "type": "string | { edit: string, preview: string }",
2277
+ "default": "fallthrough or empty",
2278
+ "description": "Default text editor placeholder."
2279
+ },
2280
+ {
2281
+ "name": "emptyPreviewText",
2282
+ "type": "string",
2283
+ "default": "'---'",
2284
+ "description": "Shown when the value is empty and no #preview slot is provided."
2285
+ },
2286
+ {
2287
+ "name": "showActions",
2288
+ "type": "boolean",
2289
+ "default": "false",
2290
+ "description": "Show the Edit trigger and enable the action-button row."
2291
+ },
2292
+ {
2293
+ "name": "showEditing",
2294
+ "type": "boolean",
2295
+ "default": "false",
2296
+ "description": "On mount, sets the internal editing flag used for editor positioning."
2297
+ },
2298
+ {
2299
+ "name": "showUndoChange",
2300
+ "type": "boolean",
2301
+ "default": "false",
2302
+ "description": "Show the undo control when the committed value diverges from the mount snapshot."
2303
+ },
2304
+ {
2305
+ "name": "collisionBoundary",
2306
+ "type": "HTMLElement | Ref<HTMLElement | null> | null",
2307
+ "default": "—",
2308
+ "description": "Bounding rect for editor collision; the viewport is used when omitted."
2309
+ },
2310
+ {
2311
+ "name": "activationMode",
2312
+ "type": "'dblclick' | 'focus' | 'none'",
2313
+ "default": "—",
2314
+ "description": "Primitive-forwarded: how the preview enters edit mode."
2315
+ },
2316
+ {
2317
+ "name": "submitMode",
2318
+ "type": "'blur' | 'enter' | 'both' | 'none'",
2319
+ "default": "—",
2320
+ "description": "Primitive-forwarded: when the primitive auto-submits the draft."
2321
+ },
2322
+ {
2323
+ "name": "editLabel",
2324
+ "type": "string",
2325
+ "default": "'Edit'",
2326
+ "description": "Accessible name of the edit trigger. Set it to translate the control."
2327
+ },
2328
+ {
2329
+ "name": "undoLabel",
2330
+ "type": "string",
2331
+ "default": "'Undo'",
2332
+ "description": "Accessible name of the undo control. Set it to translate the control."
2333
+ },
2334
+ {
2335
+ "name": "submitLabel",
2336
+ "type": "string",
2337
+ "default": "'Submit'",
2338
+ "description": "Accessible name of the submit control. Set it to translate the control."
2339
+ },
2340
+ {
2341
+ "name": "cancelLabel",
2342
+ "type": "string",
2343
+ "default": "'Cancel'",
2344
+ "description": "Accessible name of the cancel control. Set it to translate the control."
2345
+ }
2346
+ ],
2347
+ "events": [
2348
+ {
2349
+ "name": "commit-value",
2350
+ "payload": "EditableEmitPayload",
2351
+ "description": "On successful submit and on undo. $event.value is the committed value."
2352
+ },
2353
+ {
2354
+ "name": "update-editing-state",
2355
+ "payload": "EdittingState",
2356
+ "description": "The editing lifecycle state: 'edit', 'cancel', or 'submit'."
2357
+ }
2358
+ ],
2359
+ "slots": [
2360
+ {
2361
+ "name": "preview",
2362
+ "scopedProps": "root props + committedValue, draftValue, updateDraftValue, undoChange",
2363
+ "description": "Used when the value is not empty; overrides the default preview text."
2364
+ },
2365
+ {
2366
+ "name": "editor",
2367
+ "scopedProps": "same as preview",
2368
+ "description": "Replaces the default FuroTextField; hosts custom atoms."
2369
+ },
2370
+ {
2371
+ "name": "edit-trigger",
2372
+ "scopedProps": "same as preview",
2373
+ "description": "Custom edit trigger (as-child when provided)."
2374
+ },
2375
+ {
2376
+ "name": "submit-trigger",
2377
+ "scopedProps": "same as preview",
2378
+ "description": "Inside the editor actions; visible while editing."
2379
+ },
2380
+ {
2381
+ "name": "cancel-trigger",
2382
+ "scopedProps": "same as preview",
2383
+ "description": "Inside the editor actions; visible while editing."
2384
+ },
2385
+ {
2386
+ "name": "undo-trigger",
2387
+ "scopedProps": "same as preview",
2388
+ "description": "Shown when showUndoChange and the value changed since mount."
2389
+ }
2390
+ ],
2391
+ "features": [
2392
+ "Inline read-to-edit field: a preview surface that opens an editor on activation and commits the draft.",
2393
+ "No v-model:value: the parent owns parcel.value and updates it on commit-value.",
2394
+ "Default text editor (FuroTextField) when #editor is omitted; #editor hosts number, select, checkbox, file, and other controls.",
2395
+ "Furo-owned keys (invalid, disabled, required, placeholder, showActions, showUndoChange) plus primitive-forwarded edit lifecycle keys.",
2396
+ "Undo control restores the value committed at mount when showUndoChange is set.",
2397
+ "Collision-aware fixed editor panel clamped to a configurable collisionBoundary (e.g. a table element)."
2398
+ ]
2399
+ },
2400
+ {
2401
+ "slug": "control-block",
2402
+ "name": "FuroControlBlock",
2403
+ "layer": "molecule",
2404
+ "summary": "Label, control, hint, and error wrapper for any form atom.",
2405
+ "import": "import { FuroControlBlock } from '@openreachtech/furo-vue'",
2406
+ "docs": "docs/furo-control-block.md",
2407
+ "props": [
2408
+ {
2409
+ "name": "parcel",
2410
+ "type": "ControlBlockParcel | null",
2411
+ "default": "null",
2412
+ "description": "Reactive data object holding the label, control id, error messages, required flag, and orientation."
2413
+ }
2414
+ ],
2415
+ "parcel": [
2416
+ {
2417
+ "name": "label",
2418
+ "type": "string | null",
2419
+ "default": "null",
2420
+ "description": "Label text. When null, no label is rendered."
2421
+ },
2422
+ {
2423
+ "name": "controlId",
2424
+ "type": "string | null",
2425
+ "default": "null",
2426
+ "description": "Id of the slotted control, rendered as label for. When null, the label has no for."
2427
+ },
2428
+ {
2429
+ "name": "errorMessages",
2430
+ "type": "Array<string>",
2431
+ "default": "[]",
2432
+ "description": "Error messages. A non-empty array marks the block invalid and renders one line per message."
2433
+ },
2434
+ {
2435
+ "name": "required",
2436
+ "type": "boolean",
2437
+ "default": "false",
2438
+ "description": "When true, renders a required mark (*) after the label."
2439
+ },
2440
+ {
2441
+ "name": "orientation",
2442
+ "type": "'vertical' | 'horizontal'",
2443
+ "default": "'vertical'",
2444
+ "description": "Layout of label vs control. vertical stacks; horizontal places the label beside the control."
2445
+ }
2446
+ ],
2447
+ "events": [],
2448
+ "slots": [
2449
+ {
2450
+ "name": "default",
2451
+ "scopedProps": "—",
2452
+ "description": "The control to frame. Pass the same id as the parcel controlId so label for resolves."
2453
+ }
2454
+ ],
2455
+ "features": [
2456
+ "Presentational wrapper that frames a single form control with a label and error messages.",
2457
+ "Domain-agnostic: the control is supplied via the default slot, so the block never knows which atom it wraps.",
2458
+ "Emits nothing; the slotted control owns its own change-value / commit-value / update:value events.",
2459
+ "A non-empty errorMessages array marks the block invalid and renders one line per message.",
2460
+ "Required mark (*) renders after the label as a visual cue (aria-hidden).",
2461
+ "Vertical (default) or horizontal orientation via a CSS modifier, with no JS branching.",
2462
+ "A consumer-supplied class and style compose onto the block root, so a layout selector like .control.name { flex: 1 } reaches the wrapper (inheritAttrs: false composes $attrs.class / $attrs.style onto the root)."
2463
+ ]
2464
+ },
2465
+ {
2466
+ "slug": "pagination",
2467
+ "name": "FuroPagination",
2468
+ "layer": "molecule",
2469
+ "summary": "Page navigation with prev / next and numbered page controls.",
2470
+ "import": "import { FuroPagination } from '@openreachtech/furo-vue'",
2471
+ "docs": "docs/furo-pagination.md",
2472
+ "props": [
2473
+ {
2474
+ "name": "parcel",
2475
+ "type": "FuroPaginationParcel | null",
2476
+ "default": "null",
2477
+ "description": "Reactive behavior object."
2478
+ }
2479
+ ],
2480
+ "parcel": [
2481
+ {
2482
+ "name": "page",
2483
+ "type": "number | null",
2484
+ "default": "null",
2485
+ "description": "Controlled current page (1-based). When omitted, the component manages its own page."
2486
+ },
2487
+ {
2488
+ "name": "offset",
2489
+ "type": "number | null",
2490
+ "default": "null",
2491
+ "description": "Controlled current page as a zero-based record offset. The page is derived via floor(offset / limit) + 1. When both page and offset are set, page takes precedence. Provide only one."
2492
+ },
2493
+ {
2494
+ "name": "limit",
2495
+ "type": "number",
2496
+ "default": "20",
2497
+ "description": "Records per page. Combined with totalRecords to compute the page count."
2498
+ },
2499
+ {
2500
+ "name": "totalRecords",
2501
+ "type": "number",
2502
+ "default": "0",
2503
+ "description": "Total record count across all pages."
2504
+ },
2505
+ {
2506
+ "name": "siblingCount",
2507
+ "type": "number",
2508
+ "default": "2",
2509
+ "description": "Pages shown on each side of the current page before collapsing into an ellipsis."
2510
+ },
2511
+ {
2512
+ "name": "showEdges",
2513
+ "type": "boolean",
2514
+ "default": "true",
2515
+ "description": "When true, the first and last pages stay pinned with ellipsis gaps. false renders a plain contiguous range."
2516
+ },
2517
+ {
2518
+ "name": "disabled",
2519
+ "type": "boolean",
2520
+ "default": "false",
2521
+ "description": "Disables the whole control."
2522
+ }
2523
+ ],
2524
+ "events": [
2525
+ {
2526
+ "name": "update:page",
2527
+ "payload": "number",
2528
+ "description": "Selected page changed — enables v-model:page."
2529
+ },
2530
+ {
2531
+ "name": "page:change",
2532
+ "payload": "{ page: number, offset: number, limit: number }",
2533
+ "description": "Selected page changed. offset ((page - 1) * limit) and limit are provided so offset/limit data sources can use the payload directly."
2534
+ }
2535
+ ],
2536
+ "slots": [
2537
+ {
2538
+ "name": "previous",
2539
+ "scopedProps": "—",
2540
+ "description": "Content of the previous-page button (defaults to a left-caret icon)."
2541
+ },
2542
+ {
2543
+ "name": "next",
2544
+ "scopedProps": "—",
2545
+ "description": "Content of the next-page button (defaults to a right-caret icon)."
2546
+ },
2547
+ {
2548
+ "name": "ellipsis",
2549
+ "scopedProps": "—",
2550
+ "description": "Content of the gap marker (defaults to a three-dots icon)."
2551
+ },
2552
+ {
2553
+ "name": "page",
2554
+ "scopedProps": "{ page }",
2555
+ "description": "Custom content for each page entry. Rendered via as-child, so the slot may supply an anchor for SEO — the click still drives page:change."
2556
+ }
2557
+ ],
2558
+ "features": [
2559
+ "Derives the page range, ellipsis gaps, and prev/next bounds from the record count.",
2560
+ "Controlled via parcel.page, by zero-based parcel.offset, or uncontrolled.",
2561
+ "page:change payload carries page, offset, and limit for offset/limit data sources.",
2562
+ "v-model:page through the update:page event.",
2563
+ "page slot renders via as-child, so it can supply an SEO anchor that still drives page:change.",
2564
+ "Domain-agnostic: no GraphQL, router, or Nuxt imports — the consumer wires the emitted page."
2565
+ ]
2566
+ },
2567
+ {
2568
+ "slug": "popover",
2569
+ "name": "FuroPopover",
2570
+ "layer": "molecule",
2571
+ "summary": "Click-triggered overlay for inline edit surfaces and action panels.",
2572
+ "import": "import { FuroPopover } from '@openreachtech/furo-vue'",
2573
+ "docs": "docs/furo-popover.md",
2574
+ "props": [
2575
+ {
2576
+ "name": "parcel",
2577
+ "type": "PopoverParcel | null",
2578
+ "default": "null",
2579
+ "description": "Reactive data object holding positioning, disabled, modal, and optional controlled open state."
2580
+ }
2581
+ ],
2582
+ "parcel": [
2583
+ {
2584
+ "name": "side",
2585
+ "type": "'top' | 'right' | 'bottom' | 'left'",
2586
+ "default": "'bottom'",
2587
+ "description": "Edge of the trigger the content prefers."
2588
+ },
2589
+ {
2590
+ "name": "align",
2591
+ "type": "'start' | 'center' | 'end'",
2592
+ "default": "'center'",
2593
+ "description": "Alignment along the chosen side."
2594
+ },
2595
+ {
2596
+ "name": "sideOffset",
2597
+ "type": "number",
2598
+ "default": "4",
2599
+ "description": "Gap in pixels between trigger and content."
2600
+ },
2601
+ {
2602
+ "name": "disabled",
2603
+ "type": "boolean",
2604
+ "default": "false",
2605
+ "description": "When true, the trigger never opens the popover."
2606
+ },
2607
+ {
2608
+ "name": "modal",
2609
+ "type": "boolean",
2610
+ "default": "false",
2611
+ "description": "When true, focus is trapped and outside interaction is blocked while open."
2612
+ },
2613
+ {
2614
+ "name": "open",
2615
+ "type": "boolean | null",
2616
+ "default": "null",
2617
+ "description": "When set (non-null), open state is controlled by the consumer; otherwise the component manages it internally."
2618
+ }
2619
+ ],
2620
+ "events": [
2621
+ {
2622
+ "name": "open:change",
2623
+ "payload": "{ open: boolean }",
2624
+ "description": "Fired whenever the open state changes (trigger click, outside click, or Escape)."
2625
+ }
2626
+ ],
2627
+ "slots": [
2628
+ {
2629
+ "name": "trigger",
2630
+ "scopedProps": "—",
2631
+ "description": "The element the popover is anchored to. Focusable by default (rendered as a button)."
2632
+ },
2633
+ {
2634
+ "name": "content",
2635
+ "scopedProps": "—",
2636
+ "description": "The popover body. Holds arbitrary interactive content."
2637
+ }
2638
+ ],
2639
+ "features": [
2640
+ "Click-triggered overlay anchored to a trigger element.",
2641
+ "Built on a headless popover primitive handling positioning, focus, and dismissal.",
2642
+ "Holds arbitrary interactive content (inline cell / field edit, action panels).",
2643
+ "Positioning via side / align / sideOffset; the primitive flips to stay in view.",
2644
+ "Defined by a bordered surface and shadow; no pointer arrow, for a consistent card look.",
2645
+ "Optional modal mode traps focus and blocks outside interaction.",
2646
+ "Optional controlled open state through parcel.open; otherwise managed internally.",
2647
+ "Emits open:change whenever the open state changes."
2648
+ ]
2649
+ },
2650
+ {
2651
+ "slug": "separator",
2652
+ "name": "FuroSeparator",
2653
+ "layer": "molecule",
2654
+ "summary": "Horizontal or vertical divider with optional labelling.",
2655
+ "import": "import { FuroSeparator } from '@openreachtech/furo-vue'",
2656
+ "docs": "docs/furo-separator.md",
2657
+ "props": [
2658
+ {
2659
+ "name": "parcel",
2660
+ "type": "SeparatorParcel | null",
2661
+ "default": "null",
2662
+ "description": "Reactive data object holding orientation and the decorative flag."
2663
+ }
2664
+ ],
2665
+ "parcel": [
2666
+ {
2667
+ "name": "orientation",
2668
+ "type": "'horizontal' | 'vertical'",
2669
+ "default": "'horizontal'",
2670
+ "description": "Direction the divider runs. horizontal spans the full inline width; vertical stretches to the parent's height."
2671
+ },
2672
+ {
2673
+ "name": "decorative",
2674
+ "type": "boolean",
2675
+ "default": "false",
2676
+ "description": "When true, the divider is purely visual and drops the separator role so assistive tech ignores it."
2677
+ }
2678
+ ],
2679
+ "events": [],
2680
+ "slots": [],
2681
+ "features": [
2682
+ "Presentational divider drawn between sibling content — toolbar groups, menu sections, section boundaries.",
2683
+ "Built on a headless separator primitive handling the correct role / aria-orientation semantics.",
2684
+ "Horizontal (default) or vertical orientation, mapped without JS branching.",
2685
+ "Decorative mode drops the separator role so assistive tech ignores purely visual dividers.",
2686
+ "Carries no value and emits nothing."
2687
+ ]
2688
+ },
2689
+ {
2690
+ "slug": "scroll-area",
2691
+ "name": "FuroScrollArea",
2692
+ "layer": "molecule",
2693
+ "summary": "Styled scroll container with configurable scrollbar visibility.",
2694
+ "import": "import { FuroScrollArea } from '@openreachtech/furo-vue'",
2695
+ "docs": "docs/furo-scroll-area.md",
2696
+ "props": [
2697
+ {
2698
+ "name": "parcel",
2699
+ "type": "FuroScrollAreaParcel | null",
2700
+ "default": "null",
2701
+ "description": "Reactive data object holding orientation and scrollbar visibility."
2702
+ }
2703
+ ],
2704
+ "parcel": [
2705
+ {
2706
+ "name": "orientation",
2707
+ "type": "'vertical' | 'horizontal' | 'both'",
2708
+ "default": "'vertical'",
2709
+ "description": "Which scrollbars render, and which axes are scrollable. both also renders the corner where they meet."
2710
+ },
2711
+ {
2712
+ "name": "scrollbarVisibility",
2713
+ "type": "'hover' | 'scroll' | 'glimpse' | 'auto' | 'always'",
2714
+ "default": "unset ('hover')",
2715
+ "description": "When the scrollbar appears — it does not affect whether the content scrolls. When unset, the primitive default (hover) applies."
2716
+ },
2717
+ {
2718
+ "name": "scrollHideDelay",
2719
+ "type": "number",
2720
+ "default": "unset",
2721
+ "description": "Milliseconds before the scrollbar hides after the trigger ends (applies to hover / scroll / glimpse). Forwarded to the primitive."
2722
+ }
2723
+ ],
2724
+ "events": [],
2725
+ "slots": [
2726
+ {
2727
+ "name": "default",
2728
+ "scopedProps": "—",
2729
+ "description": "The overflowing content placed inside the scroll viewport."
2730
+ }
2731
+ ],
2732
+ "features": [
2733
+ "Wraps overflowing content with a styled, cross-browser scrollbar.",
2734
+ "Vertical (default), horizontal, or both-axes orientation; both also renders a corner.",
2735
+ "scrollbarVisibility controls when the bar appears without affecting whether content scrolls.",
2736
+ "Hides the native scrollbar and renders a consistent custom thumb across browsers.",
2737
+ "Carries no value and emits nothing."
2738
+ ]
2739
+ },
2740
+ {
2741
+ "slug": "skeleton",
2742
+ "name": "FuroSkeleton",
2743
+ "layer": "molecule",
2744
+ "summary": "Loading placeholder with text, circle, and rectangle variants.",
2745
+ "import": "import { FuroSkeleton } from '@openreachtech/furo-vue'",
2746
+ "docs": "docs/furo-skeleton.md",
2747
+ "props": [
2748
+ {
2749
+ "name": "parcel",
2750
+ "type": "SkeletonParcel | null",
2751
+ "default": "null",
2752
+ "description": "Reactive data object holding the variant, size overrides, and animation flag."
2753
+ }
2754
+ ],
2755
+ "parcel": [
2756
+ {
2757
+ "name": "variant",
2758
+ "type": "'text' | 'circle' | 'rectangle'",
2759
+ "default": "'text'",
2760
+ "description": "Placeholder shape. circle renders a round shape; text and rectangle use a small radius."
2761
+ },
2762
+ {
2763
+ "name": "width",
2764
+ "type": "string",
2765
+ "default": "variant default",
2766
+ "description": "CSS length overriding the width. Defaults to 100% for text / rectangle and 2.5rem for circle."
2767
+ },
2768
+ {
2769
+ "name": "height",
2770
+ "type": "string",
2771
+ "default": "variant default",
2772
+ "description": "CSS length overriding the height. Defaults to 1rem for text / rectangle and 2.5rem for circle."
2773
+ },
2774
+ {
2775
+ "name": "animated",
2776
+ "type": "boolean",
2777
+ "default": "true",
2778
+ "description": "When true, the placeholder pulses. Reduced-motion users always see a static placeholder."
2779
+ }
2780
+ ],
2781
+ "events": [],
2782
+ "slots": [],
2783
+ "features": [
2784
+ "Presentational loading placeholder shown while real content is fetching.",
2785
+ "Three shape variants — text (default), circle, and rectangle — mapped without JS branching.",
2786
+ "Optional width and height overrides accept any CSS length via custom properties.",
2787
+ "Pulse animation signals the loading state and pauses for reduced-motion users.",
2788
+ "Carries no value, emits nothing, and is hidden from assistive tech."
2789
+ ]
2790
+ },
2791
+ {
2792
+ "slug": "empty-state",
2793
+ "name": "FuroEmptyState",
2794
+ "layer": "molecule",
2795
+ "summary": "Placeholder for empty regions with consumer-owned title, description, and action slots.",
2796
+ "import": "import { FuroEmptyState } from '@openreachtech/furo-vue'",
2797
+ "docs": "docs/furo-empty-state.md",
2798
+ "props": [
2799
+ {
2800
+ "name": "parcel",
2801
+ "type": "EmptyStateParcel | null",
2802
+ "default": "null",
2803
+ "description": "Reactive data object holding the title and description text."
2804
+ }
2805
+ ],
2806
+ "parcel": [
2807
+ {
2808
+ "name": "title",
2809
+ "type": "string",
2810
+ "default": "—",
2811
+ "description": "Heading text. Rendered only when supplied; the consumer owns the wording."
2812
+ },
2813
+ {
2814
+ "name": "description",
2815
+ "type": "string",
2816
+ "default": "—",
2817
+ "description": "Supporting text under the title. Rendered only when supplied."
2818
+ }
2819
+ ],
2820
+ "events": [],
2821
+ "slots": [
2822
+ {
2823
+ "name": "icon",
2824
+ "scopedProps": "—",
2825
+ "description": "Leading icon or illustration above the title."
2826
+ },
2827
+ {
2828
+ "name": "action",
2829
+ "scopedProps": "—",
2830
+ "description": "Action controls (for example a create button) below the text."
2831
+ }
2832
+ ],
2833
+ "features": [
2834
+ "Presentational placeholder for empty regions — no views, no records, or nothing found.",
2835
+ "Title and description text come from the parcel, so the consumer owns all wording.",
2836
+ "Each text block renders only when supplied; there are no hardcoded strings.",
2837
+ "Optional icon and action slots host an illustration and controls such as a create button.",
2838
+ "Carries no value and emits nothing."
2839
+ ]
2840
+ },
2841
+ {
2842
+ "slug": "error-state",
2843
+ "name": "FuroErrorState",
2844
+ "layer": "molecule",
2845
+ "summary": "Placeholder for failed regions with consumer-owned title, description, and retry action slot.",
2846
+ "import": "import { FuroErrorState } from '@openreachtech/furo-vue'",
2847
+ "docs": "docs/furo-error-state.md",
2848
+ "props": [
2849
+ {
2850
+ "name": "parcel",
2851
+ "type": "ErrorStateParcel | null",
2852
+ "default": "null",
2853
+ "description": "Reactive data object holding the title and description text."
2854
+ }
2855
+ ],
2856
+ "parcel": [
2857
+ {
2858
+ "name": "title",
2859
+ "type": "string",
2860
+ "default": "—",
2861
+ "description": "Heading text. Rendered only when supplied; the consumer owns the wording."
2862
+ },
2863
+ {
2864
+ "name": "description",
2865
+ "type": "string",
2866
+ "default": "—",
2867
+ "description": "Supporting text under the title. Rendered only when supplied."
2868
+ }
2869
+ ],
2870
+ "events": [],
2871
+ "slots": [
2872
+ {
2873
+ "name": "icon",
2874
+ "scopedProps": "—",
2875
+ "description": "Leading icon or illustration above the title."
2876
+ },
2877
+ {
2878
+ "name": "action",
2879
+ "scopedProps": "—",
2880
+ "description": "Action controls (for example a retry button) below the text."
2881
+ }
2882
+ ],
2883
+ "features": [
2884
+ "Presentational placeholder for regions that failed to load — a fetch error or a failed request.",
2885
+ "Title and description text come from the parcel, so the consumer owns all wording.",
2886
+ "Each text block renders only when supplied; there are no hardcoded strings.",
2887
+ "Optional icon and action slots host an illustration and controls such as a retry button.",
2888
+ "Carries no value and emits nothing; the root announces the failure via role=\"alert\"."
2889
+ ]
2890
+ },
2891
+ {
2892
+ "slug": "splitter",
2893
+ "name": "FuroSplitter",
2894
+ "layer": "molecule",
2895
+ "summary": "Resizable panes with a draggable divider.",
2896
+ "import": "import { FuroSplitter } from '@openreachtech/furo-vue'",
2897
+ "docs": "docs/furo-splitter.md",
2898
+ "props": [
2899
+ {
2900
+ "name": "parcel",
2901
+ "type": "FuroSplitterParcel | null",
2902
+ "default": "null",
2903
+ "description": "Reactive configuration object. Non-Furo keys (autoSaveId, aria-label) forward to the group element."
2904
+ }
2905
+ ],
2906
+ "parcel": [
2907
+ {
2908
+ "name": "orientation",
2909
+ "type": "'horizontal' | 'vertical'",
2910
+ "default": "'horizontal'",
2911
+ "description": "Direction the panes are arranged in."
2912
+ },
2913
+ {
2914
+ "name": "appearance",
2915
+ "type": "'default' | 'plain'",
2916
+ "default": "'default'",
2917
+ "description": "default shows a divider line between panes; plain hides it so panes read as separated cards."
2918
+ },
2919
+ {
2920
+ "name": "panels",
2921
+ "type": "Array<FuroSplitterPanel>",
2922
+ "default": "[]",
2923
+ "description": "One descriptor per pane. A resize handle is inserted between consecutive panes."
2924
+ }
2925
+ ],
2926
+ "events": [
2927
+ {
2928
+ "name": "change-value",
2929
+ "payload": "SplitterEmitPayload",
2930
+ "description": "A handle is dragged and the layout changes. Use payload.layout and payload.extractPaneSize({ index })."
2931
+ },
2932
+ {
2933
+ "name": "update:value",
2934
+ "payload": "Array<number>",
2935
+ "description": "Same moment as change-value; powers one-way v-model:value for persisting the layout."
2936
+ }
2937
+ ],
2938
+ "slots": [
2939
+ {
2940
+ "name": "panel",
2941
+ "scopedProps": "{ panel, index, id }",
2942
+ "description": "Content for each pane. Switch on id or index to render the right region."
2943
+ },
2944
+ {
2945
+ "name": "handle",
2946
+ "scopedProps": "{ index }",
2947
+ "description": "Custom resize handle between panes. Defaults to a centered grip."
2948
+ }
2949
+ ],
2950
+ "features": [
2951
+ "Resizable split view that lays panes side by side or stacked with a draggable handle.",
2952
+ "Panes are declared through a panels array; content arrives via the scoped panel slot.",
2953
+ "Horizontal (default) or vertical orientation.",
2954
+ "default appearance shows a divider; plain hides it so panes read as separated cards.",
2955
+ "Pane sizes surface outward via update:value for one-way v-model:value persistence.",
2956
+ "A resize handle is inserted between every consecutive pair of panes, never after the last."
2957
+ ]
2958
+ },
2959
+ {
2960
+ "slug": "toggle-group",
2961
+ "name": "FuroToggleGroup",
2962
+ "layer": "molecule",
2963
+ "summary": "Single or multiple selection group built from toggle atoms.",
2964
+ "import": "import { FuroToggleGroup } from '@openreachtech/furo-vue'",
2965
+ "docs": "docs/furo-toggle-group.md",
2966
+ "props": [
2967
+ {
2968
+ "name": "parcel",
2969
+ "type": "FuroToggleGroupParcel | null",
2970
+ "default": "null",
2971
+ "description": "Reactive data object holding the selection, options, selection mode, variant, size, orientation, and disabled flag."
2972
+ }
2973
+ ],
2974
+ "parcel": [
2975
+ {
2976
+ "name": "value",
2977
+ "type": "string | string[]",
2978
+ "default": "—",
2979
+ "description": "Controlled selection. Present → controlled; absent → uncontrolled. A single value in single mode, an array in multiple mode."
2980
+ },
2981
+ {
2982
+ "name": "selectionMode",
2983
+ "type": "'single' | 'multiple'",
2984
+ "default": "'single'",
2985
+ "description": "Whether one or many options may be pressed at once."
2986
+ },
2987
+ {
2988
+ "name": "options",
2989
+ "type": "Array<{ value, label?, disabled? }>",
2990
+ "default": "[]",
2991
+ "description": "The toggle items. label falls back to value when omitted."
2992
+ },
2993
+ {
2994
+ "name": "variant",
2995
+ "type": "'default' | 'outline'",
2996
+ "default": "'default'",
2997
+ "description": "Item styling — outline adds a border."
2998
+ },
2999
+ {
3000
+ "name": "size",
3001
+ "type": "'default' | 'sm' | 'lg'",
3002
+ "default": "'default'",
3003
+ "description": "Item height and padding."
3004
+ },
3005
+ {
3006
+ "name": "orientation",
3007
+ "type": "'horizontal' | 'vertical'",
3008
+ "default": "'horizontal'",
3009
+ "description": "Layout direction."
3010
+ },
3011
+ {
3012
+ "name": "disabled",
3013
+ "type": "boolean",
3014
+ "default": "false",
3015
+ "description": "Disables the whole group; a per-option disabled flag disables a single item."
3016
+ }
3017
+ ],
3018
+ "events": [
3019
+ {
3020
+ "name": "change-value",
3021
+ "payload": "ToggleGroupEmitPayload",
3022
+ "description": "On every selection change. Wraps a CustomEvent exposing value and the control element; isSelected({ value }) reports per-option state."
3023
+ },
3024
+ {
3025
+ "name": "update:value",
3026
+ "payload": "string | string[]",
3027
+ "description": "v-model sync of the selection."
3028
+ }
3029
+ ],
3030
+ "slots": [
3031
+ {
3032
+ "name": "option",
3033
+ "scopedProps": "{ option, pressed }",
3034
+ "description": "Custom item content (e.g. icons). Defaults to the option's label. pressed reflects whether the option is selected."
3035
+ }
3036
+ ],
3037
+ "features": [
3038
+ "A set of related toggles where the group manages selection.",
3039
+ "Single (string) or multiple (string[]) selection through v-model:value / parcel.value.",
3040
+ "Built on a headless toggle-group primitive that owns roving focus and selection state.",
3041
+ "default or outline item variants, three sizes, and horizontal or vertical orientation.",
3042
+ "option slot supplies custom item content with a pressed flag; building block for FuroToolBar.",
3043
+ "Domain-agnostic public keys (value, selectionMode) map to the primitive internally."
3044
+ ]
3045
+ },
3046
+ {
3047
+ "slug": "tool-bar",
3048
+ "name": "FuroToolBar",
3049
+ "layer": "molecule",
3050
+ "summary": "Horizontal toolbar grouping buttons, toggles, and separators.",
3051
+ "import": "import { FuroToolBar } from '@openreachtech/furo-vue'",
3052
+ "docs": "docs/furo-tool-bar.md",
3053
+ "props": [
3054
+ {
3055
+ "name": "parcel",
3056
+ "type": "ToolBarParcel | null",
3057
+ "default": "null",
3058
+ "description": "Reactive data object holding orientation, text direction, and focus-wrap behavior."
3059
+ }
3060
+ ],
3061
+ "parcel": [
3062
+ {
3063
+ "name": "orientation",
3064
+ "type": "'horizontal' | 'vertical'",
3065
+ "default": "'horizontal'",
3066
+ "description": "Layout axis. Also sets which Arrow keys move focus and the aria-orientation."
3067
+ },
3068
+ {
3069
+ "name": "textDirection",
3070
+ "type": "'toRight' | 'toLeft'",
3071
+ "default": "'toRight'",
3072
+ "description": "Reading direction for the contents (toRight → left-to-right, toLeft → right-to-left)."
3073
+ },
3074
+ {
3075
+ "name": "loopFocus",
3076
+ "type": "boolean",
3077
+ "default": "false",
3078
+ "description": "When true, roving focus wraps from the last control back to the first (and vice versa)."
3079
+ }
3080
+ ],
3081
+ "events": [],
3082
+ "slots": [
3083
+ {
3084
+ "name": "default",
3085
+ "scopedProps": "—",
3086
+ "description": "The controls to group — buttons, toggles, toggle groups, separators."
3087
+ }
3088
+ ],
3089
+ "features": [
3090
+ "Groups interactive controls — buttons, toggles, separators — into one keyboard-navigable region.",
3091
+ "Built on a headless toolbar primitive providing roving focus (Arrow keys move; Tab is one stop).",
3092
+ "Horizontal (default) or vertical orientation, driving the keyboard axis and aria-orientation.",
3093
+ "loopFocus wraps roving focus from the last control back to the first.",
3094
+ "Text direction (toRight / toLeft) maps to the primitive reading direction.",
3095
+ "Carries no value and emits nothing."
3096
+ ]
3097
+ },
3098
+ {
3099
+ "slug": "tooltip",
3100
+ "name": "FuroTooltip",
3101
+ "layer": "molecule",
3102
+ "summary": "Floating hint shown on hover or focus of a trigger.",
3103
+ "import": "import { FuroTooltip } from '@openreachtech/furo-vue'",
3104
+ "docs": "docs/furo-tooltip.md",
3105
+ "props": [
3106
+ {
3107
+ "name": "parcel",
3108
+ "type": "TooltipParcel | null",
3109
+ "default": "null",
3110
+ "description": "Reactive data object holding text, positioning, delay, disabled, and optional controlled open state."
3111
+ }
3112
+ ],
3113
+ "parcel": [
3114
+ {
3115
+ "name": "text",
3116
+ "type": "string",
3117
+ "default": "null",
3118
+ "description": "Tooltip body shown when no content slot is supplied."
3119
+ },
3120
+ {
3121
+ "name": "side",
3122
+ "type": "'top' | 'right' | 'bottom' | 'left'",
3123
+ "default": "'top'",
3124
+ "description": "Edge of the trigger the content prefers."
3125
+ },
3126
+ {
3127
+ "name": "align",
3128
+ "type": "'start' | 'center' | 'end'",
3129
+ "default": "'center'",
3130
+ "description": "Alignment along the chosen side."
3131
+ },
3132
+ {
3133
+ "name": "sideOffset",
3134
+ "type": "number",
3135
+ "default": "4",
3136
+ "description": "Gap in pixels between trigger and content."
3137
+ },
3138
+ {
3139
+ "name": "delayDuration",
3140
+ "type": "number",
3141
+ "default": "200",
3142
+ "description": "Delay in milliseconds before the tooltip opens on hover."
3143
+ },
3144
+ {
3145
+ "name": "disabled",
3146
+ "type": "boolean",
3147
+ "default": "false",
3148
+ "description": "When true, the tooltip never opens."
3149
+ },
3150
+ {
3151
+ "name": "open",
3152
+ "type": "boolean | null",
3153
+ "default": "null",
3154
+ "description": "When set (non-null), open state is controlled by the consumer; otherwise the component manages it internally."
3155
+ }
3156
+ ],
3157
+ "events": [
3158
+ {
3159
+ "name": "open:change",
3160
+ "payload": "{ open: boolean }",
3161
+ "description": "Fired whenever the open state changes (hover, focus, or dismissal)."
3162
+ }
3163
+ ],
3164
+ "slots": [
3165
+ {
3166
+ "name": "trigger",
3167
+ "scopedProps": "—",
3168
+ "description": "The element the tooltip is anchored to. Focusable by default (rendered as a button)."
3169
+ },
3170
+ {
3171
+ "name": "content",
3172
+ "scopedProps": "—",
3173
+ "description": "Rich tooltip body. Falls back to parcel.text when omitted."
3174
+ }
3175
+ ],
3176
+ "features": [
3177
+ "Hover/focus hint surface shown next to a trigger element.",
3178
+ "Built on a headless tooltip primitive handling delay, positioning, dismissal, and aria-describedby.",
3179
+ "Carries a short text, or a rich content slot when more than text is needed.",
3180
+ "Positioning via side / align / sideOffset; the primitive flips to stay in view.",
3181
+ "Optional controlled open state through parcel.open; otherwise managed internally.",
3182
+ "Emits open:change whenever the open state changes."
3183
+ ]
3184
+ },
3185
+ {
3186
+ "slug": "collapsible",
3187
+ "name": "FuroCollapsible",
3188
+ "layer": "molecule",
3189
+ "summary": "Single expand/collapse region toggled by a trigger.",
3190
+ "import": "import { FuroCollapsible } from '@openreachtech/furo-vue'",
3191
+ "docs": "docs/furo-collapsible.md",
3192
+ "props": [
3193
+ {
3194
+ "name": "parcel",
3195
+ "type": "FuroCollapsibleParcel | null",
3196
+ "default": "null",
3197
+ "description": "Reactive configuration object. Non-Furo keys (aria-label) forward to the root element."
3198
+ }
3199
+ ],
3200
+ "parcel": [
3201
+ {
3202
+ "name": "value",
3203
+ "type": "boolean",
3204
+ "default": "unset (false)",
3205
+ "description": "Open state. When present, the component is controlled; when absent, it manages its own state."
3206
+ },
3207
+ {
3208
+ "name": "disabled",
3209
+ "type": "boolean",
3210
+ "default": "false",
3211
+ "description": "Disables the trigger; the region stays in its current state."
3212
+ }
3213
+ ],
3214
+ "events": [
3215
+ {
3216
+ "name": "change-value",
3217
+ "payload": "CollapsibleEmitPayload",
3218
+ "description": "The open state changes. Use payload.value (boolean) and payload.isOpen()."
3219
+ },
3220
+ {
3221
+ "name": "update:value",
3222
+ "payload": "boolean",
3223
+ "description": "Same moment as change-value; powers v-model:value for the open state."
3224
+ }
3225
+ ],
3226
+ "slots": [
3227
+ {
3228
+ "name": "trigger",
3229
+ "scopedProps": "{ open }",
3230
+ "description": "Trigger content (label plus optional indicator) rendered inside the toggle button."
3231
+ },
3232
+ {
3233
+ "name": "default",
3234
+ "scopedProps": "{ open }",
3235
+ "description": "The collapsible content revealed when open."
3236
+ }
3237
+ ],
3238
+ "features": [
3239
+ "Single expand/collapse region: one trigger toggles one associated content block.",
3240
+ "Open state is a boolean value (parcel.value / v-model:value); controlled or uncontrolled.",
3241
+ "Emits change-value (payload) and update:value (boolean) on every toggle.",
3242
+ "disabled freezes the trigger while keeping the current open state.",
3243
+ "Smooth height animation driven by the primitive-measured content height."
3244
+ ]
3245
+ },
3246
+ {
3247
+ "slug": "accordion",
3248
+ "name": "FuroAccordion",
3249
+ "layer": "molecule",
3250
+ "summary": "Multi-section collapse with single or multiple open sections.",
3251
+ "import": "import { FuroAccordion } from '@openreachtech/furo-vue'",
3252
+ "docs": "docs/furo-accordion.md",
3253
+ "props": [
3254
+ {
3255
+ "name": "parcel",
3256
+ "type": "FuroAccordionParcel | null",
3257
+ "default": "null",
3258
+ "description": "Reactive configuration object. Non-Furo keys (aria-label) forward to the root element."
3259
+ }
3260
+ ],
3261
+ "parcel": [
3262
+ {
3263
+ "name": "options",
3264
+ "type": "Array<FuroAccordionOption>",
3265
+ "default": "[]",
3266
+ "description": "The sections. value is the unique key; label is the default header; disabled disables one section."
3267
+ },
3268
+ {
3269
+ "name": "value",
3270
+ "type": "string | Array<string> | null",
3271
+ "default": "unset",
3272
+ "description": "Expanded section(s). A single value in single mode, an array in multiple mode. Present = controlled."
3273
+ },
3274
+ {
3275
+ "name": "selectionMode",
3276
+ "type": "'single' | 'multiple'",
3277
+ "default": "'single'",
3278
+ "description": "Whether one or several sections can be open at once."
3279
+ },
3280
+ {
3281
+ "name": "collapsible",
3282
+ "type": "boolean",
3283
+ "default": "true",
3284
+ "description": "single mode only: whether the open section can close. multiple mode is always collapsible."
3285
+ },
3286
+ {
3287
+ "name": "disabled",
3288
+ "type": "boolean",
3289
+ "default": "false",
3290
+ "description": "Disables the whole accordion."
3291
+ },
3292
+ {
3293
+ "name": "orientation",
3294
+ "type": "'vertical' | 'horizontal'",
3295
+ "default": "'vertical'",
3296
+ "description": "Layout and keyboard navigation axis."
3297
+ }
3298
+ ],
3299
+ "events": [
3300
+ {
3301
+ "name": "change-value",
3302
+ "payload": "AccordionEmitPayload",
3303
+ "description": "Expansion changes. Use payload.value and payload.isExpanded({ value })."
3304
+ },
3305
+ {
3306
+ "name": "update:value",
3307
+ "payload": "string | Array<string> | null",
3308
+ "description": "Same moment as change-value; powers v-model:value for the expanded section(s)."
3309
+ }
3310
+ ],
3311
+ "slots": [
3312
+ {
3313
+ "name": "header",
3314
+ "scopedProps": "{ option, expanded }",
3315
+ "description": "Header content for a section. Defaults to option.label (or option.value)."
3316
+ },
3317
+ {
3318
+ "name": "content",
3319
+ "scopedProps": "{ option, expanded }",
3320
+ "description": "Body content revealed when the section is open."
3321
+ }
3322
+ ],
3323
+ "features": [
3324
+ "Multi-section collapse: a stack of headers, each toggling its own content region.",
3325
+ "single mode keeps at most one section open; multiple mode allows several.",
3326
+ "Expanded value is a single value (single) or an array (multiple); controlled or uncontrolled.",
3327
+ "Emits change-value (payload) and update:value on every expansion change.",
3328
+ "Per-section disable plus a whole-accordion disabled flag.",
3329
+ "Smooth per-section height animation driven by the primitive-measured content height."
3330
+ ]
3331
+ },
3332
+ {
3333
+ "slug": "table",
3334
+ "name": "FuroTable",
3335
+ "layer": "organism",
3336
+ "summary": "Slot-based, controlled data table organism.",
3337
+ "import": "import { FuroTable } from '@openreachtech/furo-vue'",
3338
+ "docs": "docs/furo-table.md",
3339
+ "props": [
3340
+ {
3341
+ "name": "parcel",
3342
+ "type": "FuroTableParcel | null",
3343
+ "default": "null",
3344
+ "description": "Closed-set, JSON-serializable table state."
3345
+ }
3346
+ ],
3347
+ "parcel": [
3348
+ {
3349
+ "name": "columns",
3350
+ "type": "Array<FuroTableColumn>",
3351
+ "default": "[]",
3352
+ "description": "Column configuration."
3353
+ },
3354
+ {
3355
+ "name": "rows",
3356
+ "type": "Array<object>",
3357
+ "default": "[]",
3358
+ "description": "Raw row records, rendered in the order given."
3359
+ },
3360
+ {
3361
+ "name": "rowKey",
3362
+ "type": "string",
3363
+ "default": "'id'",
3364
+ "description": "Field used as each row's unique key."
3365
+ },
3366
+ {
3367
+ "name": "selectable",
3368
+ "type": "boolean",
3369
+ "default": "false",
3370
+ "description": "Show the selection column and select-all checkbox."
3371
+ },
3372
+ {
3373
+ "name": "selectedRowKeys",
3374
+ "type": "Array<string | number> | null",
3375
+ "default": "null",
3376
+ "description": "Controlled selection. null = uncontrolled (table holds its own selection)."
3377
+ },
3378
+ {
3379
+ "name": "sort",
3380
+ "type": "{ field: string, direction: 'asc' | 'desc' } | null",
3381
+ "default": "null",
3382
+ "description": "Active sort indicator (controlled)."
3383
+ },
3384
+ {
3385
+ "name": "loading",
3386
+ "type": "boolean",
3387
+ "default": "false",
3388
+ "description": "Render the loading state."
3389
+ },
3390
+ {
3391
+ "name": "errorMessage",
3392
+ "type": "string | null",
3393
+ "default": "null",
3394
+ "description": "When set, render the error state (takes precedence over loading/empty/rows)."
3395
+ },
3396
+ {
3397
+ "name": "emptyText",
3398
+ "type": "string",
3399
+ "default": "'No records'",
3400
+ "description": "Text for the default empty state."
3401
+ },
3402
+ {
3403
+ "name": "virtual",
3404
+ "type": "FuroTableVirtual | null",
3405
+ "default": "null",
3406
+ "description": "When set, fixed-height virtual scrolling."
3407
+ },
3408
+ {
3409
+ "name": "totalRecords",
3410
+ "type": "number | null",
3411
+ "default": "null (falls back to rows.length)",
3412
+ "description": "Full dataset size — drives total scroll height in virtual mode."
3413
+ },
3414
+ {
3415
+ "name": "rowOffset",
3416
+ "type": "number",
3417
+ "default": "0",
3418
+ "description": "Global index of rows[0] — lets rows be a sparse window in virtual mode."
3419
+ },
3420
+ {
3421
+ "name": "resizable",
3422
+ "type": "boolean",
3423
+ "default": "false",
3424
+ "description": "Show drag handles on column edges."
3425
+ },
3426
+ {
3427
+ "name": "compact",
3428
+ "type": "boolean",
3429
+ "default": "false",
3430
+ "description": "Compact density — denser rows, tighter padding, smaller text."
3431
+ },
3432
+ {
3433
+ "name": "gridLines",
3434
+ "type": "boolean",
3435
+ "default": "false",
3436
+ "description": "Vertical borders between columns."
3437
+ },
3438
+ {
3439
+ "name": "rowActionsLabel",
3440
+ "type": "string",
3441
+ "default": "''",
3442
+ "description": "Header text for the trailing row-actions column (rendered only when the row-actions slot is provided)."
3443
+ },
3444
+ {
3445
+ "name": "rowActionsWidth",
3446
+ "type": "string",
3447
+ "default": "'6rem'",
3448
+ "description": "CSS width of the row-actions column."
3449
+ }
3450
+ ],
3451
+ "events": [
3452
+ {
3453
+ "name": "sort:change",
3454
+ "payload": "{ field: string, direction: 'asc' | 'desc' | null }",
3455
+ "description": "A sortable header is clicked. Cycles asc → desc → null (direction null restores the default order)."
3456
+ },
3457
+ {
3458
+ "name": "selection:change",
3459
+ "payload": "{ selectedRowKeys: Array<string | number> }",
3460
+ "description": "A row or the select-all checkbox toggles."
3461
+ },
3462
+ {
3463
+ "name": "update:selectedRowKeys",
3464
+ "payload": "Array<string | number>",
3465
+ "description": "v-model:selectedRowKeys sync (fires with selection:change)."
3466
+ },
3467
+ {
3468
+ "name": "range:change",
3469
+ "payload": "{ first: number, last: number }",
3470
+ "description": "Virtual mode only — the visible global row window moved."
3471
+ },
3472
+ {
3473
+ "name": "row:click",
3474
+ "payload": "{ row: object, rowKey: string | number | null }",
3475
+ "description": "A data row is clicked. Interactive cell-slot content should @click.stop to opt out."
3476
+ }
3477
+ ],
3478
+ "slots": [
3479
+ {
3480
+ "name": "header-cell",
3481
+ "scopedProps": "{ column }",
3482
+ "description": "Header cell content. Falls back to column.label."
3483
+ },
3484
+ {
3485
+ "name": "cell",
3486
+ "scopedProps": "{ row, column, value }",
3487
+ "description": "Cell content. Falls back to the raw cell value."
3488
+ },
3489
+ {
3490
+ "name": "loading",
3491
+ "scopedProps": "—",
3492
+ "description": "Loading state content. Falls back to a spinner icon."
3493
+ },
3494
+ {
3495
+ "name": "empty",
3496
+ "scopedProps": "—",
3497
+ "description": "Empty state content. Falls back to parcel.emptyText."
3498
+ },
3499
+ {
3500
+ "name": "error",
3501
+ "scopedProps": "{ message }",
3502
+ "description": "Error state content. Falls back to parcel.errorMessage."
3503
+ },
3504
+ {
3505
+ "name": "placeholder",
3506
+ "scopedProps": "{ index }",
3507
+ "description": "Unloaded virtual row. Falls back to a shimmer skeleton bar."
3508
+ },
3509
+ {
3510
+ "name": "row-actions",
3511
+ "scopedProps": "{ row }",
3512
+ "description": "Providing this slot adds a trailing per-row actions column. The actions cell stops click propagation."
3513
+ },
3514
+ {
3515
+ "name": "pagination",
3516
+ "scopedProps": "—",
3517
+ "description": "Host a FuroPagination here. Empty by default."
3518
+ },
3519
+ {
3520
+ "name": "footer",
3521
+ "scopedProps": "{ selection }",
3522
+ "description": "Providing this slot renders a footer region below the table (bulk-action bar, summary row). selection is { keys, count }."
3523
+ }
3524
+ ],
3525
+ "features": [
3526
+ "Renders a native table from a columns + rows parcel — domain-agnostic and presentational.",
3527
+ "Controlled sort that cycles ascending, descending, then unsorted on each header click.",
3528
+ "Row selection with a select-all checkbox, controlled or uncontrolled.",
3529
+ "State precedence of error, loading, empty, then rows, with slots for each.",
3530
+ "Fixed-layout column resizing in fit mode, with stable widths across states.",
3531
+ "Controlled, sparse-aware virtual scrolling for large lazy-fetched datasets.",
3532
+ "Opt-in trailing row-actions column and footer region via the row-actions and footer slots."
3533
+ ]
3534
+ },
3535
+ {
3536
+ "slug": "dialog",
3537
+ "name": "FuroDialog",
3538
+ "layer": "organism",
3539
+ "summary": "Modal dialog organism with header, body, and footer regions.",
3540
+ "import": "import { FuroDialog } from '@openreachtech/furo-vue'",
3541
+ "docs": "docs/furo-dialog.md",
3542
+ "props": [
3543
+ {
3544
+ "name": "parcel",
3545
+ "type": "FuroDialogParcel | null",
3546
+ "default": "null",
3547
+ "description": "Reactive behavior object."
3548
+ }
3549
+ ],
3550
+ "parcel": [
3551
+ {
3552
+ "name": "open",
3553
+ "type": "boolean",
3554
+ "default": "—",
3555
+ "description": "Controlled open state. When omitted, the dialog manages its own state."
3556
+ },
3557
+ {
3558
+ "name": "disabled",
3559
+ "type": "boolean",
3560
+ "default": "false",
3561
+ "description": "Disables the trigger."
3562
+ },
3563
+ {
3564
+ "name": "modal",
3565
+ "type": "boolean",
3566
+ "default": "true",
3567
+ "description": "false renders without the overlay scrim and keeps the page interactive."
3568
+ },
3569
+ {
3570
+ "name": "title",
3571
+ "type": "string | null",
3572
+ "default": "null",
3573
+ "description": "Heading text. Provide a title (or the title slot) for accessibility."
3574
+ },
3575
+ {
3576
+ "name": "description",
3577
+ "type": "string | null",
3578
+ "default": "null",
3579
+ "description": "Sub-heading text below the title."
3580
+ },
3581
+ {
3582
+ "name": "closeText",
3583
+ "type": "string",
3584
+ "default": "'Close'",
3585
+ "description": "Accessible label for the built-in close button."
3586
+ },
3587
+ {
3588
+ "name": "closeOnOutsideClick",
3589
+ "type": "boolean",
3590
+ "default": "true",
3591
+ "description": "false ignores overlay / outside-click dismissal."
3592
+ },
3593
+ {
3594
+ "name": "closeOnEscape",
3595
+ "type": "boolean",
3596
+ "default": "true",
3597
+ "description": "false ignores the Escape key."
3598
+ },
3599
+ {
3600
+ "name": "size",
3601
+ "type": "'sm' | 'default' | 'lg' | 'fullscreen'",
3602
+ "default": "'default'",
3603
+ "description": "Content width variant. fullscreen fills the viewport."
3604
+ },
3605
+ {
3606
+ "name": "busy",
3607
+ "type": "boolean",
3608
+ "default": "false",
3609
+ "description": "While true, all dismissal is blocked — use during async work."
3610
+ },
3611
+ {
3612
+ "name": "initialFocus",
3613
+ "type": "string | null",
3614
+ "default": "null",
3615
+ "description": "CSS selector (scoped to the content) of the element to focus on open."
3616
+ }
3617
+ ],
3618
+ "events": [
3619
+ {
3620
+ "name": "update:open",
3621
+ "payload": "boolean",
3622
+ "description": "Open state changed — enables v-model:open."
3623
+ },
3624
+ {
3625
+ "name": "open:change",
3626
+ "payload": "{ open: boolean }",
3627
+ "description": "Open state changed (semantic form)."
3628
+ }
3629
+ ],
3630
+ "slots": [
3631
+ {
3632
+ "name": "trigger",
3633
+ "scopedProps": "—",
3634
+ "description": "Optional element that opens the dialog, rendered via as-child. Omit when opened via controlled open."
3635
+ },
3636
+ {
3637
+ "name": "title",
3638
+ "scopedProps": "—",
3639
+ "description": "Overrides the heading (falls back to parcel.title)."
3640
+ },
3641
+ {
3642
+ "name": "description",
3643
+ "scopedProps": "—",
3644
+ "description": "Overrides the description (falls back to parcel.description)."
3645
+ },
3646
+ {
3647
+ "name": "default",
3648
+ "scopedProps": "{ close }",
3649
+ "description": "Dialog body content. Receives a close() slot prop to dismiss from inside."
3650
+ },
3651
+ {
3652
+ "name": "footer",
3653
+ "scopedProps": "{ close }",
3654
+ "description": "Footer region. Receives a close() slot prop so action buttons can dismiss the dialog."
3655
+ },
3656
+ {
3657
+ "name": "close",
3658
+ "scopedProps": "—",
3659
+ "description": "Content of the built-in close button (defaults to ✕)."
3660
+ }
3661
+ ],
3662
+ "features": [
3663
+ "Modal or non-modal dialog with overlay scrim, focus trap, and an accessible heading.",
3664
+ "Controlled via parcel.open / v-model:open, or self-managed when open is omitted.",
3665
+ "Esc and overlay-click dismissal that can each be disabled independently.",
3666
+ "Four size variants: sm, default, lg, and fullscreen.",
3667
+ "A busy flag blocks every dismissal path during async work.",
3668
+ "Footer and body slots expose a close() slot prop for action buttons."
3669
+ ]
3670
+ },
3671
+ {
3672
+ "slug": "alert-dialog",
3673
+ "name": "FuroAlertDialog",
3674
+ "layer": "organism",
3675
+ "summary": "Confirmation dialog with confirm / cancel actions, tone, and busy states.",
3676
+ "import": "import { FuroAlertDialog } from '@openreachtech/furo-vue'",
3677
+ "docs": "docs/furo-alert-dialog.md",
3678
+ "props": [
3679
+ {
3680
+ "name": "parcel",
3681
+ "type": "FuroAlertDialogParcel | null",
3682
+ "default": "null",
3683
+ "description": "Reactive behavior object."
3684
+ }
3685
+ ],
3686
+ "parcel": [
3687
+ {
3688
+ "name": "open",
3689
+ "type": "boolean",
3690
+ "default": "—",
3691
+ "description": "Controlled open state. When omitted, the dialog manages its own state."
3692
+ },
3693
+ {
3694
+ "name": "disabled",
3695
+ "type": "boolean",
3696
+ "default": "false",
3697
+ "description": "Disables the trigger."
3698
+ },
3699
+ {
3700
+ "name": "title",
3701
+ "type": "string | null",
3702
+ "default": "null",
3703
+ "description": "Heading text. Provide a title (or the title slot) for accessibility."
3704
+ },
3705
+ {
3706
+ "name": "description",
3707
+ "type": "string | null",
3708
+ "default": "null",
3709
+ "description": "Sub-heading text below the title."
3710
+ },
3711
+ {
3712
+ "name": "confirmText",
3713
+ "type": "string",
3714
+ "default": "'Confirm'",
3715
+ "description": "Label for the built-in confirm button."
3716
+ },
3717
+ {
3718
+ "name": "cancelText",
3719
+ "type": "string",
3720
+ "default": "'Cancel'",
3721
+ "description": "Label for the built-in cancel button."
3722
+ },
3723
+ {
3724
+ "name": "tone",
3725
+ "type": "'default' | 'destructive'",
3726
+ "default": "'default'",
3727
+ "description": "destructive renders the confirm button with the destructive variant."
3728
+ },
3729
+ {
3730
+ "name": "closeOnEscape",
3731
+ "type": "boolean",
3732
+ "default": "true",
3733
+ "description": "false ignores the Escape key."
3734
+ },
3735
+ {
3736
+ "name": "size",
3737
+ "type": "'sm' | 'default' | 'lg'",
3738
+ "default": "'default'",
3739
+ "description": "Content width variant."
3740
+ },
3741
+ {
3742
+ "name": "busy",
3743
+ "type": "boolean",
3744
+ "default": "false",
3745
+ "description": "While true, dismissal is blocked and the action buttons are disabled (confirm shows a loading state)."
3746
+ },
3747
+ {
3748
+ "name": "initialFocus",
3749
+ "type": "string | null",
3750
+ "default": "null",
3751
+ "description": "CSS selector (scoped to the content) of the element to focus on open. When unset, the cancel button is focused."
3752
+ }
3753
+ ],
3754
+ "events": [
3755
+ {
3756
+ "name": "confirm",
3757
+ "payload": "—",
3758
+ "description": "The confirm action was chosen."
3759
+ },
3760
+ {
3761
+ "name": "cancel",
3762
+ "payload": "—",
3763
+ "description": "The cancel action was chosen (button or Escape)."
3764
+ },
3765
+ {
3766
+ "name": "update:open",
3767
+ "payload": "boolean",
3768
+ "description": "Open state changed — enables v-model:open."
3769
+ },
3770
+ {
3771
+ "name": "open:change",
3772
+ "payload": "{ open: boolean }",
3773
+ "description": "Open state changed (semantic form)."
3774
+ }
3775
+ ],
3776
+ "slots": [
3777
+ {
3778
+ "name": "trigger",
3779
+ "scopedProps": "—",
3780
+ "description": "Optional element that opens the dialog, rendered via as-child. Omit when opened via controlled open."
3781
+ },
3782
+ {
3783
+ "name": "title",
3784
+ "scopedProps": "—",
3785
+ "description": "Overrides the heading (falls back to parcel.title)."
3786
+ },
3787
+ {
3788
+ "name": "description",
3789
+ "scopedProps": "—",
3790
+ "description": "Overrides the description (falls back to parcel.description)."
3791
+ },
3792
+ {
3793
+ "name": "default",
3794
+ "scopedProps": "—",
3795
+ "description": "Optional body content rendered between the heading and the footer."
3796
+ },
3797
+ {
3798
+ "name": "footer",
3799
+ "scopedProps": "{ confirm, cancel }",
3800
+ "description": "Overrides the built-in confirm / cancel buttons. Receives confirm() and cancel() slot props."
3801
+ }
3802
+ ],
3803
+ "features": [
3804
+ "Forces an explicit decision — no close button, and outside-click never dismisses.",
3805
+ "Ships built-in confirm and cancel action buttons with overridable labels.",
3806
+ "A destructive tone renders the confirm button with the destructive variant.",
3807
+ "Controlled via parcel.open / v-model:open, or self-managed when open is omitted.",
3808
+ "A busy flag disables the buttons, blocks dismissal, and shows a loading confirm.",
3809
+ "Emits semantic confirm and cancel events; Escape maps to cancel."
3810
+ ]
3811
+ },
3812
+ {
3813
+ "slug": "drawer",
3814
+ "name": "FuroDrawer",
3815
+ "layer": "organism",
3816
+ "summary": "Edge-anchored panel with a draggable handle.",
3817
+ "import": "import { FuroDrawer } from '@openreachtech/furo-vue'",
3818
+ "docs": "docs/furo-drawer.md",
3819
+ "props": [
3820
+ {
3821
+ "name": "parcel",
3822
+ "type": "FuroDrawerParcel | null",
3823
+ "default": "null",
3824
+ "description": "Reactive behavior object."
3825
+ }
3826
+ ],
3827
+ "parcel": [
3828
+ {
3829
+ "name": "open",
3830
+ "type": "boolean",
3831
+ "default": "—",
3832
+ "description": "Controlled open state. When omitted, the drawer manages its own state."
3833
+ },
3834
+ {
3835
+ "name": "disabled",
3836
+ "type": "boolean",
3837
+ "default": "false",
3838
+ "description": "Disables the trigger."
3839
+ },
3840
+ {
3841
+ "name": "modal",
3842
+ "type": "boolean | 'trap-focus'",
3843
+ "default": "true",
3844
+ "description": "true: overlay + focus trap + scroll lock. 'trap-focus': focus trapped, page interactive. false: fully non-modal."
3845
+ },
3846
+ {
3847
+ "name": "title",
3848
+ "type": "string | null",
3849
+ "default": "null",
3850
+ "description": "Heading text. Provide a title (or the title slot) for accessibility."
3851
+ },
3852
+ {
3853
+ "name": "description",
3854
+ "type": "string | null",
3855
+ "default": "null",
3856
+ "description": "Sub-heading text below the title."
3857
+ },
3858
+ {
3859
+ "name": "closeText",
3860
+ "type": "string",
3861
+ "default": "'Close'",
3862
+ "description": "Accessible label for the built-in close button."
3863
+ },
3864
+ {
3865
+ "name": "closeOnOutsideClick",
3866
+ "type": "boolean",
3867
+ "default": "true",
3868
+ "description": "false ignores overlay / outside-click dismissal."
3869
+ },
3870
+ {
3871
+ "name": "closeOnEscape",
3872
+ "type": "boolean",
3873
+ "default": "true",
3874
+ "description": "false ignores the Escape key."
3875
+ },
3876
+ {
3877
+ "name": "side",
3878
+ "type": "'left' | 'right' | 'top' | 'bottom'",
3879
+ "default": "'right'",
3880
+ "description": "Edge the panel docks to, slides in from, and is swiped toward to dismiss."
3881
+ },
3882
+ {
3883
+ "name": "size",
3884
+ "type": "'sm' | 'default' | 'lg' | 'fullscreen'",
3885
+ "default": "'default'",
3886
+ "description": "Cross-axis extent: width for left/right, height for top/bottom. fullscreen fills the docking axis."
3887
+ },
3888
+ {
3889
+ "name": "snapPoints",
3890
+ "type": "Array<number | string> | null",
3891
+ "default": "null",
3892
+ "description": "Preset resting positions: fractions 0–1, pixels > 1, or '148px'/'30rem' strings."
3893
+ },
3894
+ {
3895
+ "name": "activeSnapPoint",
3896
+ "type": "number | string | null",
3897
+ "default": "null",
3898
+ "description": "Controlled active snap point. When set, the parent owns it (update:activeSnapPoint)."
3899
+ },
3900
+ {
3901
+ "name": "sequentialSnap",
3902
+ "type": "boolean",
3903
+ "default": "false",
3904
+ "description": "true snaps one point at a time; false snaps to the nearest by distance."
3905
+ },
3906
+ {
3907
+ "name": "swipeToOpen",
3908
+ "type": "boolean",
3909
+ "default": "false",
3910
+ "description": "Renders an edge grab strip so the panel can be swiped open from closed."
3911
+ },
3912
+ {
3913
+ "name": "dragHandle",
3914
+ "type": "boolean",
3915
+ "default": "false",
3916
+ "description": "Renders a drag handle (grab indicator) on the docked edge."
3917
+ },
3918
+ {
3919
+ "name": "busy",
3920
+ "type": "boolean",
3921
+ "default": "false",
3922
+ "description": "While true, all dismissal is blocked — use during async work."
3923
+ },
3924
+ {
3925
+ "name": "initialFocus",
3926
+ "type": "string | null",
3927
+ "default": "null",
3928
+ "description": "CSS selector (scoped to the drawer content) of the element to focus on open."
3929
+ }
3930
+ ],
3931
+ "events": [
3932
+ {
3933
+ "name": "update:open",
3934
+ "payload": "boolean",
3935
+ "description": "Open state changed — enables v-model:open."
3936
+ },
3937
+ {
3938
+ "name": "open:change",
3939
+ "payload": "{ open: boolean }",
3940
+ "description": "Open state changed (semantic form)."
3941
+ },
3942
+ {
3943
+ "name": "update:activeSnapPoint",
3944
+ "payload": "number | string | null",
3945
+ "description": "Active snap point changed — enables v-model:activeSnapPoint."
3946
+ },
3947
+ {
3948
+ "name": "snap:change",
3949
+ "payload": "{ snapPoint: number | string | null }",
3950
+ "description": "Active snap point changed (semantic form)."
3951
+ }
3952
+ ],
3953
+ "slots": [
3954
+ {
3955
+ "name": "trigger",
3956
+ "scopedProps": "—",
3957
+ "description": "Optional element that opens the drawer (rendered via as-child). Omit when opened via controlled open or swipe-to-open."
3958
+ },
3959
+ {
3960
+ "name": "title",
3961
+ "scopedProps": "—",
3962
+ "description": "Overrides the heading (falls back to parcel.title)."
3963
+ },
3964
+ {
3965
+ "name": "description",
3966
+ "scopedProps": "—",
3967
+ "description": "Overrides the description (falls back to parcel.description)."
3968
+ },
3969
+ {
3970
+ "name": "default",
3971
+ "scopedProps": "{ close }",
3972
+ "description": "Drawer body content. Receives a close() slot prop to dismiss from inside."
3973
+ },
3974
+ {
3975
+ "name": "footer",
3976
+ "scopedProps": "{ close }",
3977
+ "description": "Footer region (e.g. action buttons). Receives a close() slot prop."
3978
+ },
3979
+ {
3980
+ "name": "close",
3981
+ "scopedProps": "—",
3982
+ "description": "Content of the built-in close button (defaults to ✕)."
3983
+ }
3984
+ ],
3985
+ "features": [
3986
+ "Slide-in panel docked to any viewport edge: left, right, top, or bottom.",
3987
+ "Swipe-to-dismiss with momentum, plus optional swipe-to-open from closed.",
3988
+ "Snap points for partially-open resting positions, nearest or sequential.",
3989
+ "Modal, focus-trapped non-modal (side-panel), or fully non-modal modes.",
3990
+ "Controlled or uncontrolled open and active-snap-point state.",
3991
+ "Built-in Title/Description, close button, and Esc handling with a busy lock."
3992
+ ]
3993
+ },
3994
+ {
3995
+ "slug": "tabs",
3996
+ "name": "FuroTabs",
3997
+ "layer": "organism",
3998
+ "summary": "Tab list and panels organism with keyboard navigation.",
3999
+ "import": "import { FuroTabs } from '@openreachtech/furo-vue'",
4000
+ "docs": "docs/furo-tabs.md",
4001
+ "props": [
4002
+ {
4003
+ "name": "parcel",
4004
+ "type": "FuroTabsParcel | null",
4005
+ "default": "null",
4006
+ "description": "Reactive behavior object."
4007
+ }
4008
+ ],
4009
+ "parcel": [
4010
+ {
4011
+ "name": "tabs",
4012
+ "type": "Array<FuroTabsTab>",
4013
+ "default": "[]",
4014
+ "description": "Tab descriptors that drive the trigger row and panel slots."
4015
+ },
4016
+ {
4017
+ "name": "value",
4018
+ "type": "string | null",
4019
+ "default": "—",
4020
+ "description": "Active tab value. The key present means controlled, and null with it means controlled with no tab active; the key absent means the component manages its own active tab, defaulting to the first tab."
4021
+ },
4022
+ {
4023
+ "name": "orientation",
4024
+ "type": "'horizontal' | 'vertical'",
4025
+ "default": "'horizontal'",
4026
+ "description": "Layout direction of the trigger row."
4027
+ },
4028
+ {
4029
+ "name": "variant",
4030
+ "type": "'line' | 'solid'",
4031
+ "default": "'line'",
4032
+ "description": "line is an underlined trigger row with a sliding indicator; solid is a segmented control."
4033
+ },
4034
+ {
4035
+ "name": "scrollable",
4036
+ "type": "boolean",
4037
+ "default": "false",
4038
+ "description": "When true, the trigger row scrolls and previous/next navigation buttons appear once it overflows."
4039
+ },
4040
+ {
4041
+ "name": "showPanels",
4042
+ "type": "boolean",
4043
+ "default": "true",
4044
+ "description": "When false, no panels render — the component is a navigation menu only."
4045
+ },
4046
+ {
4047
+ "name": "showIndicator",
4048
+ "type": "boolean",
4049
+ "default": "true",
4050
+ "description": "Renders the animated sliding indicator. Applies to the line variant only."
4051
+ },
4052
+ {
4053
+ "name": "disabled",
4054
+ "type": "boolean",
4055
+ "default": "false",
4056
+ "description": "Disables the whole tab set."
4057
+ },
4058
+ {
4059
+ "name": "scrollPreviousLabel",
4060
+ "type": "string",
4061
+ "default": "'Scroll to previous tabs'",
4062
+ "description": "Accessible name of the scroll-toward-start button. Set it to translate the control."
4063
+ },
4064
+ {
4065
+ "name": "scrollNextLabel",
4066
+ "type": "string",
4067
+ "default": "'Scroll to next tabs'",
4068
+ "description": "Accessible name of the scroll-toward-end button. Set it to translate the control."
4069
+ }
4070
+ ],
4071
+ "events": [
4072
+ {
4073
+ "name": "update:value",
4074
+ "payload": "string",
4075
+ "description": "Active tab changed — enables v-model:value."
4076
+ },
4077
+ {
4078
+ "name": "tab:change",
4079
+ "payload": "{ value: string }",
4080
+ "description": "Active tab changed."
4081
+ }
4082
+ ],
4083
+ "slots": [
4084
+ {
4085
+ "name": "<value> (or <slotName>)",
4086
+ "scopedProps": "—",
4087
+ "description": "Panel content for the matching tab. One slot per tab, keyed by the tab's value (or its slotName override)."
4088
+ },
4089
+ {
4090
+ "name": "label-<value>",
4091
+ "scopedProps": "{ value, label }",
4092
+ "description": "Custom trigger content for the matching tab. When omitted, the trigger shows label."
4093
+ }
4094
+ ],
4095
+ "features": [
4096
+ "Renders a trigger row from a declarative tabs list and a panel per tab via named slots.",
4097
+ "Controlled via parcel.value / v-model:value, or self-managed (defaults to the first tab).",
4098
+ "Two visual variants: an underlined line row with a sliding indicator, and a segmented solid control.",
4099
+ "Horizontal or vertical orientation of the trigger row.",
4100
+ "A scrollable trigger row with auto-disabling previous/next navigation buttons.",
4101
+ "A panel-less menu mode (showPanels false) for router-driven navigation."
4102
+ ]
4103
+ },
4104
+ {
4105
+ "slug": "sidebar",
4106
+ "name": "FuroSidebar",
4107
+ "layer": "organism",
4108
+ "summary": "Application navigation rail with grouped items, nested sub-items, a search entry, and a collapsed form.",
4109
+ "import": "import { FuroSidebar } from '@openreachtech/furo-vue'",
4110
+ "docs": "docs/furo-sidebar.md",
4111
+ "props": [
4112
+ {
4113
+ "name": "parcel",
4114
+ "type": "FuroSidebarParcel | null",
4115
+ "default": "null",
4116
+ "description": "Furo behavior object. The only public prop; HTML attributes pass through to the nav element."
4117
+ }
4118
+ ],
4119
+ "parcel": [
4120
+ {
4121
+ "name": "groups",
4122
+ "type": "Array<FuroSidebarGroup>",
4123
+ "default": "[]",
4124
+ "description": "Runs of navigation items, each with an optional heading."
4125
+ },
4126
+ {
4127
+ "name": "activeKey",
4128
+ "type": "string | null",
4129
+ "default": "—",
4130
+ "description": "The key the application currently shows. The key present means controlled, and null with it means controlled with no row highlighted; the key absent means the rail holds it."
4131
+ },
4132
+ {
4133
+ "name": "expandedKeys",
4134
+ "type": "Array<string> | null",
4135
+ "default": "—",
4136
+ "description": "The keys whose sub-items are revealed. The key present means controlled; the key absent means the rail holds them."
4137
+ },
4138
+ {
4139
+ "name": "collapsed",
4140
+ "type": "boolean",
4141
+ "default": "false",
4142
+ "description": "Narrows the rail to its icon boxes."
4143
+ },
4144
+ {
4145
+ "name": "searchable",
4146
+ "type": "boolean",
4147
+ "default": "false",
4148
+ "description": "Renders the search entry above the groups."
4149
+ },
4150
+ {
4151
+ "name": "searchValue",
4152
+ "type": "string | null",
4153
+ "default": "null",
4154
+ "description": "The text the search entry holds."
4155
+ },
4156
+ {
4157
+ "name": "searchPlaceholder",
4158
+ "type": "string | null",
4159
+ "default": "null",
4160
+ "description": "Placeholder of the search entry."
4161
+ },
4162
+ {
4163
+ "name": "searchLabel",
4164
+ "type": "string",
4165
+ "default": "'Search'",
4166
+ "description": "Accessible name of the search entry."
4167
+ },
4168
+ {
4169
+ "name": "label",
4170
+ "type": "string",
4171
+ "default": "'Sidebar'",
4172
+ "description": "Accessible name of the navigation landmark."
4173
+ }
4174
+ ],
4175
+ "events": [
4176
+ {
4177
+ "name": "navigate",
4178
+ "payload": "{ key, parentKey }",
4179
+ "description": "Fires when an item without sub-items, or a sub-item, is chosen. parentKey names the item a sub-item sits under."
4180
+ },
4181
+ {
4182
+ "name": "update:activeKey",
4183
+ "payload": "string",
4184
+ "description": "Rides alongside navigate, which is what makes v-model:active-key work."
4185
+ },
4186
+ {
4187
+ "name": "expand-change",
4188
+ "payload": "{ key, expanded }",
4189
+ "description": "Fires when a disclosure opens or closes."
4190
+ },
4191
+ {
4192
+ "name": "update:expandedKeys",
4193
+ "payload": "Array<string>",
4194
+ "description": "Rides alongside expand-change, which is what makes v-model:expanded-keys work."
4195
+ },
4196
+ {
4197
+ "name": "search-change",
4198
+ "payload": "SidebarSearchPayload",
4199
+ "description": "Fires on every keystroke in the search entry."
4200
+ },
4201
+ {
4202
+ "name": "search-commit",
4203
+ "payload": "SidebarSearchPayload",
4204
+ "description": "Fires on blur and on Enter in the search entry."
4205
+ },
4206
+ {
4207
+ "name": "update:searchValue",
4208
+ "payload": "string | null",
4209
+ "description": "Rides alongside both search events, which is what makes v-model:search-value work."
4210
+ }
4211
+ ],
4212
+ "slots": [
4213
+ {
4214
+ "name": "header",
4215
+ "scopedProps": "—",
4216
+ "description": "Content above the search entry, for a product mark or an account switcher."
4217
+ },
4218
+ {
4219
+ "name": "search",
4220
+ "scopedProps": "—",
4221
+ "description": "Replaces the default search control while keeping its place in the rail."
4222
+ },
4223
+ {
4224
+ "name": "item",
4225
+ "scopedProps": "{ entry, active, expanded, collapsed }",
4226
+ "description": "Replaces the default primary button, which is where a router link goes."
4227
+ },
4228
+ {
4229
+ "name": "sub-item",
4230
+ "scopedProps": "{ entry, parent, active }",
4231
+ "description": "Replaces the default nested button."
4232
+ },
4233
+ {
4234
+ "name": "footer",
4235
+ "scopedProps": "—",
4236
+ "description": "Content below the groups, for a sign-out row or a version line."
4237
+ }
4238
+ ],
4239
+ "features": [
4240
+ "Public SFC prop is parcel only; every other HTML attribute lands on the nav element.",
4241
+ "Items arrive as data, so the component knows nothing about what they mean.",
4242
+ "Groups carry an optional heading, which is how the design separates one run of items from the next.",
4243
+ "An item that declares items of its own becomes a disclosure and reveals them in place.",
4244
+ "Setting searchable renders FuroSearchField at the top rather than a second search control.",
4245
+ "Setting collapsed narrows the rail to its icon boxes and drops labels, headings, sub-items and the search entry.",
4246
+ "activeKey and expandedKeys are controlled when supplied and internal when not, like FuroTabs.",
4247
+ "The item and sub-item slots replace the default buttons, which is where a router link goes."
4248
+ ]
4249
+ },
4250
+ {
4251
+ "slug": "stepper",
4252
+ "name": "FuroStepper",
4253
+ "layer": "organism",
4254
+ "summary": "Multi-step progress organism for form sequences.",
4255
+ "import": "import { FuroStepper } from '@openreachtech/furo-vue'",
4256
+ "docs": "docs/furo-stepper.md",
4257
+ "props": [
4258
+ {
4259
+ "name": "parcel",
4260
+ "type": "FuroStepperParcel | null",
4261
+ "default": "null",
4262
+ "description": "Reactive behavior object."
4263
+ }
4264
+ ],
4265
+ "parcel": [
4266
+ {
4267
+ "name": "steps",
4268
+ "type": "Array<FuroStepperStep>",
4269
+ "default": "[]",
4270
+ "description": "Step descriptors that drive the rail and panel slots."
4271
+ },
4272
+ {
4273
+ "name": "value",
4274
+ "type": "number | null",
4275
+ "default": "—",
4276
+ "description": "Active step (1-based). The key present means controlled, and null with it means controlled with no step active; the key absent means the component manages its own active step, defaulting to the first step."
4277
+ },
4278
+ {
4279
+ "name": "orientation",
4280
+ "type": "'horizontal' | 'vertical'",
4281
+ "default": "'horizontal'",
4282
+ "description": "Layout direction of the step rail."
4283
+ },
4284
+ {
4285
+ "name": "linear",
4286
+ "type": "boolean",
4287
+ "default": "false",
4288
+ "description": "When true, steps must be completed in order — forward jumps are blocked."
4289
+ },
4290
+ {
4291
+ "name": "showPanels",
4292
+ "type": "boolean",
4293
+ "default": "true",
4294
+ "description": "When false, no panels render — the component is an indicator strip only."
4295
+ },
4296
+ {
4297
+ "name": "disabled",
4298
+ "type": "boolean",
4299
+ "default": "false",
4300
+ "description": "Disables the whole stepper."
4301
+ }
4302
+ ],
4303
+ "events": [
4304
+ {
4305
+ "name": "update:value",
4306
+ "payload": "number",
4307
+ "description": "Active step changed — enables v-model:value."
4308
+ },
4309
+ {
4310
+ "name": "step:change",
4311
+ "payload": "{ value: number }",
4312
+ "description": "Active step changed."
4313
+ }
4314
+ ],
4315
+ "slots": [
4316
+ {
4317
+ "name": "<value> (or <slotName>)",
4318
+ "scopedProps": "{ value, step }",
4319
+ "description": "Panel content for the matching step. One slot per step, keyed by the step's value (or its slotName override)."
4320
+ },
4321
+ {
4322
+ "name": "indicator-<value>",
4323
+ "scopedProps": "{ step, value, completed }",
4324
+ "description": "Custom indicator content. When omitted, shows a check icon when completed, else the step number."
4325
+ },
4326
+ {
4327
+ "name": "title-<value>",
4328
+ "scopedProps": "{ value }",
4329
+ "description": "Custom title content. When omitted, the title shows title."
4330
+ }
4331
+ ],
4332
+ "features": [
4333
+ "Renders a step rail from a declarative steps list and an optional panel per step via named slots.",
4334
+ "Controlled via parcel.value / v-model:value (1-based), or self-managed (defaults to the first step).",
4335
+ "Horizontal or vertical orientation of the step rail.",
4336
+ "A linear mode that blocks forward jumps until earlier steps are completed.",
4337
+ "An indicator-strip mode (showPanels false) that drives an external form region.",
4338
+ "Per-step indicator and title slots for fully custom rail content."
4339
+ ]
4340
+ },
4341
+ {
4342
+ "slug": "editor",
4343
+ "name": "FuroEditor",
4344
+ "layer": "organism",
4345
+ "summary": "Rich-text editor organism with a configurable toolbar.",
4346
+ "import": "import { FuroEditor } from '@openreachtech/furo-vue'",
4347
+ "docs": "docs/furo-editor.md",
4348
+ "props": [
4349
+ {
4350
+ "name": "parcel",
4351
+ "type": "object | null",
4352
+ "default": "null",
4353
+ "description": "Configuration and state."
4354
+ }
4355
+ ],
4356
+ "parcel": [
4357
+ {
4358
+ "name": "value",
4359
+ "type": "string",
4360
+ "default": "''",
4361
+ "description": "HTML content. Controlled — pair with update:value."
4362
+ },
4363
+ {
4364
+ "name": "placeholder",
4365
+ "type": "string",
4366
+ "default": "''",
4367
+ "description": "Empty-state placeholder."
4368
+ },
4369
+ {
4370
+ "name": "readOnly",
4371
+ "type": "boolean",
4372
+ "default": "false",
4373
+ "description": "Hides the toolbar and makes content non-editable (keeps the bordered surface)."
4374
+ },
4375
+ {
4376
+ "name": "appearance",
4377
+ "type": "'editor' | 'plain'",
4378
+ "default": "'editor'",
4379
+ "description": "'plain' renders content as bare text — no toolbar, border, background, or padding."
4380
+ },
4381
+ {
4382
+ "name": "autofocus",
4383
+ "type": "boolean | 'start' | 'end' | 'all' | number",
4384
+ "default": "false",
4385
+ "description": "Where the caret lands when the editor is created. Read once, at creation."
4386
+ },
4387
+ {
4388
+ "name": "contentAttributes",
4389
+ "type": "Record<string, string>",
4390
+ "default": "{}",
4391
+ "description": "Attributes set on the writing area, for example aria-label. Read once, at creation."
4392
+ },
4393
+ {
4394
+ "name": "toolbar",
4395
+ "type": "Array<Array<string>>",
4396
+ "default": "default",
4397
+ "description": "Toolbar layout as groups of action names; separators sit between groups."
4398
+ },
4399
+ {
4400
+ "name": "attachedFiles",
4401
+ "type": "Array<*>",
4402
+ "default": "[]",
4403
+ "description": "Attachment records held for the consumer; shape is the consumer's own."
4404
+ },
4405
+ {
4406
+ "name": "labels",
4407
+ "type": "object",
4408
+ "default": "built-in",
4409
+ "description": "Partial overrides for toolbar tooltips and dialog text."
4410
+ },
4411
+ {
4412
+ "name": "mention",
4413
+ "type": "{ searchMentions }",
4414
+ "default": "absent",
4415
+ "description": "Enables @-mentions when present. searchMentions is ({ query }) => Promise<Array<{ id, label }>>."
4416
+ },
4417
+ {
4418
+ "name": "image",
4419
+ "type": "{ uploadImage }",
4420
+ "default": "absent",
4421
+ "description": "Enables inline images when present. uploadImage is ({ file }) => Promise<{ src, alt? }>."
4422
+ },
4423
+ {
4424
+ "name": "actionOverrides",
4425
+ "type": "Record<string, fn>",
4426
+ "default": "{}",
4427
+ "description": "Override the click behavior of a built-in control by name."
4428
+ }
4429
+ ],
4430
+ "events": [
4431
+ {
4432
+ "name": "update:value",
4433
+ "payload": "string (HTML)",
4434
+ "description": "Content changed (v-model:value)."
4435
+ },
4436
+ {
4437
+ "name": "change-value",
4438
+ "payload": "{ value }",
4439
+ "description": "Content changed."
4440
+ },
4441
+ {
4442
+ "name": "commit-value",
4443
+ "payload": "{ value }",
4444
+ "description": "Editor blurred."
4445
+ },
4446
+ {
4447
+ "name": "update:attachedFiles",
4448
+ "payload": "Array<*>",
4449
+ "description": "Attachment list changed (e.g. a removal)."
4450
+ },
4451
+ {
4452
+ "name": "mention:add",
4453
+ "payload": "{ id, label }",
4454
+ "description": "A mention was inserted."
4455
+ },
4456
+ {
4457
+ "name": "files:add",
4458
+ "payload": "{ files }",
4459
+ "description": "Files were dropped or pasted that the editor does not insert itself."
4460
+ },
4461
+ {
4462
+ "name": "image:error",
4463
+ "payload": "{ file, error }",
4464
+ "description": "An inline-image upload was refused; the rest of the batch continues."
4465
+ }
4466
+ ],
4467
+ "slots": [
4468
+ {
4469
+ "name": "toolbar-start",
4470
+ "scopedProps": "{ command, editor }",
4471
+ "description": "Custom controls prepended to the toolbar."
4472
+ },
4473
+ {
4474
+ "name": "toolbar-end",
4475
+ "scopedProps": "{ command, editor }",
4476
+ "description": "Custom controls appended to the toolbar."
4477
+ },
4478
+ {
4479
+ "name": "attachments",
4480
+ "scopedProps": "{ attachedFiles, remove, isEditable }",
4481
+ "description": "Render the attachment UI. remove is ({ index }) => void."
4482
+ },
4483
+ {
4484
+ "name": "footer",
4485
+ "scopedProps": "—",
4486
+ "description": "Content rendered below the editor (e.g. submit row)."
4487
+ }
4488
+ ],
4489
+ "features": [
4490
+ "Chatter-style rich-text composition with formatting, links, lists, and blockquote.",
4491
+ "Controlled HTML value paired with update:value, plus change-value and commit-value events.",
4492
+ "Layered paste handling: plain-text normalization, HTML sanitization, and Markdown auto-convert.",
4493
+ "Declarative toolbar layout as groups of action names, with separators between groups.",
4494
+ "Mention and inline-image seams enabled by supplying consumer-owned adapters.",
4495
+ "Dropped and pasted files the editor does not embed reach the consumer through files:add.",
4496
+ "Custom-action seams via toolbar-start / toolbar-end slots and parcel.actionOverrides."
4497
+ ]
4498
+ },
4499
+ {
4500
+ "slug": "toast",
4501
+ "name": "FuroToast",
4502
+ "layer": "organism",
4503
+ "summary": "Single toast notification organism.",
4504
+ "import": "import { FuroToast } from '@openreachtech/furo-vue'",
4505
+ "docs": "docs/furo-toast.md",
4506
+ "props": [
4507
+ {
4508
+ "name": "parcel",
4509
+ "type": "ToastParcel | null",
4510
+ "default": "null",
4511
+ "description": "Reactive behavior object."
4512
+ }
4513
+ ],
4514
+ "parcel": [
4515
+ {
4516
+ "name": "toasts",
4517
+ "type": "Array<ToastEntry>",
4518
+ "default": "[]",
4519
+ "description": "The queue, owned by the parent. Render order follows the array; remove an entry on dismiss."
4520
+ },
4521
+ {
4522
+ "name": "position",
4523
+ "type": "'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'",
4524
+ "default": "'bottom-right'",
4525
+ "description": "Viewport placement."
4526
+ },
4527
+ {
4528
+ "name": "durationInMilliseconds",
4529
+ "type": "number",
4530
+ "default": "4000",
4531
+ "description": "Default auto-dismiss in ms. Per-toast durationInMilliseconds overrides it."
4532
+ },
4533
+ {
4534
+ "name": "swipeDirection",
4535
+ "type": "'right' | 'left' | 'up' | 'down'",
4536
+ "default": "derived from position",
4537
+ "description": "Swipe-to-dismiss direction. When unset, it follows the position."
4538
+ },
4539
+ {
4540
+ "name": "label",
4541
+ "type": "string",
4542
+ "default": "'Notifications'",
4543
+ "description": "Accessible label for the region."
4544
+ },
4545
+ {
4546
+ "name": "hotkey",
4547
+ "type": "Array<string> | null",
4548
+ "default": "null",
4549
+ "description": "Keyboard shortcut to focus the viewport (e.g. ['F8'])."
4550
+ },
4551
+ {
4552
+ "name": "maxVisible",
4553
+ "type": "number",
4554
+ "default": "3",
4555
+ "description": "Caps how many toasts render at once (the most recent). The rest stay queued."
4556
+ }
4557
+ ],
4558
+ "events": [
4559
+ {
4560
+ "name": "dismiss",
4561
+ "payload": "{ key }",
4562
+ "description": "A toast closed (timeout, swipe, or close button). Remove it from your array."
4563
+ },
4564
+ {
4565
+ "name": "action",
4566
+ "payload": "{ key }",
4567
+ "description": "The action button was clicked. The toast also dismisses afterward."
4568
+ }
4569
+ ],
4570
+ "slots": [
4571
+ {
4572
+ "name": "title",
4573
+ "scopedProps": "{ toast }",
4574
+ "description": "Overrides a toast's title region (falls back to toast.title)."
4575
+ },
4576
+ {
4577
+ "name": "description",
4578
+ "scopedProps": "{ toast }",
4579
+ "description": "Overrides a toast's description region (falls back to toast.description)."
4580
+ }
4581
+ ],
4582
+ "features": [
4583
+ "Controlled notification stack — the parent owns the queue via parcel.toasts.",
4584
+ "Registry-free with no internal queue; emits dismiss / action by key for the parent to update its array.",
4585
+ "Six viewport positions with derived swipe-to-dismiss direction.",
4586
+ "Five toast types, including a held-open loading type for the promise pattern.",
4587
+ "A collapsed stack that expands on hover or focus.",
4588
+ "Direction-aware enter/exit motion and per-toast or default auto-dismiss durations."
4589
+ ]
4590
+ },
4591
+ {
4592
+ "slug": "toaster",
4593
+ "name": "FuroToaster",
4594
+ "layer": "organism",
4595
+ "summary": "Imperative toast() host that stacks and dismisses notifications.",
4596
+ "import": "import { FuroToaster, toast } from '@openreachtech/furo-vue'",
4597
+ "docs": "docs/furo-toast.md",
4598
+ "props": [
4599
+ {
4600
+ "name": "—",
4601
+ "type": "—",
4602
+ "default": "—",
4603
+ "description": "FuroToaster takes no props; configure it through toast.configure()."
4604
+ }
4605
+ ],
4606
+ "parcel": [],
4607
+ "events": [],
4608
+ "slots": [],
4609
+ "features": [
4610
+ "Imperative global toast host mounted once in the app layout.",
4611
+ "An opt-in layer on top of the controlled FuroToast — the organism stays registry-free.",
4612
+ "A ToastQueue singleton bridges function handlers to the parcel.",
4613
+ "toast.show returns a key; toast.update merges fields for the loading-to-success pattern.",
4614
+ "actions[].onClick handlers are held in the queue (not serialized) and routed back on action.",
4615
+ "toast.configure sets viewport defaults like position, duration, and richColors."
4616
+ ]
4617
+ }
4618
+ ]
4619
+ }