@treeui/vue 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +2 -7
  2. package/dist/components/{TreeAccordion.vue.d.ts → TAccordion.vue.d.ts} +1 -1
  3. package/dist/components/TAccordion.vue.d.ts.map +1 -0
  4. package/dist/components/{TreeAccordionItem.vue.d.ts → TAccordionItem.vue.d.ts} +1 -1
  5. package/dist/components/TAccordionItem.vue.d.ts.map +1 -0
  6. package/dist/components/{TreeAlert.vue.d.ts → TAlert.vue.d.ts} +7 -7
  7. package/dist/components/TAlert.vue.d.ts.map +1 -0
  8. package/dist/components/{TreeAvatar.vue.d.ts → TAvatar.vue.d.ts} +7 -7
  9. package/dist/components/TAvatar.vue.d.ts.map +1 -0
  10. package/dist/components/{TreeBadge.vue.d.ts → TBadge.vue.d.ts} +9 -9
  11. package/dist/components/TBadge.vue.d.ts.map +1 -0
  12. package/dist/components/{TreeBreadcrumb.vue.d.ts → TBreadcrumb.vue.d.ts} +1 -1
  13. package/dist/components/TBreadcrumb.vue.d.ts.map +1 -0
  14. package/dist/components/{TreeBreadcrumbItem.vue.d.ts → TBreadcrumbItem.vue.d.ts} +1 -1
  15. package/dist/components/TBreadcrumbItem.vue.d.ts.map +1 -0
  16. package/dist/components/{TreeButton.vue.d.ts → TButton.vue.d.ts} +6 -6
  17. package/dist/components/TButton.vue.d.ts.map +1 -0
  18. package/dist/components/{TreeCard.vue.d.ts → TCard.vue.d.ts} +6 -6
  19. package/dist/components/TCard.vue.d.ts.map +1 -0
  20. package/dist/components/{TreeCheckbox.vue.d.ts → TCheckbox.vue.d.ts} +4 -4
  21. package/dist/components/TCheckbox.vue.d.ts.map +1 -0
  22. package/dist/components/{TreeCombobox.vue.d.ts → TCombobox.vue.d.ts} +9 -9
  23. package/dist/components/TCombobox.vue.d.ts.map +1 -0
  24. package/dist/components/{TreeConfirmDialog.vue.d.ts → TConfirmDialog.vue.d.ts} +6 -6
  25. package/dist/components/TConfirmDialog.vue.d.ts.map +1 -0
  26. package/dist/components/{TreeContainer.vue.d.ts → TContainer.vue.d.ts} +4 -4
  27. package/dist/components/TContainer.vue.d.ts.map +1 -0
  28. package/dist/components/{TreeContextMenu.vue.d.ts → TContextMenu.vue.d.ts} +9 -9
  29. package/dist/components/TContextMenu.vue.d.ts.map +1 -0
  30. package/dist/components/{TreeDatePicker.vue.d.ts → TDatePicker.vue.d.ts} +4 -4
  31. package/dist/components/TDatePicker.vue.d.ts.map +1 -0
  32. package/dist/components/{TreeDateTimePicker.vue.d.ts → TDateTimePicker.vue.d.ts} +4 -4
  33. package/dist/components/TDateTimePicker.vue.d.ts.map +1 -0
  34. package/dist/components/{TreeDivider.vue.d.ts → TDivider.vue.d.ts} +1 -1
  35. package/dist/components/TDivider.vue.d.ts.map +1 -0
  36. package/dist/components/{TreeDrawer.vue.d.ts → TDrawer.vue.d.ts} +6 -6
  37. package/dist/components/TDrawer.vue.d.ts.map +1 -0
  38. package/dist/components/{TreeDropdown.vue.d.ts → TDropdown.vue.d.ts} +9 -9
  39. package/dist/components/TDropdown.vue.d.ts.map +1 -0
  40. package/dist/components/{TreeEmptyState.vue.d.ts → TEmptyState.vue.d.ts} +4 -4
  41. package/dist/components/TEmptyState.vue.d.ts.map +1 -0
  42. package/dist/components/{TreeFileUpload.vue.d.ts → TFileUpload.vue.d.ts} +9 -9
  43. package/dist/components/TFileUpload.vue.d.ts.map +1 -0
  44. package/dist/components/{TreeFormField.vue.d.ts → TFormField.vue.d.ts} +4 -4
  45. package/dist/components/TFormField.vue.d.ts.map +1 -0
  46. package/dist/components/{TreeGrid.vue.d.ts → TGrid.vue.d.ts} +1 -1
  47. package/dist/components/TGrid.vue.d.ts.map +1 -0
  48. package/dist/components/{TreeIcon.vue.d.ts → TIcon.vue.d.ts} +3 -3
  49. package/dist/components/TIcon.vue.d.ts.map +1 -0
  50. package/dist/components/{TreeInput.vue.d.ts → TInput.vue.d.ts} +4 -4
  51. package/dist/components/TInput.vue.d.ts.map +1 -0
  52. package/dist/components/{TreeLink.vue.d.ts → TLink.vue.d.ts} +4 -4
  53. package/dist/components/TLink.vue.d.ts.map +1 -0
  54. package/dist/components/{TreeMarkdownEditor.vue.d.ts → TMarkdownEditor.vue.d.ts} +4 -4
  55. package/dist/components/TMarkdownEditor.vue.d.ts.map +1 -0
  56. package/dist/components/{TreeModal.vue.d.ts → TModal.vue.d.ts} +4 -4
  57. package/dist/components/TModal.vue.d.ts.map +1 -0
  58. package/dist/components/{TreeMultiSelect.vue.d.ts → TMultiSelect.vue.d.ts} +11 -11
  59. package/dist/components/TMultiSelect.vue.d.ts.map +1 -0
  60. package/dist/components/{TreeNavMenu.vue.d.ts → TNavMenu.vue.d.ts} +11 -11
  61. package/dist/components/TNavMenu.vue.d.ts.map +1 -0
  62. package/dist/components/{TreeNavbar.vue.d.ts → TNavbar.vue.d.ts} +4 -4
  63. package/dist/components/TNavbar.vue.d.ts.map +1 -0
  64. package/dist/components/{TreeNumberInput.vue.d.ts → TNumberInput.vue.d.ts} +4 -4
  65. package/dist/components/TNumberInput.vue.d.ts.map +1 -0
  66. package/dist/components/{TreePagination.vue.d.ts → TPagination.vue.d.ts} +4 -4
  67. package/dist/components/TPagination.vue.d.ts.map +1 -0
  68. package/dist/components/{TreePopover.vue.d.ts → TPopover.vue.d.ts} +4 -4
  69. package/dist/components/TPopover.vue.d.ts.map +1 -0
  70. package/dist/components/{TreePricing.vue.d.ts → TPricing.vue.d.ts} +5 -5
  71. package/dist/components/TPricing.vue.d.ts.map +1 -0
  72. package/dist/components/{TreePricingCard.vue.d.ts → TPricingCard.vue.d.ts} +4 -4
  73. package/dist/components/TPricingCard.vue.d.ts.map +1 -0
  74. package/dist/components/{TreeProgress.vue.d.ts → TProgress.vue.d.ts} +4 -4
  75. package/dist/components/TProgress.vue.d.ts.map +1 -0
  76. package/dist/components/{TreeRadio.vue.d.ts → TRadio.vue.d.ts} +4 -4
  77. package/dist/components/TRadio.vue.d.ts.map +1 -0
  78. package/dist/components/{TreeRadioGroup.vue.d.ts → TRadioGroup.vue.d.ts} +4 -4
  79. package/dist/components/TRadioGroup.vue.d.ts.map +1 -0
  80. package/dist/components/{TreeSelect.vue.d.ts → TSelect.vue.d.ts} +7 -7
  81. package/dist/components/TSelect.vue.d.ts.map +1 -0
  82. package/dist/components/{TreeSelectableList.vue.d.ts → TSelectableList.vue.d.ts} +9 -9
  83. package/dist/components/TSelectableList.vue.d.ts.map +1 -0
  84. package/dist/components/{TreeSidebar.vue.d.ts → TSidebar.vue.d.ts} +7 -7
  85. package/dist/components/TSidebar.vue.d.ts.map +1 -0
  86. package/dist/components/{TreeSkeleton.vue.d.ts → TSkeleton.vue.d.ts} +1 -1
  87. package/dist/components/TSkeleton.vue.d.ts.map +1 -0
  88. package/dist/components/{TreeSpinner.vue.d.ts → TSpinner.vue.d.ts} +4 -4
  89. package/dist/components/TSpinner.vue.d.ts.map +1 -0
  90. package/dist/components/{TreeStack.vue.d.ts → TStack.vue.d.ts} +4 -4
  91. package/dist/components/TStack.vue.d.ts.map +1 -0
  92. package/dist/components/{TreeStat.vue.d.ts → TStat.vue.d.ts} +7 -7
  93. package/dist/components/TStat.vue.d.ts.map +1 -0
  94. package/dist/components/{TreeSteps.vue.d.ts → TSteps.vue.d.ts} +16 -16
  95. package/dist/components/TSteps.vue.d.ts.map +1 -0
  96. package/dist/components/{TreeSwitch.vue.d.ts → TSwitch.vue.d.ts} +4 -4
  97. package/dist/components/TSwitch.vue.d.ts.map +1 -0
  98. package/dist/components/{TreeTab.vue.d.ts → TTab.vue.d.ts} +1 -1
  99. package/dist/components/TTab.vue.d.ts.map +1 -0
  100. package/dist/components/{TreeTabList.vue.d.ts → TTabList.vue.d.ts} +1 -1
  101. package/dist/components/TTabList.vue.d.ts.map +1 -0
  102. package/dist/components/{TreeTabPanel.vue.d.ts → TTabPanel.vue.d.ts} +1 -1
  103. package/dist/components/TTabPanel.vue.d.ts.map +1 -0
  104. package/dist/components/{TreeTable.vue.d.ts → TTable.vue.d.ts} +15 -15
  105. package/dist/components/TTable.vue.d.ts.map +1 -0
  106. package/dist/components/{TreeTabs.vue.d.ts → TTabs.vue.d.ts} +4 -4
  107. package/dist/components/TTabs.vue.d.ts.map +1 -0
  108. package/dist/components/{TreeTag.vue.d.ts → TTag.vue.d.ts} +7 -7
  109. package/dist/components/TTag.vue.d.ts.map +1 -0
  110. package/dist/components/{TreeTextarea.vue.d.ts → TTextarea.vue.d.ts} +4 -4
  111. package/dist/components/TTextarea.vue.d.ts.map +1 -0
  112. package/dist/components/{TreeTimeline.vue.d.ts → TTimeline.vue.d.ts} +13 -13
  113. package/dist/components/TTimeline.vue.d.ts.map +1 -0
  114. package/dist/components/{TreeToast.vue.d.ts → TToast.vue.d.ts} +1 -1
  115. package/dist/components/TToast.vue.d.ts.map +1 -0
  116. package/dist/components/{TreeToastProvider.vue.d.ts → TToastProvider.vue.d.ts} +1 -1
  117. package/dist/components/TToastProvider.vue.d.ts.map +1 -0
  118. package/dist/components/{TreeToggleGroup.vue.d.ts → TToggleGroup.vue.d.ts} +15 -15
  119. package/dist/components/TToggleGroup.vue.d.ts.map +1 -0
  120. package/dist/components/{TreeTooltip.vue.d.ts → TTooltip.vue.d.ts} +4 -4
  121. package/dist/components/TTooltip.vue.d.ts.map +1 -0
  122. package/dist/components/{TreeTreeView.vue.d.ts → TTreeView.vue.d.ts} +6 -6
  123. package/dist/components/TTreeView.vue.d.ts.map +1 -0
  124. package/dist/components/{TreeTreeViewItem.vue.d.ts → TTreeViewItem.vue.d.ts} +3 -3
  125. package/dist/components/TTreeViewItem.vue.d.ts.map +1 -0
  126. package/dist/components/index.d.ts +80 -143
  127. package/dist/components/index.d.ts.map +1 -1
  128. package/dist/components/sidebar.d.ts +2 -2
  129. package/dist/components/sidebar.d.ts.map +1 -1
  130. package/dist/components/tabs-context.d.ts +2 -2
  131. package/dist/components/tabs-context.d.ts.map +1 -1
  132. package/dist/components/tree-view.d.ts +8 -8
  133. package/dist/components/tree-view.d.ts.map +1 -1
  134. package/dist/index.cjs +4 -4
  135. package/dist/index.cjs.map +1 -1
  136. package/dist/index.js +1289 -1337
  137. package/dist/index.js.map +1 -1
  138. package/dist/plugin.d.ts.map +1 -1
  139. package/dist/style.css +1 -1
  140. package/dist/types/contracts.d.ts +5 -5
  141. package/dist/types/contracts.d.ts.map +1 -1
  142. package/package.json +4 -4
  143. package/dist/components/TreeAccordion.vue.d.ts.map +0 -1
  144. package/dist/components/TreeAccordionItem.vue.d.ts.map +0 -1
  145. package/dist/components/TreeAlert.vue.d.ts.map +0 -1
  146. package/dist/components/TreeAvatar.vue.d.ts.map +0 -1
  147. package/dist/components/TreeBadge.vue.d.ts.map +0 -1
  148. package/dist/components/TreeBreadcrumb.vue.d.ts.map +0 -1
  149. package/dist/components/TreeBreadcrumbItem.vue.d.ts.map +0 -1
  150. package/dist/components/TreeButton.vue.d.ts.map +0 -1
  151. package/dist/components/TreeCard.vue.d.ts.map +0 -1
  152. package/dist/components/TreeCheckbox.vue.d.ts.map +0 -1
  153. package/dist/components/TreeCombobox.vue.d.ts.map +0 -1
  154. package/dist/components/TreeConfirmDialog.vue.d.ts.map +0 -1
  155. package/dist/components/TreeContainer.vue.d.ts.map +0 -1
  156. package/dist/components/TreeContextMenu.vue.d.ts.map +0 -1
  157. package/dist/components/TreeDatePicker.vue.d.ts.map +0 -1
  158. package/dist/components/TreeDateTimePicker.vue.d.ts.map +0 -1
  159. package/dist/components/TreeDivider.vue.d.ts.map +0 -1
  160. package/dist/components/TreeDrawer.vue.d.ts.map +0 -1
  161. package/dist/components/TreeDropdown.vue.d.ts.map +0 -1
  162. package/dist/components/TreeEmptyState.vue.d.ts.map +0 -1
  163. package/dist/components/TreeFileUpload.vue.d.ts.map +0 -1
  164. package/dist/components/TreeFormField.vue.d.ts.map +0 -1
  165. package/dist/components/TreeGrid.vue.d.ts.map +0 -1
  166. package/dist/components/TreeIcon.vue.d.ts.map +0 -1
  167. package/dist/components/TreeInput.vue.d.ts.map +0 -1
  168. package/dist/components/TreeLink.vue.d.ts.map +0 -1
  169. package/dist/components/TreeMarkdownEditor.vue.d.ts.map +0 -1
  170. package/dist/components/TreeModal.vue.d.ts.map +0 -1
  171. package/dist/components/TreeMultiSelect.vue.d.ts.map +0 -1
  172. package/dist/components/TreeNavMenu.vue.d.ts.map +0 -1
  173. package/dist/components/TreeNavbar.vue.d.ts.map +0 -1
  174. package/dist/components/TreeNumberInput.vue.d.ts.map +0 -1
  175. package/dist/components/TreePagination.vue.d.ts.map +0 -1
  176. package/dist/components/TreePopover.vue.d.ts.map +0 -1
  177. package/dist/components/TreePricing.vue.d.ts.map +0 -1
  178. package/dist/components/TreePricingCard.vue.d.ts.map +0 -1
  179. package/dist/components/TreeProgress.vue.d.ts.map +0 -1
  180. package/dist/components/TreeRadio.vue.d.ts.map +0 -1
  181. package/dist/components/TreeRadioGroup.vue.d.ts.map +0 -1
  182. package/dist/components/TreeSelect.vue.d.ts.map +0 -1
  183. package/dist/components/TreeSelectableList.vue.d.ts.map +0 -1
  184. package/dist/components/TreeSidebar.vue.d.ts.map +0 -1
  185. package/dist/components/TreeSkeleton.vue.d.ts.map +0 -1
  186. package/dist/components/TreeSpinner.vue.d.ts.map +0 -1
  187. package/dist/components/TreeStack.vue.d.ts.map +0 -1
  188. package/dist/components/TreeStat.vue.d.ts.map +0 -1
  189. package/dist/components/TreeSteps.vue.d.ts.map +0 -1
  190. package/dist/components/TreeSwitch.vue.d.ts.map +0 -1
  191. package/dist/components/TreeTab.vue.d.ts.map +0 -1
  192. package/dist/components/TreeTabList.vue.d.ts.map +0 -1
  193. package/dist/components/TreeTabPanel.vue.d.ts.map +0 -1
  194. package/dist/components/TreeTable.vue.d.ts.map +0 -1
  195. package/dist/components/TreeTabs.vue.d.ts.map +0 -1
  196. package/dist/components/TreeTag.vue.d.ts.map +0 -1
  197. package/dist/components/TreeTextarea.vue.d.ts.map +0 -1
  198. package/dist/components/TreeTimeline.vue.d.ts.map +0 -1
  199. package/dist/components/TreeToast.vue.d.ts.map +0 -1
  200. package/dist/components/TreeToastProvider.vue.d.ts.map +0 -1
  201. package/dist/components/TreeToggleGroup.vue.d.ts.map +0 -1
  202. package/dist/components/TreeTooltip.vue.d.ts.map +0 -1
  203. package/dist/components/TreeTreeView.vue.d.ts.map +0 -1
  204. package/dist/components/TreeTreeViewItem.vue.d.ts.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots"],"sources":["../src/components/accordion.ts","../src/components/TreeAccordion.vue","../src/components/TreeAccordion.vue","../src/components/TreeAccordionItem.vue","../src/components/TreeAccordionItem.vue","../src/components/TreeAlert.vue","../src/components/TreeAlert.vue","../src/components/TreeBadge.vue","../src/components/TreeBadge.vue","../src/components/TreeBreadcrumb.vue","../src/components/TreeBreadcrumb.vue","../src/components/TreeBreadcrumbItem.vue","../src/components/TreeBreadcrumbItem.vue","../src/components/TreeSpinner.vue","../src/components/TreeSpinner.vue","../src/components/TreeButton.vue","../src/components/TreeButton.vue","../src/components/TreeCard.vue","../src/components/TreeCard.vue","../src/components/TreeCheckbox.vue","../src/components/TreeCheckbox.vue","../src/composables/useControllableOpen.ts","../src/components/TreeCombobox.vue","../src/components/TreeCombobox.vue","../src/components/TreeModal.vue","../src/components/TreeModal.vue","../src/components/TreeConfirmDialog.vue","../src/components/TreeConfirmDialog.vue","../src/components/TreeContainer.vue","../src/components/TreeContainer.vue","../src/components/TreeContextMenu.vue","../src/components/TreeContextMenu.vue","../src/components/TreeDatePicker.vue","../src/components/TreeDatePicker.vue","../src/components/TreeDateTimePicker.vue","../src/components/TreeDateTimePicker.vue","../src/components/TreeDrawer.vue","../src/components/TreeDrawer.vue","../src/components/TreeDropdown.vue","../src/components/TreeDropdown.vue","../src/components/TreeEmptyState.vue","../src/components/TreeEmptyState.vue","../src/components/TreeFileUpload.vue","../src/components/TreeFileUpload.vue","../src/components/TreeMultiSelect.vue","../src/components/TreeMultiSelect.vue","../src/components/TreeGrid.vue","../src/components/TreeGrid.vue","../src/components/TreeNavbar.vue","../src/components/TreeNavbar.vue","../src/components/TreeLink.vue","../src/components/TreeLink.vue","../src/components/sidebar.ts","../src/components/TreeNavMenu.vue","../src/components/TreeNavMenu.vue","../src/components/TreeRadio.vue","../src/components/TreeRadio.vue","../src/components/TreeRadioGroup.vue","../src/components/TreeRadioGroup.vue","../src/components/TreeSelect.vue","../src/components/TreeSelect.vue","../src/components/TreeSidebar.vue","../src/components/TreeSidebar.vue","../src/components/TreeInput.vue","../src/components/TreeInput.vue","../src/components/TreeNumberInput.vue","../src/components/TreeNumberInput.vue","../src/components/TreeSelectableList.vue","../src/components/TreeSelectableList.vue","../src/components/TreeStack.vue","../src/components/TreeStack.vue","../src/components/tree-view.ts","../src/components/TreeTreeViewItem.vue","../src/components/TreeTreeViewItem.vue","../src/components/TreeTreeView.vue","../src/components/TreeTreeView.vue","../src/components/TreeSteps.vue","../src/components/TreeSteps.vue","../src/components/TreeToggleGroup.vue","../src/components/TreeToggleGroup.vue","../src/components/TreeTextarea.vue","../src/components/TreeTextarea.vue","../src/components/TreeSkeleton.vue","../src/components/TreeSkeleton.vue","../src/components/TreeStat.vue","../src/components/TreeStat.vue","../src/components/TreeSwitch.vue","../src/components/TreeSwitch.vue","../src/components/TreeTooltip.vue","../src/components/TreeTooltip.vue","../src/components/TreeFormField.vue","../src/components/TreeFormField.vue","../src/components/TreePagination.vue","../src/components/TreePagination.vue","../src/components/TreePopover.vue","../src/components/TreePopover.vue","../src/components/TreeProgress.vue","../src/components/TreeProgress.vue","../src/components/tabs-context.ts","../src/components/TreeTabs.vue","../src/components/TreeTabs.vue","../src/components/TreeTabList.vue","../src/components/TreeTabList.vue","../src/components/TreeTab.vue","../src/components/TreeTab.vue","../src/components/TreeTabPanel.vue","../src/components/TreeTabPanel.vue","../src/components/TreeToast.vue","../src/components/TreeToast.vue","../src/composables/useToast.ts","../src/components/TreeToastProvider.vue","../src/components/TreeToastProvider.vue","../src/components/TreeAvatar.vue","../src/components/TreeAvatar.vue","../src/components/TreeDivider.vue","../src/components/TreeDivider.vue","../src/components/TreeTable.vue","../src/components/TreeTable.vue","../src/components/TreeTag.vue","../src/components/TreeTag.vue","../src/components/TreeTimeline.vue","../src/components/TreeTimeline.vue","../src/components/TreePricingCard.vue","../src/components/TreePricingCard.vue","../src/components/TreePricing.vue","../src/components/TreePricing.vue","../src/components/TreeMarkdownEditor.vue","../src/components/TreeMarkdownEditor.vue","../src/components/TreeIcon.vue","../src/components/TreeIcon.vue","../src/plugin.ts","../src/types/contracts.ts"],"sourcesContent":["import type { InjectionKey } from 'vue';\n\nexport type AccordionType = 'single' | 'multiple';\n\nexport interface AccordionContext {\n type: AccordionType;\n disabled: boolean;\n collapsible: boolean;\n isItemOpen: (value: string) => boolean;\n toggleItem: (value: string) => void;\n registerTrigger: (value: string, el: HTMLElement) => void;\n unregisterTrigger: (value: string) => void;\n focusPrev: (value: string) => void;\n focusNext: (value: string) => void;\n focusFirst: () => void;\n focusLast: () => void;\n}\n\nexport const accordionInjectionKey: InjectionKey<AccordionContext> = Symbol('tree-accordion');\n","<script setup lang=\"ts\">\nimport { computed, provide, reactive } from 'vue';\nimport { type AccordionType, accordionInjectionKey } from './accordion';\n\nconst props = withDefaults(\n defineProps<{\n type?: AccordionType;\n modelValue?: string | string[];\n defaultValue?: string | string[];\n disabled?: boolean;\n collapsible?: boolean;\n }>(),\n {\n type: 'single',\n modelValue: undefined,\n defaultValue: undefined,\n disabled: false,\n collapsible: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string | string[] | undefined): void;\n}>();\n\n// Internal uncontrolled state\nconst internalValue = computed<string[]>(() => {\n const def = props.defaultValue;\n if (def === undefined) return [];\n return Array.isArray(def) ? def : [def];\n});\n\nconst uncontrolledValue = reactive<Set<string>>(new Set(internalValue.value));\n\nconst isControlled = computed(() => props.modelValue !== undefined);\n\nconst openValues = computed<Set<string>>(() => {\n if (isControlled.value) {\n const mv = props.modelValue!;\n return new Set(Array.isArray(mv) ? mv : [mv]);\n }\n return uncontrolledValue;\n});\n\nfunction isItemOpen(value: string): boolean {\n return openValues.value.has(value);\n}\n\nfunction emitUpdate(values: Set<string>) {\n if (props.type === 'single') {\n const arr = [...values];\n emit('update:modelValue', arr.length > 0 ? arr[0] : undefined);\n } else {\n emit('update:modelValue', [...values]);\n }\n}\n\nfunction toggleItem(value: string) {\n const currentlyOpen = isItemOpen(value);\n\n if (props.type === 'single') {\n if (currentlyOpen) {\n if (props.collapsible) {\n if (!isControlled.value) {\n uncontrolledValue.delete(value);\n }\n emitUpdate(new Set());\n }\n } else {\n if (!isControlled.value) {\n uncontrolledValue.clear();\n uncontrolledValue.add(value);\n }\n emitUpdate(new Set([value]));\n }\n } else {\n // Multiple mode\n const next = new Set(openValues.value);\n if (currentlyOpen) {\n next.delete(value);\n } else {\n next.add(value);\n }\n if (!isControlled.value) {\n if (currentlyOpen) {\n uncontrolledValue.delete(value);\n } else {\n uncontrolledValue.add(value);\n }\n }\n emitUpdate(next);\n }\n}\n\n// Keyboard navigation between triggers\nconst triggerMap = new Map<string, HTMLElement>();\nconst triggerOrder: string[] = reactive([]);\n\nfunction registerTrigger(value: string, el: HTMLElement) {\n if (!triggerMap.has(value)) {\n triggerOrder.push(value);\n }\n triggerMap.set(value, el);\n}\n\nfunction unregisterTrigger(value: string) {\n triggerMap.delete(value);\n const idx = triggerOrder.indexOf(value);\n if (idx !== -1) triggerOrder.splice(idx, 1);\n}\n\nfunction getEnabledTriggers(): string[] {\n return triggerOrder.filter((v) => {\n const el = triggerMap.get(v);\n return el && !el.hasAttribute('disabled');\n });\n}\n\nfunction focusPrev(value: string) {\n const enabled = getEnabledTriggers();\n const idx = enabled.indexOf(value);\n const prev = idx > 0 ? idx - 1 : enabled.length - 1;\n triggerMap.get(enabled[prev])?.focus();\n}\n\nfunction focusNext(value: string) {\n const enabled = getEnabledTriggers();\n const idx = enabled.indexOf(value);\n const next = idx < enabled.length - 1 ? idx + 1 : 0;\n triggerMap.get(enabled[next])?.focus();\n}\n\nfunction focusFirst() {\n const enabled = getEnabledTriggers();\n if (enabled.length) triggerMap.get(enabled[0])?.focus();\n}\n\nfunction focusLast() {\n const enabled = getEnabledTriggers();\n if (enabled.length) triggerMap.get(enabled[enabled.length - 1])?.focus();\n}\n\nprovide(accordionInjectionKey, {\n type: props.type,\n disabled: props.disabled,\n collapsible: props.collapsible,\n isItemOpen,\n toggleItem,\n registerTrigger,\n unregisterTrigger,\n focusPrev,\n focusNext,\n focusFirst,\n focusLast,\n});\n</script>\n\n<template>\n <div class=\"tree-accordion\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, provide, reactive } from 'vue';\nimport { type AccordionType, accordionInjectionKey } from './accordion';\n\nconst props = withDefaults(\n defineProps<{\n type?: AccordionType;\n modelValue?: string | string[];\n defaultValue?: string | string[];\n disabled?: boolean;\n collapsible?: boolean;\n }>(),\n {\n type: 'single',\n modelValue: undefined,\n defaultValue: undefined,\n disabled: false,\n collapsible: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string | string[] | undefined): void;\n}>();\n\n// Internal uncontrolled state\nconst internalValue = computed<string[]>(() => {\n const def = props.defaultValue;\n if (def === undefined) return [];\n return Array.isArray(def) ? def : [def];\n});\n\nconst uncontrolledValue = reactive<Set<string>>(new Set(internalValue.value));\n\nconst isControlled = computed(() => props.modelValue !== undefined);\n\nconst openValues = computed<Set<string>>(() => {\n if (isControlled.value) {\n const mv = props.modelValue!;\n return new Set(Array.isArray(mv) ? mv : [mv]);\n }\n return uncontrolledValue;\n});\n\nfunction isItemOpen(value: string): boolean {\n return openValues.value.has(value);\n}\n\nfunction emitUpdate(values: Set<string>) {\n if (props.type === 'single') {\n const arr = [...values];\n emit('update:modelValue', arr.length > 0 ? arr[0] : undefined);\n } else {\n emit('update:modelValue', [...values]);\n }\n}\n\nfunction toggleItem(value: string) {\n const currentlyOpen = isItemOpen(value);\n\n if (props.type === 'single') {\n if (currentlyOpen) {\n if (props.collapsible) {\n if (!isControlled.value) {\n uncontrolledValue.delete(value);\n }\n emitUpdate(new Set());\n }\n } else {\n if (!isControlled.value) {\n uncontrolledValue.clear();\n uncontrolledValue.add(value);\n }\n emitUpdate(new Set([value]));\n }\n } else {\n // Multiple mode\n const next = new Set(openValues.value);\n if (currentlyOpen) {\n next.delete(value);\n } else {\n next.add(value);\n }\n if (!isControlled.value) {\n if (currentlyOpen) {\n uncontrolledValue.delete(value);\n } else {\n uncontrolledValue.add(value);\n }\n }\n emitUpdate(next);\n }\n}\n\n// Keyboard navigation between triggers\nconst triggerMap = new Map<string, HTMLElement>();\nconst triggerOrder: string[] = reactive([]);\n\nfunction registerTrigger(value: string, el: HTMLElement) {\n if (!triggerMap.has(value)) {\n triggerOrder.push(value);\n }\n triggerMap.set(value, el);\n}\n\nfunction unregisterTrigger(value: string) {\n triggerMap.delete(value);\n const idx = triggerOrder.indexOf(value);\n if (idx !== -1) triggerOrder.splice(idx, 1);\n}\n\nfunction getEnabledTriggers(): string[] {\n return triggerOrder.filter((v) => {\n const el = triggerMap.get(v);\n return el && !el.hasAttribute('disabled');\n });\n}\n\nfunction focusPrev(value: string) {\n const enabled = getEnabledTriggers();\n const idx = enabled.indexOf(value);\n const prev = idx > 0 ? idx - 1 : enabled.length - 1;\n triggerMap.get(enabled[prev])?.focus();\n}\n\nfunction focusNext(value: string) {\n const enabled = getEnabledTriggers();\n const idx = enabled.indexOf(value);\n const next = idx < enabled.length - 1 ? idx + 1 : 0;\n triggerMap.get(enabled[next])?.focus();\n}\n\nfunction focusFirst() {\n const enabled = getEnabledTriggers();\n if (enabled.length) triggerMap.get(enabled[0])?.focus();\n}\n\nfunction focusLast() {\n const enabled = getEnabledTriggers();\n if (enabled.length) triggerMap.get(enabled[enabled.length - 1])?.focus();\n}\n\nprovide(accordionInjectionKey, {\n type: props.type,\n disabled: props.disabled,\n collapsible: props.collapsible,\n isItemOpen,\n toggleItem,\n registerTrigger,\n unregisterTrigger,\n focusPrev,\n focusNext,\n focusFirst,\n focusLast,\n});\n</script>\n\n<template>\n <div class=\"tree-accordion\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onMounted, onBeforeUnmount, ref, useId } from 'vue';\nimport { accordionInjectionKey } from './accordion';\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n }>(),\n {\n disabled: false,\n },\n);\n\nconst injected = inject(accordionInjectionKey);\n\nif (!injected) {\n throw new Error('[TreeUI] TAccordionItem must be used inside a TAccordion.');\n}\n\nconst ctx = injected;\n\nconst triggerId = useId();\nconst panelId = useId();\nconst triggerRef = ref<HTMLButtonElement | null>(null);\n\nconst isOpen = computed(() => ctx.isItemOpen(props.value));\nconst isDisabled = computed(() => props.disabled || ctx.disabled);\n\nconst itemClasses = computed(() => [\n 'tree-accordion__item',\n {\n 'is-open': isOpen.value,\n 'is-disabled': isDisabled.value,\n },\n]);\n\nfunction handleToggle() {\n if (isDisabled.value) return;\n ctx.toggleItem(props.value);\n}\n\nfunction handleKeydown(event: KeyboardEvent) {\n if (isDisabled.value) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n ctx.focusNext(props.value);\n break;\n case 'ArrowUp':\n event.preventDefault();\n ctx.focusPrev(props.value);\n break;\n case 'Home':\n event.preventDefault();\n ctx.focusFirst();\n break;\n case 'End':\n event.preventDefault();\n ctx.focusLast();\n break;\n }\n}\n\nonMounted(() => {\n if (triggerRef.value) {\n ctx.registerTrigger(props.value, triggerRef.value);\n }\n});\n\nonBeforeUnmount(() => {\n ctx.unregisterTrigger(props.value);\n});\n</script>\n\n<template>\n <div :class=\"itemClasses\">\n <h3 class=\"tree-accordion__heading\">\n <button\n :id=\"triggerId\"\n ref=\"triggerRef\"\n type=\"button\"\n class=\"tree-accordion__trigger\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"panelId\"\n :disabled=\"isDisabled || undefined\"\n @click=\"handleToggle\"\n @keydown=\"handleKeydown\"\n >\n <slot\n name=\"trigger\"\n :open=\"isOpen\"\n >\n {{ value }}\n </slot>\n <svg\n class=\"tree-accordion__icon\"\n :class=\"{ 'is-open': isOpen }\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n </h3>\n <div\n v-if=\"isOpen\"\n :id=\"panelId\"\n role=\"region\"\n :aria-labelledby=\"triggerId\"\n class=\"tree-accordion__content\"\n >\n <div class=\"tree-accordion__panel\">\n <slot />\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onMounted, onBeforeUnmount, ref, useId } from 'vue';\nimport { accordionInjectionKey } from './accordion';\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n }>(),\n {\n disabled: false,\n },\n);\n\nconst injected = inject(accordionInjectionKey);\n\nif (!injected) {\n throw new Error('[TreeUI] TAccordionItem must be used inside a TAccordion.');\n}\n\nconst ctx = injected;\n\nconst triggerId = useId();\nconst panelId = useId();\nconst triggerRef = ref<HTMLButtonElement | null>(null);\n\nconst isOpen = computed(() => ctx.isItemOpen(props.value));\nconst isDisabled = computed(() => props.disabled || ctx.disabled);\n\nconst itemClasses = computed(() => [\n 'tree-accordion__item',\n {\n 'is-open': isOpen.value,\n 'is-disabled': isDisabled.value,\n },\n]);\n\nfunction handleToggle() {\n if (isDisabled.value) return;\n ctx.toggleItem(props.value);\n}\n\nfunction handleKeydown(event: KeyboardEvent) {\n if (isDisabled.value) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n ctx.focusNext(props.value);\n break;\n case 'ArrowUp':\n event.preventDefault();\n ctx.focusPrev(props.value);\n break;\n case 'Home':\n event.preventDefault();\n ctx.focusFirst();\n break;\n case 'End':\n event.preventDefault();\n ctx.focusLast();\n break;\n }\n}\n\nonMounted(() => {\n if (triggerRef.value) {\n ctx.registerTrigger(props.value, triggerRef.value);\n }\n});\n\nonBeforeUnmount(() => {\n ctx.unregisterTrigger(props.value);\n});\n</script>\n\n<template>\n <div :class=\"itemClasses\">\n <h3 class=\"tree-accordion__heading\">\n <button\n :id=\"triggerId\"\n ref=\"triggerRef\"\n type=\"button\"\n class=\"tree-accordion__trigger\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"panelId\"\n :disabled=\"isDisabled || undefined\"\n @click=\"handleToggle\"\n @keydown=\"handleKeydown\"\n >\n <slot\n name=\"trigger\"\n :open=\"isOpen\"\n >\n {{ value }}\n </slot>\n <svg\n class=\"tree-accordion__icon\"\n :class=\"{ 'is-open': isOpen }\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n </h3>\n <div\n v-if=\"isOpen\"\n :id=\"panelId\"\n role=\"region\"\n :aria-labelledby=\"triggerId\"\n class=\"tree-accordion__content\"\n >\n <div class=\"tree-accordion__panel\">\n <slot />\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nexport type TreeAlertVariant = 'info' | 'success' | 'warning' | 'danger';\n\nconst props = withDefaults(\n defineProps<{\n variant?: TreeAlertVariant;\n size?: TreeSize;\n dismissible?: boolean;\n }>(),\n {\n variant: 'info',\n size: 'md',\n dismissible: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'dismiss'): void;\n}>();\n\nconst classes = computed(() => [\n 'tree-alert',\n `tree-alert--${props.variant}`,\n `tree-alert--${props.size}`,\n]);\n\nfunction handleDismiss() {\n emit('dismiss');\n}\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"alert\"\n >\n <span\n v-if=\"$slots.icon\"\n class=\"tree-alert__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <div class=\"tree-alert__content\">\n <slot />\n </div>\n <button\n v-if=\"dismissible\"\n type=\"button\"\n class=\"tree-alert__dismiss\"\n aria-label=\"Dismiss\"\n @click=\"handleDismiss\"\n >\n <slot name=\"dismiss-icon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nexport type TreeAlertVariant = 'info' | 'success' | 'warning' | 'danger';\n\nconst props = withDefaults(\n defineProps<{\n variant?: TreeAlertVariant;\n size?: TreeSize;\n dismissible?: boolean;\n }>(),\n {\n variant: 'info',\n size: 'md',\n dismissible: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'dismiss'): void;\n}>();\n\nconst classes = computed(() => [\n 'tree-alert',\n `tree-alert--${props.variant}`,\n `tree-alert--${props.size}`,\n]);\n\nfunction handleDismiss() {\n emit('dismiss');\n}\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"alert\"\n >\n <span\n v-if=\"$slots.icon\"\n class=\"tree-alert__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <div class=\"tree-alert__content\">\n <slot />\n </div>\n <button\n v-if=\"dismissible\"\n type=\"button\"\n class=\"tree-alert__dismiss\"\n aria-label=\"Dismiss\"\n @click=\"handleDismiss\"\n >\n <slot name=\"dismiss-icon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize, TreeVariant } from '../types/contracts';\n\nconst _treeBadgeTones = ['neutral', 'success', 'warning', 'danger', 'info'] as const;\n\nexport type TreeBadgeTone = (typeof _treeBadgeTones)[number];\n\nconst props = withDefaults(\n defineProps<{\n variant?: TreeVariant;\n size?: TreeSize;\n tone?: TreeBadgeTone;\n }>(),\n {\n variant: 'soft',\n size: 'md',\n tone: 'neutral',\n },\n);\n\nconst classes = computed(() => [\n 'tree-badge',\n `tree-badge--${props.variant}`,\n `tree-badge--${props.size}`,\n `tree-badge--tone-${props.tone}`,\n]);\n</script>\n\n<template>\n <span :class=\"classes\">\n <span\n v-if=\"$slots.icon\"\n class=\"tree-badge__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <slot />\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize, TreeVariant } from '../types/contracts';\n\nconst _treeBadgeTones = ['neutral', 'success', 'warning', 'danger', 'info'] as const;\n\nexport type TreeBadgeTone = (typeof _treeBadgeTones)[number];\n\nconst props = withDefaults(\n defineProps<{\n variant?: TreeVariant;\n size?: TreeSize;\n tone?: TreeBadgeTone;\n }>(),\n {\n variant: 'soft',\n size: 'md',\n tone: 'neutral',\n },\n);\n\nconst classes = computed(() => [\n 'tree-badge',\n `tree-badge--${props.variant}`,\n `tree-badge--${props.size}`,\n `tree-badge--tone-${props.tone}`,\n]);\n</script>\n\n<template>\n <span :class=\"classes\">\n <span\n v-if=\"$slots.icon\"\n class=\"tree-badge__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <slot />\n </span>\n</template>\n","<script setup lang=\"ts\">\nconst props = withDefaults(\n defineProps<{\n /**\n * Character or string used to visually separate breadcrumb items.\n */\n separator?: string;\n }>(),\n {\n separator: '/',\n },\n);\n</script>\n\n<template>\n <nav\n aria-label=\"Breadcrumb\"\n class=\"tree-breadcrumb\"\n >\n <ol\n class=\"tree-breadcrumb__list\"\n :style=\"{ '--tree-breadcrumb-separator': `'${props.separator}'` }\"\n >\n <slot />\n </ol>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nconst props = withDefaults(\n defineProps<{\n /**\n * Character or string used to visually separate breadcrumb items.\n */\n separator?: string;\n }>(),\n {\n separator: '/',\n },\n);\n</script>\n\n<template>\n <nav\n aria-label=\"Breadcrumb\"\n class=\"tree-breadcrumb\"\n >\n <ol\n class=\"tree-breadcrumb__list\"\n :style=\"{ '--tree-breadcrumb-separator': `'${props.separator}'` }\"\n >\n <slot />\n </ol>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, type Component } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n /**\n * URL the breadcrumb item links to. Omit for the current/last item.\n */\n href?: string;\n /**\n * Route target. When provided and vue-router is available, renders RouterLink.\n */\n to?: string | Record<string, unknown>;\n /**\n * Marks this item as the current page. Automatically set if it's the last item without href.\n */\n current?: boolean;\n }>(),\n {\n href: undefined,\n to: undefined,\n current: false,\n },\n);\n\nconst instance = getCurrentInstance();\n\nconst routerLinkComponent = computed<Component | null>(() => {\n if (!props.to) return null;\n\n return (instance?.appContext.components.RouterLink as Component | undefined) ?? null;\n});\n\nconst hasRouterLink = computed(() => {\n return Boolean(routerLinkComponent.value);\n});\n\nconst canRenderLink = computed(() => {\n if (props.href) return true;\n if (typeof props.to === 'string') return true;\n return Boolean(props.to && hasRouterLink.value);\n});\n\nconst isCurrent = computed(() => props.current || !canRenderLink.value);\n\nconst tag = computed<string | Component>(() => {\n if (props.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n\n return 'a';\n});\n\nconst linkProps = computed(() => {\n if (props.to && hasRouterLink.value) {\n return { to: props.to };\n }\n\n return {\n href: props.href ?? (typeof props.to === 'string' ? props.to : undefined),\n };\n});\n</script>\n\n<template>\n <li class=\"tree-breadcrumb__item\">\n <component\n :is=\"tag\"\n v-if=\"!isCurrent\"\n v-bind=\"linkProps\"\n class=\"tree-breadcrumb__link\"\n >\n <slot />\n </component>\n <span\n v-else\n class=\"tree-breadcrumb__current\"\n aria-current=\"page\"\n >\n <slot />\n </span>\n </li>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, type Component } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n /**\n * URL the breadcrumb item links to. Omit for the current/last item.\n */\n href?: string;\n /**\n * Route target. When provided and vue-router is available, renders RouterLink.\n */\n to?: string | Record<string, unknown>;\n /**\n * Marks this item as the current page. Automatically set if it's the last item without href.\n */\n current?: boolean;\n }>(),\n {\n href: undefined,\n to: undefined,\n current: false,\n },\n);\n\nconst instance = getCurrentInstance();\n\nconst routerLinkComponent = computed<Component | null>(() => {\n if (!props.to) return null;\n\n return (instance?.appContext.components.RouterLink as Component | undefined) ?? null;\n});\n\nconst hasRouterLink = computed(() => {\n return Boolean(routerLinkComponent.value);\n});\n\nconst canRenderLink = computed(() => {\n if (props.href) return true;\n if (typeof props.to === 'string') return true;\n return Boolean(props.to && hasRouterLink.value);\n});\n\nconst isCurrent = computed(() => props.current || !canRenderLink.value);\n\nconst tag = computed<string | Component>(() => {\n if (props.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n\n return 'a';\n});\n\nconst linkProps = computed(() => {\n if (props.to && hasRouterLink.value) {\n return { to: props.to };\n }\n\n return {\n href: props.href ?? (typeof props.to === 'string' ? props.to : undefined),\n };\n});\n</script>\n\n<template>\n <li class=\"tree-breadcrumb__item\">\n <component\n :is=\"tag\"\n v-if=\"!isCurrent\"\n v-bind=\"linkProps\"\n class=\"tree-breadcrumb__link\"\n >\n <slot />\n </component>\n <span\n v-else\n class=\"tree-breadcrumb__current\"\n aria-current=\"page\"\n >\n <slot />\n </span>\n </li>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n size?: TreeSize;\n label?: string;\n }>(),\n {\n size: 'md',\n label: 'Loading',\n },\n);\n\nconst classes = computed(() => ['tree-spinner', `tree-spinner--${props.size}`]);\n</script>\n\n<template>\n <span\n :class=\"classes\"\n role=\"status\"\n :aria-label=\"label\"\n >\n <span\n class=\"tree-spinner__ring\"\n aria-hidden=\"true\"\n />\n <span class=\"tree-visually-hidden\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n size?: TreeSize;\n label?: string;\n }>(),\n {\n size: 'md',\n label: 'Loading',\n },\n);\n\nconst classes = computed(() => ['tree-spinner', `tree-spinner--${props.size}`]);\n</script>\n\n<template>\n <span\n :class=\"classes\"\n role=\"status\"\n :aria-label=\"label\"\n >\n <span\n class=\"tree-spinner__ring\"\n aria-hidden=\"true\"\n />\n <span class=\"tree-visually-hidden\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize, TreeVariant } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TreeVariant;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n type?: 'button' | 'submit' | 'reset';\n }>(),\n {\n as: 'button',\n variant: 'solid',\n size: 'md',\n disabled: false,\n loading: false,\n type: 'button',\n },\n);\n\nconst emit = defineEmits<{\n click: [event: MouseEvent];\n}>();\n\nconst isNativeButton = computed(() => props.as === 'button');\nconst isDisabled = computed(() => props.disabled || props.loading);\nconst classes = computed(() => [\n 'tree-button',\n `tree-button--${props.variant}`,\n `tree-button--${props.size}`,\n {\n 'is-loading': props.loading,\n 'is-disabled': isDisabled.value,\n },\n]);\n\nconst onClick = (event: MouseEvent) => {\n if (isDisabled.value) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n emit('click', event);\n};\n</script>\n\n<template>\n <component\n :is=\"as\"\n :type=\"isNativeButton ? type : undefined\"\n :class=\"classes\"\n :disabled=\"isNativeButton ? isDisabled : undefined\"\n :aria-disabled=\"!isNativeButton && isDisabled ? 'true' : undefined\"\n :aria-busy=\"loading || undefined\"\n :tabindex=\"!isNativeButton && isDisabled ? -1 : undefined\"\n @click=\"onClick\"\n >\n <span\n v-if=\"loading\"\n class=\"tree-button__spinner\"\n >\n <TreeSpinner\n size=\"sm\"\n label=\"Loading\"\n />\n </span>\n <span\n v-if=\"$slots.icon\"\n class=\"tree-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span class=\"tree-button__label\">\n <slot />\n </span>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize, TreeVariant } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TreeVariant;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n type?: 'button' | 'submit' | 'reset';\n }>(),\n {\n as: 'button',\n variant: 'solid',\n size: 'md',\n disabled: false,\n loading: false,\n type: 'button',\n },\n);\n\nconst emit = defineEmits<{\n click: [event: MouseEvent];\n}>();\n\nconst isNativeButton = computed(() => props.as === 'button');\nconst isDisabled = computed(() => props.disabled || props.loading);\nconst classes = computed(() => [\n 'tree-button',\n `tree-button--${props.variant}`,\n `tree-button--${props.size}`,\n {\n 'is-loading': props.loading,\n 'is-disabled': isDisabled.value,\n },\n]);\n\nconst onClick = (event: MouseEvent) => {\n if (isDisabled.value) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n emit('click', event);\n};\n</script>\n\n<template>\n <component\n :is=\"as\"\n :type=\"isNativeButton ? type : undefined\"\n :class=\"classes\"\n :disabled=\"isNativeButton ? isDisabled : undefined\"\n :aria-disabled=\"!isNativeButton && isDisabled ? 'true' : undefined\"\n :aria-busy=\"loading || undefined\"\n :tabindex=\"!isNativeButton && isDisabled ? -1 : undefined\"\n @click=\"onClick\"\n >\n <span\n v-if=\"loading\"\n class=\"tree-button__spinner\"\n >\n <TreeSpinner\n size=\"sm\"\n label=\"Loading\"\n />\n </span>\n <span\n v-if=\"$slots.icon\"\n class=\"tree-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span class=\"tree-button__label\">\n <slot />\n </span>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeCardVariant, TreeSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TreeCardVariant;\n size?: TreeSize;\n title?: string;\n }>(),\n {\n as: 'section',\n variant: 'outline',\n size: 'md',\n title: undefined,\n },\n);\n\nconst classes = computed(() => [\n 'tree-card',\n `tree-card--${props.variant}`,\n `tree-card--${props.size}`,\n]);\n\nconst hasHeader = computed(() => !!props.title);\n</script>\n\n<template>\n <component\n :is=\"as\"\n :class=\"classes\"\n >\n <header\n v-if=\"$slots.header || hasHeader || $slots.actions\"\n class=\"tree-card__header\"\n >\n <slot name=\"header\">\n <span\n v-if=\"title\"\n class=\"tree-card__title\"\n >\n {{ title }}\n </span>\n <span\n v-if=\"$slots.actions\"\n class=\"tree-card__actions\"\n >\n <slot name=\"actions\" />\n </span>\n </slot>\n </header>\n <div class=\"tree-card__body\">\n <slot />\n </div>\n <footer\n v-if=\"$slots.footer\"\n class=\"tree-card__footer\"\n >\n <slot name=\"footer\" />\n </footer>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeCardVariant, TreeSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TreeCardVariant;\n size?: TreeSize;\n title?: string;\n }>(),\n {\n as: 'section',\n variant: 'outline',\n size: 'md',\n title: undefined,\n },\n);\n\nconst classes = computed(() => [\n 'tree-card',\n `tree-card--${props.variant}`,\n `tree-card--${props.size}`,\n]);\n\nconst hasHeader = computed(() => !!props.title);\n</script>\n\n<template>\n <component\n :is=\"as\"\n :class=\"classes\"\n >\n <header\n v-if=\"$slots.header || hasHeader || $slots.actions\"\n class=\"tree-card__header\"\n >\n <slot name=\"header\">\n <span\n v-if=\"title\"\n class=\"tree-card__title\"\n >\n {{ title }}\n </span>\n <span\n v-if=\"$slots.actions\"\n class=\"tree-card__actions\"\n >\n <slot name=\"actions\" />\n </span>\n </slot>\n </header>\n <div class=\"tree-card__body\">\n <slot />\n </div>\n <footer\n v-if=\"$slots.footer\"\n class=\"tree-card__footer\"\n >\n <slot name=\"footer\" />\n </footer>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n indeterminate?: boolean;\n invalid?: boolean;\n }>(),\n {\n modelValue: false,\n size: 'md',\n disabled: false,\n indeterminate: false,\n invalid: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nwatch(\n () => props.indeterminate,\n (val) => {\n if (inputRef.value) {\n inputRef.value.indeterminate = val;\n }\n },\n);\n\nwatch(inputRef, (el) => {\n if (el) {\n el.indeterminate = props.indeterminate;\n }\n});\n\nconst rootClasses = computed(() => [\n 'tree-checkbox',\n `tree-checkbox--${props.size}`,\n {\n 'is-checked': props.modelValue,\n 'is-indeterminate': props.indeterminate,\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n emit('update:modelValue', !props.modelValue);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n ref=\"inputRef\"\n v-bind=\"inputAttrs\"\n type=\"checkbox\"\n class=\"tree-checkbox__input\"\n :checked=\"modelValue\"\n :disabled=\"disabled\"\n :aria-checked=\"indeterminate ? 'mixed' : modelValue\"\n :aria-invalid=\"invalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"tree-checkbox__control\"\n aria-hidden=\"true\"\n >\n <svg\n v-if=\"modelValue && !indeterminate\"\n class=\"tree-checkbox__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n <svg\n v-else-if=\"indeterminate\"\n class=\"tree-checkbox__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n >\n <line\n x1=\"4\"\n y1=\"8\"\n x2=\"12\"\n y2=\"8\"\n />\n </svg>\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"tree-checkbox__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n indeterminate?: boolean;\n invalid?: boolean;\n }>(),\n {\n modelValue: false,\n size: 'md',\n disabled: false,\n indeterminate: false,\n invalid: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nwatch(\n () => props.indeterminate,\n (val) => {\n if (inputRef.value) {\n inputRef.value.indeterminate = val;\n }\n },\n);\n\nwatch(inputRef, (el) => {\n if (el) {\n el.indeterminate = props.indeterminate;\n }\n});\n\nconst rootClasses = computed(() => [\n 'tree-checkbox',\n `tree-checkbox--${props.size}`,\n {\n 'is-checked': props.modelValue,\n 'is-indeterminate': props.indeterminate,\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n emit('update:modelValue', !props.modelValue);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n ref=\"inputRef\"\n v-bind=\"inputAttrs\"\n type=\"checkbox\"\n class=\"tree-checkbox__input\"\n :checked=\"modelValue\"\n :disabled=\"disabled\"\n :aria-checked=\"indeterminate ? 'mixed' : modelValue\"\n :aria-invalid=\"invalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"tree-checkbox__control\"\n aria-hidden=\"true\"\n >\n <svg\n v-if=\"modelValue && !indeterminate\"\n class=\"tree-checkbox__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n <svg\n v-else-if=\"indeterminate\"\n class=\"tree-checkbox__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n >\n <line\n x1=\"4\"\n y1=\"8\"\n x2=\"12\"\n y2=\"8\"\n />\n </svg>\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"tree-checkbox__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","import { computed, ref, type Ref } from 'vue';\n\nexport const useControllableOpen = (\n controlledValue: Ref<boolean | undefined>,\n defaultValue: boolean,\n onChange: (value: boolean) => void,\n) => {\n const uncontrolledValue = ref(defaultValue);\n\n const value = computed(() => controlledValue.value ?? uncontrolledValue.value);\n\n const setValue = (nextValue: boolean) => {\n if (nextValue === value.value) {\n return;\n }\n\n if (controlledValue.value === undefined) {\n uncontrolledValue.value = nextValue;\n }\n\n onChange(nextValue);\n };\n\n return {\n value,\n setValue,\n };\n};\n\n","<script setup lang=\"ts\">\nimport { createId, isEscapeKey } from '@treeui/utils';\nimport { computed, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeComboboxOption {\n label: string;\n value: string;\n description?: string;\n keywords?: string[];\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n options?: TreeComboboxOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n emptyText?: string;\n }>(),\n {\n modelValue: '',\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n emptyText: 'No results found.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n 'input-change': [value: string];\n}>();\n\ndefineSlots<{\n prefix?: () => unknown;\n option?: (props: {\n option: TreeComboboxOption;\n selected: boolean;\n active: boolean;\n }) => unknown;\n empty?: (props: { query: string }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('tree-combobox');\nconst rootRef = ref<HTMLElement | null>(null);\nconst activeIndex = ref(-1);\nconst query = ref('');\n\nconst normalize = (value: string) => value.trim().toLowerCase();\nconst getOptionId = (value: string) => `${listboxId}-option-${value}`;\n\nconst selectedOption = computed(() =>\n props.options.find((option) => option.value === props.modelValue),\n);\n\nconst selectedLabel = computed(() => selectedOption.value?.label ?? '');\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, autocomplete, ...rest } = attrs;\n return {\n autocomplete: typeof autocomplete === 'string' ? autocomplete : 'off',\n ...rest,\n };\n});\n\nconst listboxLabel = computed(() =>\n typeof attrs['aria-label'] === 'string' ? attrs['aria-label'] : undefined,\n);\n\nconst listboxLabelledby = computed(() =>\n typeof attrs['aria-labelledby'] === 'string' ? attrs['aria-labelledby'] : undefined,\n);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-combobox',\n `tree-combobox--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst filteredOptions = computed(() => {\n const normalizedQuery = normalize(query.value);\n\n if (!normalizedQuery) {\n return props.options;\n }\n\n return props.options.filter((option) => {\n const fields = [\n option.label,\n option.description ?? '',\n ...(option.keywords ?? []),\n ];\n\n return fields.some((field) => field.toLowerCase().includes(normalizedQuery));\n });\n});\n\nconst enabledFilteredIndexes = computed(() =>\n filteredOptions.value.reduce<number[]>((indexes, option, index) => {\n if (!option.disabled) {\n indexes.push(index);\n }\n\n return indexes;\n }, []),\n);\n\nconst activeOption = computed(() =>\n activeIndex.value >= 0 ? filteredOptions.value[activeIndex.value] : undefined,\n);\n\nconst activeDescendant = computed(() =>\n isOpen.value && activeOption.value ? getOptionId(activeOption.value.value) : undefined,\n);\n\nconst syncQueryFromSelection = () => {\n query.value = selectedLabel.value;\n};\n\nconst setInitialActiveIndex = (fallback: 'first' | 'last' = 'first') => {\n const selectedIndex = filteredOptions.value.findIndex((option) =>\n option.value === props.modelValue && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n activeIndex.value = selectedIndex;\n return;\n }\n\n if (enabledFilteredIndexes.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n activeIndex.value =\n fallback === 'last'\n ? enabledFilteredIndexes.value[enabledFilteredIndexes.value.length - 1]\n : enabledFilteredIndexes.value[0];\n};\n\nconst moveActive = (direction: 1 | -1) => {\n if (enabledFilteredIndexes.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const currentEnabledIndex = enabledFilteredIndexes.value.indexOf(activeIndex.value);\n\n if (currentEnabledIndex === -1) {\n activeIndex.value =\n direction === 1\n ? enabledFilteredIndexes.value[0]\n : enabledFilteredIndexes.value[enabledFilteredIndexes.value.length - 1];\n return;\n }\n\n const nextEnabledIndex = currentEnabledIndex + direction;\n\n if (nextEnabledIndex < 0 || nextEnabledIndex >= enabledFilteredIndexes.value.length) {\n return;\n }\n\n activeIndex.value = enabledFilteredIndexes.value[nextEnabledIndex];\n};\n\nconst openListbox = (fallback: 'first' | 'last' = 'first') => {\n if (props.disabled) {\n return;\n }\n\n setValue(true);\n setInitialActiveIndex(fallback);\n};\n\nconst commitPendingClear = () => {\n if (query.value.trim() !== '' || !props.modelValue) {\n return false;\n }\n\n emit('update:modelValue', '');\n return true;\n};\n\nconst closeListbox = (restoreSelection = false) => {\n setValue(false);\n activeIndex.value = -1;\n\n if (!restoreSelection) {\n return;\n }\n\n if (commitPendingClear()) {\n return;\n }\n\n if (selectedLabel.value && query.value !== selectedLabel.value) {\n query.value = selectedLabel.value;\n }\n};\n\nconst selectOption = (option: TreeComboboxOption) => {\n if (option.disabled) {\n return;\n }\n\n query.value = option.label;\n emit('update:modelValue', option.value);\n closeListbox(false);\n};\n\nconst onInput = (event: Event) => {\n query.value = (event.target as HTMLInputElement).value;\n emit('input-change', query.value);\n\n if (props.disabled) {\n return;\n }\n\n if (!isOpen.value) {\n openListbox('first');\n return;\n }\n\n setInitialActiveIndex('first');\n};\n\nconst onInputFocus = () => {\n openListbox('first');\n};\n\nconst onInputClick = () => {\n if (!isOpen.value) {\n openListbox('first');\n }\n};\n\nconst onInputKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event)) {\n if (isOpen.value) {\n event.preventDefault();\n closeListbox(true);\n }\n\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('first');\n } else {\n moveActive(1);\n }\n break;\n case 'ArrowUp':\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('last');\n } else {\n moveActive(-1);\n }\n break;\n case 'Enter':\n if (isOpen.value && activeOption.value && !activeOption.value.disabled) {\n event.preventDefault();\n selectOption(activeOption.value);\n }\n break;\n case 'Home':\n if (!isOpen.value) return;\n event.preventDefault();\n setInitialActiveIndex('first');\n break;\n case 'End':\n if (!isOpen.value) return;\n event.preventDefault();\n setInitialActiveIndex('last');\n break;\n case 'Tab':\n closeListbox(true);\n break;\n default:\n break;\n }\n};\n\nconst onOptionPointerEnter = (index: number) => {\n const option = filteredOptions.value[index];\n\n if (option && !option.disabled) {\n activeIndex.value = index;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeListbox(true);\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nwatch(\n () => props.modelValue,\n () => {\n if (!isOpen.value) {\n syncQueryFromSelection();\n }\n },\n { immediate: true },\n);\n\nwatch(\n () => props.options,\n () => {\n if (!isOpen.value) {\n syncQueryFromSelection();\n return;\n }\n\n setInitialActiveIndex('first');\n },\n { deep: true },\n);\n\nwatch(filteredOptions, () => {\n if (!isOpen.value) {\n return;\n }\n\n if (filteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const current = filteredOptions.value[activeIndex.value];\n\n if (!current || current.disabled) {\n setInitialActiveIndex('first');\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div class=\"tree-combobox__control\">\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-combobox__slot tree-combobox__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"tree-combobox__input\"\n role=\"combobox\"\n type=\"text\"\n :value=\"query\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n :aria-expanded=\"isOpen\"\n :aria-activedescendant=\"activeDescendant\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n @input=\"onInput\"\n @focus=\"onInputFocus\"\n @click=\"onInputClick\"\n @keydown=\"onInputKeydown\"\n >\n <TreeSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <svg\n v-else\n class=\"tree-combobox__indicator\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </div>\n\n <transition name=\"tree-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"listboxId\"\n role=\"listbox\"\n class=\"tree-combobox__listbox\"\n :aria-label=\"listboxLabel\"\n :aria-labelledby=\"listboxLabelledby\"\n >\n <li\n v-if=\"filteredOptions.length === 0\"\n class=\"tree-combobox__empty\"\n >\n <slot\n name=\"empty\"\n :query=\"query\"\n >\n {{ emptyText }}\n </slot>\n </li>\n\n <template v-else>\n <li\n v-for=\"(option, index) in filteredOptions\"\n :id=\"getOptionId(option.value)\"\n :key=\"option.value\"\n role=\"option\"\n class=\"tree-combobox__option\"\n :class=\"{\n 'is-active': index === activeIndex,\n 'is-disabled': option.disabled,\n 'is-selected': option.value === modelValue,\n }\"\n :aria-selected=\"option.value === modelValue\"\n :aria-disabled=\"option.disabled || undefined\"\n @mouseenter=\"onOptionPointerEnter(index)\"\n @click=\"selectOption(option)\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"option.value === modelValue\"\n :active=\"index === activeIndex\"\n >\n <span class=\"tree-combobox__option-copy\">\n <span class=\"tree-combobox__option-label\">{{ option.label }}</span>\n <span\n v-if=\"option.description\"\n class=\"tree-combobox__option-description\"\n >\n {{ option.description }}\n </span>\n </span>\n <svg\n v-if=\"option.value === modelValue\"\n class=\"tree-combobox__check\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n </slot>\n </li>\n </template>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isEscapeKey } from '@treeui/utils';\nimport { computed, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeComboboxOption {\n label: string;\n value: string;\n description?: string;\n keywords?: string[];\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n options?: TreeComboboxOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n emptyText?: string;\n }>(),\n {\n modelValue: '',\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n emptyText: 'No results found.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n 'input-change': [value: string];\n}>();\n\ndefineSlots<{\n prefix?: () => unknown;\n option?: (props: {\n option: TreeComboboxOption;\n selected: boolean;\n active: boolean;\n }) => unknown;\n empty?: (props: { query: string }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('tree-combobox');\nconst rootRef = ref<HTMLElement | null>(null);\nconst activeIndex = ref(-1);\nconst query = ref('');\n\nconst normalize = (value: string) => value.trim().toLowerCase();\nconst getOptionId = (value: string) => `${listboxId}-option-${value}`;\n\nconst selectedOption = computed(() =>\n props.options.find((option) => option.value === props.modelValue),\n);\n\nconst selectedLabel = computed(() => selectedOption.value?.label ?? '');\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, autocomplete, ...rest } = attrs;\n return {\n autocomplete: typeof autocomplete === 'string' ? autocomplete : 'off',\n ...rest,\n };\n});\n\nconst listboxLabel = computed(() =>\n typeof attrs['aria-label'] === 'string' ? attrs['aria-label'] : undefined,\n);\n\nconst listboxLabelledby = computed(() =>\n typeof attrs['aria-labelledby'] === 'string' ? attrs['aria-labelledby'] : undefined,\n);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-combobox',\n `tree-combobox--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst filteredOptions = computed(() => {\n const normalizedQuery = normalize(query.value);\n\n if (!normalizedQuery) {\n return props.options;\n }\n\n return props.options.filter((option) => {\n const fields = [\n option.label,\n option.description ?? '',\n ...(option.keywords ?? []),\n ];\n\n return fields.some((field) => field.toLowerCase().includes(normalizedQuery));\n });\n});\n\nconst enabledFilteredIndexes = computed(() =>\n filteredOptions.value.reduce<number[]>((indexes, option, index) => {\n if (!option.disabled) {\n indexes.push(index);\n }\n\n return indexes;\n }, []),\n);\n\nconst activeOption = computed(() =>\n activeIndex.value >= 0 ? filteredOptions.value[activeIndex.value] : undefined,\n);\n\nconst activeDescendant = computed(() =>\n isOpen.value && activeOption.value ? getOptionId(activeOption.value.value) : undefined,\n);\n\nconst syncQueryFromSelection = () => {\n query.value = selectedLabel.value;\n};\n\nconst setInitialActiveIndex = (fallback: 'first' | 'last' = 'first') => {\n const selectedIndex = filteredOptions.value.findIndex((option) =>\n option.value === props.modelValue && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n activeIndex.value = selectedIndex;\n return;\n }\n\n if (enabledFilteredIndexes.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n activeIndex.value =\n fallback === 'last'\n ? enabledFilteredIndexes.value[enabledFilteredIndexes.value.length - 1]\n : enabledFilteredIndexes.value[0];\n};\n\nconst moveActive = (direction: 1 | -1) => {\n if (enabledFilteredIndexes.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const currentEnabledIndex = enabledFilteredIndexes.value.indexOf(activeIndex.value);\n\n if (currentEnabledIndex === -1) {\n activeIndex.value =\n direction === 1\n ? enabledFilteredIndexes.value[0]\n : enabledFilteredIndexes.value[enabledFilteredIndexes.value.length - 1];\n return;\n }\n\n const nextEnabledIndex = currentEnabledIndex + direction;\n\n if (nextEnabledIndex < 0 || nextEnabledIndex >= enabledFilteredIndexes.value.length) {\n return;\n }\n\n activeIndex.value = enabledFilteredIndexes.value[nextEnabledIndex];\n};\n\nconst openListbox = (fallback: 'first' | 'last' = 'first') => {\n if (props.disabled) {\n return;\n }\n\n setValue(true);\n setInitialActiveIndex(fallback);\n};\n\nconst commitPendingClear = () => {\n if (query.value.trim() !== '' || !props.modelValue) {\n return false;\n }\n\n emit('update:modelValue', '');\n return true;\n};\n\nconst closeListbox = (restoreSelection = false) => {\n setValue(false);\n activeIndex.value = -1;\n\n if (!restoreSelection) {\n return;\n }\n\n if (commitPendingClear()) {\n return;\n }\n\n if (selectedLabel.value && query.value !== selectedLabel.value) {\n query.value = selectedLabel.value;\n }\n};\n\nconst selectOption = (option: TreeComboboxOption) => {\n if (option.disabled) {\n return;\n }\n\n query.value = option.label;\n emit('update:modelValue', option.value);\n closeListbox(false);\n};\n\nconst onInput = (event: Event) => {\n query.value = (event.target as HTMLInputElement).value;\n emit('input-change', query.value);\n\n if (props.disabled) {\n return;\n }\n\n if (!isOpen.value) {\n openListbox('first');\n return;\n }\n\n setInitialActiveIndex('first');\n};\n\nconst onInputFocus = () => {\n openListbox('first');\n};\n\nconst onInputClick = () => {\n if (!isOpen.value) {\n openListbox('first');\n }\n};\n\nconst onInputKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event)) {\n if (isOpen.value) {\n event.preventDefault();\n closeListbox(true);\n }\n\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('first');\n } else {\n moveActive(1);\n }\n break;\n case 'ArrowUp':\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('last');\n } else {\n moveActive(-1);\n }\n break;\n case 'Enter':\n if (isOpen.value && activeOption.value && !activeOption.value.disabled) {\n event.preventDefault();\n selectOption(activeOption.value);\n }\n break;\n case 'Home':\n if (!isOpen.value) return;\n event.preventDefault();\n setInitialActiveIndex('first');\n break;\n case 'End':\n if (!isOpen.value) return;\n event.preventDefault();\n setInitialActiveIndex('last');\n break;\n case 'Tab':\n closeListbox(true);\n break;\n default:\n break;\n }\n};\n\nconst onOptionPointerEnter = (index: number) => {\n const option = filteredOptions.value[index];\n\n if (option && !option.disabled) {\n activeIndex.value = index;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeListbox(true);\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nwatch(\n () => props.modelValue,\n () => {\n if (!isOpen.value) {\n syncQueryFromSelection();\n }\n },\n { immediate: true },\n);\n\nwatch(\n () => props.options,\n () => {\n if (!isOpen.value) {\n syncQueryFromSelection();\n return;\n }\n\n setInitialActiveIndex('first');\n },\n { deep: true },\n);\n\nwatch(filteredOptions, () => {\n if (!isOpen.value) {\n return;\n }\n\n if (filteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const current = filteredOptions.value[activeIndex.value];\n\n if (!current || current.disabled) {\n setInitialActiveIndex('first');\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div class=\"tree-combobox__control\">\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-combobox__slot tree-combobox__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"tree-combobox__input\"\n role=\"combobox\"\n type=\"text\"\n :value=\"query\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n :aria-expanded=\"isOpen\"\n :aria-activedescendant=\"activeDescendant\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n @input=\"onInput\"\n @focus=\"onInputFocus\"\n @click=\"onInputClick\"\n @keydown=\"onInputKeydown\"\n >\n <TreeSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <svg\n v-else\n class=\"tree-combobox__indicator\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </div>\n\n <transition name=\"tree-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"listboxId\"\n role=\"listbox\"\n class=\"tree-combobox__listbox\"\n :aria-label=\"listboxLabel\"\n :aria-labelledby=\"listboxLabelledby\"\n >\n <li\n v-if=\"filteredOptions.length === 0\"\n class=\"tree-combobox__empty\"\n >\n <slot\n name=\"empty\"\n :query=\"query\"\n >\n {{ emptyText }}\n </slot>\n </li>\n\n <template v-else>\n <li\n v-for=\"(option, index) in filteredOptions\"\n :id=\"getOptionId(option.value)\"\n :key=\"option.value\"\n role=\"option\"\n class=\"tree-combobox__option\"\n :class=\"{\n 'is-active': index === activeIndex,\n 'is-disabled': option.disabled,\n 'is-selected': option.value === modelValue,\n }\"\n :aria-selected=\"option.value === modelValue\"\n :aria-disabled=\"option.disabled || undefined\"\n @mouseenter=\"onOptionPointerEnter(index)\"\n @click=\"selectOption(option)\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"option.value === modelValue\"\n :active=\"index === activeIndex\"\n >\n <span class=\"tree-combobox__option-copy\">\n <span class=\"tree-combobox__option-label\">{{ option.label }}</span>\n <span\n v-if=\"option.description\"\n class=\"tree-combobox__option-description\"\n >\n {{ option.description }}\n </span>\n </span>\n <svg\n v-if=\"option.value === modelValue\"\n class=\"tree-combobox__check\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n </slot>\n </li>\n </template>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n createId,\n focusFirst,\n focusLast,\n getFocusableElements,\n isEscapeKey,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('tree-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['tree-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 'tree-modal__surface',\n `tree-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\n};\n\nconst focusSurface = () => {\n nextTick(() => {\n if (!surfaceRef.value) {\n return;\n }\n\n const focused = focusFirst(surfaceRef.value);\n if (!focused) {\n surfaceRef.value.focus();\n }\n });\n};\n\nconst openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\n return;\n }\n\n if (event.key !== 'Tab' || !surfaceRef.value) {\n return;\n }\n\n const focusable = getFocusableElements(surfaceRef.value);\n\n if (!focusable.length) {\n event.preventDefault();\n surfaceRef.value.focus();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n focusLast(surfaceRef.value);\n }\n\n if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n focusFirst(surfaceRef.value);\n }\n};\n\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"tree-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"tree-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"tree-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"tree-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"tree-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"tree-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"tree-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"tree-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"tree-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"tree-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"tree-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"tree-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n createId,\n focusFirst,\n focusLast,\n getFocusableElements,\n isEscapeKey,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('tree-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['tree-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 'tree-modal__surface',\n `tree-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\n};\n\nconst focusSurface = () => {\n nextTick(() => {\n if (!surfaceRef.value) {\n return;\n }\n\n const focused = focusFirst(surfaceRef.value);\n if (!focused) {\n surfaceRef.value.focus();\n }\n });\n};\n\nconst openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\n return;\n }\n\n if (event.key !== 'Tab' || !surfaceRef.value) {\n return;\n }\n\n const focusable = getFocusableElements(surfaceRef.value);\n\n if (!focusable.length) {\n event.preventDefault();\n surfaceRef.value.focus();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n focusLast(surfaceRef.value);\n }\n\n if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n focusFirst(surfaceRef.value);\n }\n};\n\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"tree-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"tree-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"tree-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"tree-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"tree-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"tree-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"tree-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"tree-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"tree-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"tree-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"tree-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"tree-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, toRef, useAttrs } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize, TreeVariant } from '../types/contracts';\nimport TreeButton from './TreeButton.vue';\nimport TreeModal from './TreeModal.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst slots = defineSlots<{\n trigger?: () => unknown;\n icon?: () => unknown;\n default?: () => unknown;\n actions?: (props: {\n confirm: () => void;\n cancel: () => void;\n loading: boolean;\n }) => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n title?: string;\n description?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n confirmVariant?: TreeVariant;\n confirmDisabled?: boolean;\n cancelDisabled?: boolean;\n loading?: boolean;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n closeOnConfirm?: boolean;\n closeOnCancel?: boolean;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'sm',\n title: '',\n description: '',\n confirmLabel: 'Confirm',\n cancelLabel: 'Cancel',\n confirmVariant: 'danger',\n confirmDisabled: false,\n cancelDisabled: false,\n loading: false,\n closeOnEscape: true,\n closeOnOverlay: false,\n showCloseButton: false,\n closeLabel: 'Close dialog',\n closeOnConfirm: true,\n closeOnCancel: true,\n },\n);\n\nconst emit = defineEmits<{\n confirm: [];\n cancel: [];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst dialogClasses = computed(() => [\n 'tree-confirm-dialog',\n {\n 'tree-confirm-dialog--with-icon': Boolean(slots.icon),\n },\n]);\n\nconst hasBodyContent = computed(() => Boolean(slots.default));\n\nconst closeDialog = () => {\n setValue(false);\n};\n\nconst syncOpen = (value: boolean) => {\n setValue(value);\n};\n\nconst handleCancel = () => {\n if (props.cancelDisabled) {\n return;\n }\n\n emit('cancel');\n\n if (props.closeOnCancel) {\n closeDialog();\n }\n};\n\nconst handleConfirm = () => {\n if (props.confirmDisabled || props.loading) {\n return;\n }\n\n emit('confirm');\n\n if (props.closeOnConfirm) {\n closeDialog();\n }\n};\n</script>\n\n<template>\n <TreeModal\n v-bind=\"attrs\"\n :open=\"isOpen\"\n :disabled=\"disabled\"\n :size=\"size\"\n :title=\"title\"\n :description=\"description\"\n :close-on-escape=\"closeOnEscape\"\n :close-on-overlay=\"closeOnOverlay\"\n :show-close-button=\"showCloseButton\"\n :close-label=\"closeLabel\"\n @update:open=\"syncOpen\"\n >\n <template\n v-if=\"$slots.trigger\"\n #trigger\n >\n <slot name=\"trigger\" />\n </template>\n\n <template #content>\n <div :class=\"dialogClasses\">\n <div\n v-if=\"$slots.icon\"\n class=\"tree-confirm-dialog__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div\n v-if=\"hasBodyContent\"\n class=\"tree-confirm-dialog__body\"\n >\n <slot />\n </div>\n </div>\n </template>\n\n <template #footer>\n <slot\n name=\"actions\"\n :confirm=\"handleConfirm\"\n :cancel=\"handleCancel\"\n :loading=\"loading\"\n >\n <TreeButton\n variant=\"ghost\"\n :disabled=\"cancelDisabled\"\n @click=\"handleCancel\"\n >\n {{ cancelLabel }}\n </TreeButton>\n <TreeButton\n :variant=\"confirmVariant\"\n :loading=\"loading\"\n :disabled=\"confirmDisabled\"\n @click=\"handleConfirm\"\n >\n {{ confirmLabel }}\n </TreeButton>\n </slot>\n </template>\n </TreeModal>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, toRef, useAttrs } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize, TreeVariant } from '../types/contracts';\nimport TreeButton from './TreeButton.vue';\nimport TreeModal from './TreeModal.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst slots = defineSlots<{\n trigger?: () => unknown;\n icon?: () => unknown;\n default?: () => unknown;\n actions?: (props: {\n confirm: () => void;\n cancel: () => void;\n loading: boolean;\n }) => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n title?: string;\n description?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n confirmVariant?: TreeVariant;\n confirmDisabled?: boolean;\n cancelDisabled?: boolean;\n loading?: boolean;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n closeOnConfirm?: boolean;\n closeOnCancel?: boolean;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'sm',\n title: '',\n description: '',\n confirmLabel: 'Confirm',\n cancelLabel: 'Cancel',\n confirmVariant: 'danger',\n confirmDisabled: false,\n cancelDisabled: false,\n loading: false,\n closeOnEscape: true,\n closeOnOverlay: false,\n showCloseButton: false,\n closeLabel: 'Close dialog',\n closeOnConfirm: true,\n closeOnCancel: true,\n },\n);\n\nconst emit = defineEmits<{\n confirm: [];\n cancel: [];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst dialogClasses = computed(() => [\n 'tree-confirm-dialog',\n {\n 'tree-confirm-dialog--with-icon': Boolean(slots.icon),\n },\n]);\n\nconst hasBodyContent = computed(() => Boolean(slots.default));\n\nconst closeDialog = () => {\n setValue(false);\n};\n\nconst syncOpen = (value: boolean) => {\n setValue(value);\n};\n\nconst handleCancel = () => {\n if (props.cancelDisabled) {\n return;\n }\n\n emit('cancel');\n\n if (props.closeOnCancel) {\n closeDialog();\n }\n};\n\nconst handleConfirm = () => {\n if (props.confirmDisabled || props.loading) {\n return;\n }\n\n emit('confirm');\n\n if (props.closeOnConfirm) {\n closeDialog();\n }\n};\n</script>\n\n<template>\n <TreeModal\n v-bind=\"attrs\"\n :open=\"isOpen\"\n :disabled=\"disabled\"\n :size=\"size\"\n :title=\"title\"\n :description=\"description\"\n :close-on-escape=\"closeOnEscape\"\n :close-on-overlay=\"closeOnOverlay\"\n :show-close-button=\"showCloseButton\"\n :close-label=\"closeLabel\"\n @update:open=\"syncOpen\"\n >\n <template\n v-if=\"$slots.trigger\"\n #trigger\n >\n <slot name=\"trigger\" />\n </template>\n\n <template #content>\n <div :class=\"dialogClasses\">\n <div\n v-if=\"$slots.icon\"\n class=\"tree-confirm-dialog__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div\n v-if=\"hasBodyContent\"\n class=\"tree-confirm-dialog__body\"\n >\n <slot />\n </div>\n </div>\n </template>\n\n <template #footer>\n <slot\n name=\"actions\"\n :confirm=\"handleConfirm\"\n :cancel=\"handleCancel\"\n :loading=\"loading\"\n >\n <TreeButton\n variant=\"ghost\"\n :disabled=\"cancelDisabled\"\n @click=\"handleCancel\"\n >\n {{ cancelLabel }}\n </TreeButton>\n <TreeButton\n :variant=\"confirmVariant\"\n :loading=\"loading\"\n :disabled=\"confirmDisabled\"\n @click=\"handleConfirm\"\n >\n {{ confirmLabel }}\n </TreeButton>\n </slot>\n </template>\n </TreeModal>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeContainerSizes = ['sm', 'md', 'lg', 'xl', 'full'] as const;\n\nexport type TreeContainerSize = (typeof _treeContainerSizes)[number];\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TreeContainerSize;\n padded?: boolean;\n centered?: boolean;\n }>(),\n {\n as: 'div',\n size: 'lg',\n padded: true,\n centered: true,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-container',\n `tree-container--${props.size}`,\n {\n 'is-padded': props.padded,\n 'is-centered': props.centered,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeContainerSizes = ['sm', 'md', 'lg', 'xl', 'full'] as const;\n\nexport type TreeContainerSize = (typeof _treeContainerSizes)[number];\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TreeContainerSize;\n padded?: boolean;\n centered?: boolean;\n }>(),\n {\n as: 'div',\n size: 'lg',\n padded: true,\n centered: true,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-container',\n `tree-container--${props.size}`,\n {\n 'is-padded': props.padded,\n 'is-centered': props.centered,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\n\nexport interface TreeContextMenuItem {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TreeContextMenuItem[];\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n }>(),\n {\n items: () => [],\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n },\n);\n\nconst emit = defineEmits<{\n select: [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n default(): unknown;\n item(props: { item: TreeContextMenuItem; index: number }): unknown;\n}>();\n\nconst menuId = createId('tree-context-menu');\nconst rootRef = ref<HTMLElement | null>(null);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\nconst menuPosition = ref({ x: 0, y: 0 });\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-context-menu',\n `tree-context-menu--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-open': isOpen.value,\n },\n]);\n\nconst enabledItems = computed(() => props.items.filter((i) => !i.disabled));\n\nconst openMenu = (x: number, y: number) => {\n if (props.disabled) return;\n menuPosition.value = { x, y };\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n setValue(true);\n nextTick(() => focusItem(focusedIndex.value));\n};\n\nconst closeMenu = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => rootRef.value?.focus());\n }\n};\n\nconst selectItem = (item: TreeContextMenuItem) => {\n if (item.disabled) return;\n emit('select', item.value);\n closeMenu(true);\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n if (!item) return;\n const el = itemRefs.value.get(item.value);\n el?.focus();\n};\n\nconst setItemRef = (el: Element | null, value: string) => {\n if (el instanceof HTMLElement) {\n itemRefs.value.set(value, el);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.items.length) {\n if (!props.items[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusItem(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onContextMenu = (event: MouseEvent) => {\n if (props.disabled) return;\n event.preventDefault();\n openMenu(event.clientX, event.clientY);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, item: TreeContextMenuItem) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeMenu(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(item);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n focusItem(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[enabledItems.value.length - 1])\n : props.items.length - 1;\n focusItem(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n const menuEl = document.getElementById(menuId);\n if (menuEl?.contains(target)) return;\n closeMenu();\n};\n\nconst onDocumentContextMenu = (event: MouseEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeMenu();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n document.addEventListener('contextmenu', onDocumentContextMenu);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n document.removeEventListener('contextmenu', onDocumentContextMenu);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n document.removeEventListener('contextmenu', onDocumentContextMenu);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n @contextmenu=\"onContextMenu\"\n >\n <slot />\n <Teleport to=\"body\">\n <transition name=\"tree-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"menuId\"\n role=\"menu\"\n class=\"tree-context-menu__menu\"\n :class=\"`tree-context-menu--${size}`\"\n :style=\"{ top: `${menuPosition.y}px`, left: `${menuPosition.x}px` }\"\n aria-label=\"Context menu\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n :ref=\"(el) => setItemRef(el as Element | null, item.value)\"\n role=\"menuitem\"\n class=\"tree-context-menu__item\"\n :class=\"{\n 'is-disabled': item.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-disabled=\"item.disabled || undefined\"\n :tabindex=\"item.disabled ? -1 : 0\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n {{ item.label }}\n </slot>\n </li>\n </ul>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\n\nexport interface TreeContextMenuItem {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TreeContextMenuItem[];\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n }>(),\n {\n items: () => [],\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n },\n);\n\nconst emit = defineEmits<{\n select: [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n default(): unknown;\n item(props: { item: TreeContextMenuItem; index: number }): unknown;\n}>();\n\nconst menuId = createId('tree-context-menu');\nconst rootRef = ref<HTMLElement | null>(null);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\nconst menuPosition = ref({ x: 0, y: 0 });\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-context-menu',\n `tree-context-menu--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-open': isOpen.value,\n },\n]);\n\nconst enabledItems = computed(() => props.items.filter((i) => !i.disabled));\n\nconst openMenu = (x: number, y: number) => {\n if (props.disabled) return;\n menuPosition.value = { x, y };\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n setValue(true);\n nextTick(() => focusItem(focusedIndex.value));\n};\n\nconst closeMenu = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => rootRef.value?.focus());\n }\n};\n\nconst selectItem = (item: TreeContextMenuItem) => {\n if (item.disabled) return;\n emit('select', item.value);\n closeMenu(true);\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n if (!item) return;\n const el = itemRefs.value.get(item.value);\n el?.focus();\n};\n\nconst setItemRef = (el: Element | null, value: string) => {\n if (el instanceof HTMLElement) {\n itemRefs.value.set(value, el);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.items.length) {\n if (!props.items[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusItem(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onContextMenu = (event: MouseEvent) => {\n if (props.disabled) return;\n event.preventDefault();\n openMenu(event.clientX, event.clientY);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, item: TreeContextMenuItem) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeMenu(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(item);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n focusItem(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[enabledItems.value.length - 1])\n : props.items.length - 1;\n focusItem(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n const menuEl = document.getElementById(menuId);\n if (menuEl?.contains(target)) return;\n closeMenu();\n};\n\nconst onDocumentContextMenu = (event: MouseEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeMenu();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n document.addEventListener('contextmenu', onDocumentContextMenu);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n document.removeEventListener('contextmenu', onDocumentContextMenu);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n document.removeEventListener('contextmenu', onDocumentContextMenu);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n @contextmenu=\"onContextMenu\"\n >\n <slot />\n <Teleport to=\"body\">\n <transition name=\"tree-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"menuId\"\n role=\"menu\"\n class=\"tree-context-menu__menu\"\n :class=\"`tree-context-menu--${size}`\"\n :style=\"{ top: `${menuPosition.y}px`, left: `${menuPosition.x}px` }\"\n aria-label=\"Context menu\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n :ref=\"(el) => setItemRef(el as Element | null, item.value)\"\n role=\"menuitem\"\n class=\"tree-context-menu__item\"\n :class=\"{\n 'is-disabled': item.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-disabled=\"item.disabled || undefined\"\n :tabindex=\"item.disabled ? -1 : 0\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n {{ item.label }}\n </slot>\n </li>\n </ul>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n addDays,\n addMonths,\n createId,\n isActivationKey,\n isEscapeKey,\n isSameDay,\n parseDateValue,\n startOfDay,\n startOfMonth,\n startOfWeek,\n toDateValue,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n type ComponentPublicInstance,\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\ninterface CalendarCell {\n date: Date;\n dayLabel: number;\n disabled: boolean;\n inMonth: boolean;\n isFocused: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n}\n\nconst CalendarIcon = getTreeIcon('calendar');\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n open?: boolean;\n defaultOpen?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n invalid?: boolean;\n placeholder?: string;\n locale?: string;\n min?: string;\n max?: string;\n weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n id?: string;\n }>(),\n {\n modelValue: '',\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n invalid: false,\n placeholder: 'Select date',\n locale: 'en-US',\n min: '',\n max: '',\n weekStartsOn: 0,\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n select: [value: string];\n}>();\n\nconst attrs = useAttrs();\nconst today = startOfDay(new Date());\nconst selectedDate = computed(() => parseDateValue(props.modelValue));\nconst minDate = computed(() => parseDateValue(props.min));\nconst maxDate = computed(() => parseDateValue(props.max));\nconst calendarId = props.id ?? createId('tree-date-picker');\nconst captionId = `${calendarId}-caption`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst dayRefs = new Map<string, HTMLButtonElement>();\nconst viewMonth = ref(startOfMonth(selectedDate.value ?? today));\nconst focusedDate = ref<Date>(selectedDate.value ?? today);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, name: _name, ...rest } = attrs;\n return rest;\n});\n\nconst hiddenInputName = computed(() =>\n typeof attrs.name === 'string' ? attrs.name : undefined,\n);\n\nconst rootClasses = computed(() => [\n 'tree-date-picker',\n `tree-date-picker--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst triggerText = computed(() => {\n if (!selectedDate.value) {\n return props.placeholder;\n }\n\n return new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n }).format(selectedDate.value);\n});\n\nconst monthLabel = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n month: 'long',\n year: 'numeric',\n }).format(viewMonth.value),\n);\n\nconst weekdayLabels = computed(() => {\n const formatter = new Intl.DateTimeFormat(props.locale, { weekday: 'short' });\n const weekBase = startOfWeek(new Date(2024, 0, 7), props.weekStartsOn);\n\n return Array.from({ length: 7 }, (_, index) =>\n formatter.format(addDays(weekBase, index)),\n );\n});\n\nconst isDateDisabled = (date: Date) => {\n if (props.disabled) {\n return true;\n }\n\n if (minDate.value && date < minDate.value) {\n return true;\n }\n\n if (maxDate.value && date > maxDate.value) {\n return true;\n }\n\n return false;\n};\n\nconst syncCalendarView = (date: Date) => {\n focusedDate.value = startOfDay(date);\n viewMonth.value = startOfMonth(date);\n};\n\nwatch(\n selectedDate,\n (value) => {\n if (value) {\n syncCalendarView(value);\n return;\n }\n\n if (!isOpen.value) {\n syncCalendarView(today);\n }\n },\n { immediate: true },\n);\n\nconst cells = computed(() => {\n const startDate = startOfWeek(startOfMonth(viewMonth.value), props.weekStartsOn);\n\n return Array.from({ length: 6 }, (_, weekIndex) =>\n Array.from({ length: 7 }, (_, dayIndex) => {\n const date = addDays(startDate, weekIndex * 7 + dayIndex);\n const key = toDateValue(date);\n\n return {\n date,\n dayLabel: date.getDate(),\n disabled: isDateDisabled(date),\n inMonth: date.getMonth() === viewMonth.value.getMonth(),\n isFocused: isSameDay(date, focusedDate.value),\n isSelected: isSameDay(date, selectedDate.value),\n isToday: isSameDay(date, today),\n key,\n } satisfies CalendarCell;\n }),\n );\n});\n\nconst canMovePrev = computed(() => {\n if (!minDate.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) > startOfMonth(minDate.value);\n});\n\nconst canMoveNext = computed(() => {\n if (!maxDate.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) < startOfMonth(maxDate.value);\n});\n\nconst focusCurrentDay = () => {\n const key = toDateValue(focusedDate.value);\n nextTick(() => {\n dayRefs.get(key)?.focus();\n });\n};\n\nconst setDayRef = (\n element: Element | ComponentPublicInstance | null,\n key: string,\n) => {\n if (element instanceof HTMLButtonElement) {\n dayRefs.set(key, element);\n return;\n }\n\n dayRefs.delete(key);\n};\n\nconst openCalendar = () => {\n if (props.disabled) {\n return;\n }\n\n syncCalendarView(selectedDate.value ?? focusedDate.value ?? today);\n setValue(true);\n focusCurrentDay();\n};\n\nconst closeCalendar = (restoreFocus = false) => {\n setValue(false);\n\n if (restoreFocus) {\n nextTick(() => {\n triggerRef.value?.focus();\n });\n }\n};\n\nconst toggleCalendar = () => {\n if (isOpen.value) {\n closeCalendar();\n return;\n }\n\n openCalendar();\n};\n\nconst moveCalendar = (direction: 1 | -1) => {\n const nextMonth = addMonths(viewMonth.value, direction);\n syncCalendarView(nextMonth);\n focusCurrentDay();\n};\n\nconst moveFocus = (nextDate: Date) => {\n if (isDateDisabled(nextDate)) {\n return;\n }\n\n syncCalendarView(nextDate);\n focusCurrentDay();\n};\n\nconst selectDate = (date: Date) => {\n if (isDateDisabled(date)) {\n return;\n }\n\n const normalizedDate = startOfDay(date);\n const value = toDateValue(normalizedDate);\n\n syncCalendarView(normalizedDate);\n emit('update:modelValue', value);\n emit('select', value);\n closeCalendar(true);\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeCalendar();\n return;\n }\n\n if (\n isActivationKey(event) ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n openCalendar();\n }\n};\n\nconst onDayKeydown = (event: KeyboardEvent, date: Date) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeCalendar(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectDate(date);\n return;\n }\n\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(addDays(date, -1));\n break;\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(addDays(date, 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(addDays(date, -7));\n break;\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(addDays(date, 7));\n break;\n case 'Home':\n event.preventDefault();\n moveFocus(startOfWeek(date, props.weekStartsOn));\n break;\n case 'End':\n event.preventDefault();\n moveFocus(addDays(startOfWeek(date, props.weekStartsOn), 6));\n break;\n case 'PageUp':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? -12 : -1));\n break;\n case 'PageDown':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? 12 : 1));\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeCalendar();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n return;\n }\n\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <input\n v-if=\"hiddenInputName\"\n type=\"hidden\"\n :name=\"hiddenInputName\"\n :value=\"modelValue\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"tree-date-picker__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? calendarId : undefined\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n @click=\"toggleCalendar\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-date-picker__slot tree-date-picker__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <span\n class=\"tree-date-picker__value\"\n :data-placeholder=\"selectedDate ? undefined : true\"\n >\n {{ triggerText }}\n </span>\n <span class=\"tree-date-picker__slot tree-date-picker__slot--suffix\">\n <slot name=\"suffix\">\n <CalendarIcon v-bind=\"treeIconDefaults\" />\n </slot>\n </span>\n </button>\n\n <transition name=\"tree-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"calendarId\"\n class=\"tree-date-picker__content\"\n role=\"dialog\"\n aria-modal=\"false\"\n :aria-labelledby=\"captionId\"\n >\n <div class=\"tree-date-picker__header\">\n <button\n type=\"button\"\n class=\"tree-date-picker__nav\"\n :disabled=\"!canMovePrev\"\n aria-label=\"Previous month\"\n @click=\"moveCalendar(-1)\"\n >\n <ChevronLeftIcon v-bind=\"treeIconDefaults\" />\n </button>\n <p\n :id=\"captionId\"\n class=\"tree-date-picker__month\"\n >\n {{ monthLabel }}\n </p>\n <button\n type=\"button\"\n class=\"tree-date-picker__nav\"\n :disabled=\"!canMoveNext\"\n aria-label=\"Next month\"\n @click=\"moveCalendar(1)\"\n >\n <ChevronRightIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <div\n class=\"tree-date-picker__weekdays\"\n aria-hidden=\"true\"\n >\n <span\n v-for=\"label in weekdayLabels\"\n :key=\"label\"\n class=\"tree-date-picker__weekday\"\n >\n {{ label }}\n </span>\n </div>\n\n <div\n class=\"tree-date-picker__grid\"\n role=\"grid\"\n :aria-labelledby=\"captionId\"\n >\n <div\n v-for=\"(week, weekIndex) in cells\"\n :key=\"weekIndex\"\n class=\"tree-date-picker__row\"\n role=\"row\"\n >\n <div\n v-for=\"cell in week\"\n :key=\"cell.key\"\n class=\"tree-date-picker__cell\"\n role=\"gridcell\"\n :aria-selected=\"cell.isSelected\"\n >\n <button\n :ref=\"(element) => setDayRef(element, cell.key)\"\n type=\"button\"\n class=\"tree-date-picker__day\"\n :class=\"{\n 'is-muted': !cell.inMonth,\n 'is-selected': cell.isSelected,\n 'is-today': cell.isToday,\n }\"\n :data-date=\"cell.key\"\n :disabled=\"cell.disabled\"\n :tabindex=\"cell.isFocused ? 0 : -1\"\n :aria-current=\"cell.isToday ? 'date' : undefined\"\n :aria-label=\"cell.key\"\n @click=\"selectDate(cell.date)\"\n @keydown=\"onDayKeydown($event, cell.date)\"\n >\n {{ cell.dayLabel }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n addDays,\n addMonths,\n createId,\n isActivationKey,\n isEscapeKey,\n isSameDay,\n parseDateValue,\n startOfDay,\n startOfMonth,\n startOfWeek,\n toDateValue,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n type ComponentPublicInstance,\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\ninterface CalendarCell {\n date: Date;\n dayLabel: number;\n disabled: boolean;\n inMonth: boolean;\n isFocused: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n}\n\nconst CalendarIcon = getTreeIcon('calendar');\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n open?: boolean;\n defaultOpen?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n invalid?: boolean;\n placeholder?: string;\n locale?: string;\n min?: string;\n max?: string;\n weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n id?: string;\n }>(),\n {\n modelValue: '',\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n invalid: false,\n placeholder: 'Select date',\n locale: 'en-US',\n min: '',\n max: '',\n weekStartsOn: 0,\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n select: [value: string];\n}>();\n\nconst attrs = useAttrs();\nconst today = startOfDay(new Date());\nconst selectedDate = computed(() => parseDateValue(props.modelValue));\nconst minDate = computed(() => parseDateValue(props.min));\nconst maxDate = computed(() => parseDateValue(props.max));\nconst calendarId = props.id ?? createId('tree-date-picker');\nconst captionId = `${calendarId}-caption`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst dayRefs = new Map<string, HTMLButtonElement>();\nconst viewMonth = ref(startOfMonth(selectedDate.value ?? today));\nconst focusedDate = ref<Date>(selectedDate.value ?? today);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, name: _name, ...rest } = attrs;\n return rest;\n});\n\nconst hiddenInputName = computed(() =>\n typeof attrs.name === 'string' ? attrs.name : undefined,\n);\n\nconst rootClasses = computed(() => [\n 'tree-date-picker',\n `tree-date-picker--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst triggerText = computed(() => {\n if (!selectedDate.value) {\n return props.placeholder;\n }\n\n return new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n }).format(selectedDate.value);\n});\n\nconst monthLabel = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n month: 'long',\n year: 'numeric',\n }).format(viewMonth.value),\n);\n\nconst weekdayLabels = computed(() => {\n const formatter = new Intl.DateTimeFormat(props.locale, { weekday: 'short' });\n const weekBase = startOfWeek(new Date(2024, 0, 7), props.weekStartsOn);\n\n return Array.from({ length: 7 }, (_, index) =>\n formatter.format(addDays(weekBase, index)),\n );\n});\n\nconst isDateDisabled = (date: Date) => {\n if (props.disabled) {\n return true;\n }\n\n if (minDate.value && date < minDate.value) {\n return true;\n }\n\n if (maxDate.value && date > maxDate.value) {\n return true;\n }\n\n return false;\n};\n\nconst syncCalendarView = (date: Date) => {\n focusedDate.value = startOfDay(date);\n viewMonth.value = startOfMonth(date);\n};\n\nwatch(\n selectedDate,\n (value) => {\n if (value) {\n syncCalendarView(value);\n return;\n }\n\n if (!isOpen.value) {\n syncCalendarView(today);\n }\n },\n { immediate: true },\n);\n\nconst cells = computed(() => {\n const startDate = startOfWeek(startOfMonth(viewMonth.value), props.weekStartsOn);\n\n return Array.from({ length: 6 }, (_, weekIndex) =>\n Array.from({ length: 7 }, (_, dayIndex) => {\n const date = addDays(startDate, weekIndex * 7 + dayIndex);\n const key = toDateValue(date);\n\n return {\n date,\n dayLabel: date.getDate(),\n disabled: isDateDisabled(date),\n inMonth: date.getMonth() === viewMonth.value.getMonth(),\n isFocused: isSameDay(date, focusedDate.value),\n isSelected: isSameDay(date, selectedDate.value),\n isToday: isSameDay(date, today),\n key,\n } satisfies CalendarCell;\n }),\n );\n});\n\nconst canMovePrev = computed(() => {\n if (!minDate.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) > startOfMonth(minDate.value);\n});\n\nconst canMoveNext = computed(() => {\n if (!maxDate.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) < startOfMonth(maxDate.value);\n});\n\nconst focusCurrentDay = () => {\n const key = toDateValue(focusedDate.value);\n nextTick(() => {\n dayRefs.get(key)?.focus();\n });\n};\n\nconst setDayRef = (\n element: Element | ComponentPublicInstance | null,\n key: string,\n) => {\n if (element instanceof HTMLButtonElement) {\n dayRefs.set(key, element);\n return;\n }\n\n dayRefs.delete(key);\n};\n\nconst openCalendar = () => {\n if (props.disabled) {\n return;\n }\n\n syncCalendarView(selectedDate.value ?? focusedDate.value ?? today);\n setValue(true);\n focusCurrentDay();\n};\n\nconst closeCalendar = (restoreFocus = false) => {\n setValue(false);\n\n if (restoreFocus) {\n nextTick(() => {\n triggerRef.value?.focus();\n });\n }\n};\n\nconst toggleCalendar = () => {\n if (isOpen.value) {\n closeCalendar();\n return;\n }\n\n openCalendar();\n};\n\nconst moveCalendar = (direction: 1 | -1) => {\n const nextMonth = addMonths(viewMonth.value, direction);\n syncCalendarView(nextMonth);\n focusCurrentDay();\n};\n\nconst moveFocus = (nextDate: Date) => {\n if (isDateDisabled(nextDate)) {\n return;\n }\n\n syncCalendarView(nextDate);\n focusCurrentDay();\n};\n\nconst selectDate = (date: Date) => {\n if (isDateDisabled(date)) {\n return;\n }\n\n const normalizedDate = startOfDay(date);\n const value = toDateValue(normalizedDate);\n\n syncCalendarView(normalizedDate);\n emit('update:modelValue', value);\n emit('select', value);\n closeCalendar(true);\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeCalendar();\n return;\n }\n\n if (\n isActivationKey(event) ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n openCalendar();\n }\n};\n\nconst onDayKeydown = (event: KeyboardEvent, date: Date) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeCalendar(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectDate(date);\n return;\n }\n\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(addDays(date, -1));\n break;\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(addDays(date, 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(addDays(date, -7));\n break;\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(addDays(date, 7));\n break;\n case 'Home':\n event.preventDefault();\n moveFocus(startOfWeek(date, props.weekStartsOn));\n break;\n case 'End':\n event.preventDefault();\n moveFocus(addDays(startOfWeek(date, props.weekStartsOn), 6));\n break;\n case 'PageUp':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? -12 : -1));\n break;\n case 'PageDown':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? 12 : 1));\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeCalendar();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n return;\n }\n\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <input\n v-if=\"hiddenInputName\"\n type=\"hidden\"\n :name=\"hiddenInputName\"\n :value=\"modelValue\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"tree-date-picker__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? calendarId : undefined\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n @click=\"toggleCalendar\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-date-picker__slot tree-date-picker__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <span\n class=\"tree-date-picker__value\"\n :data-placeholder=\"selectedDate ? undefined : true\"\n >\n {{ triggerText }}\n </span>\n <span class=\"tree-date-picker__slot tree-date-picker__slot--suffix\">\n <slot name=\"suffix\">\n <CalendarIcon v-bind=\"treeIconDefaults\" />\n </slot>\n </span>\n </button>\n\n <transition name=\"tree-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"calendarId\"\n class=\"tree-date-picker__content\"\n role=\"dialog\"\n aria-modal=\"false\"\n :aria-labelledby=\"captionId\"\n >\n <div class=\"tree-date-picker__header\">\n <button\n type=\"button\"\n class=\"tree-date-picker__nav\"\n :disabled=\"!canMovePrev\"\n aria-label=\"Previous month\"\n @click=\"moveCalendar(-1)\"\n >\n <ChevronLeftIcon v-bind=\"treeIconDefaults\" />\n </button>\n <p\n :id=\"captionId\"\n class=\"tree-date-picker__month\"\n >\n {{ monthLabel }}\n </p>\n <button\n type=\"button\"\n class=\"tree-date-picker__nav\"\n :disabled=\"!canMoveNext\"\n aria-label=\"Next month\"\n @click=\"moveCalendar(1)\"\n >\n <ChevronRightIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <div\n class=\"tree-date-picker__weekdays\"\n aria-hidden=\"true\"\n >\n <span\n v-for=\"label in weekdayLabels\"\n :key=\"label\"\n class=\"tree-date-picker__weekday\"\n >\n {{ label }}\n </span>\n </div>\n\n <div\n class=\"tree-date-picker__grid\"\n role=\"grid\"\n :aria-labelledby=\"captionId\"\n >\n <div\n v-for=\"(week, weekIndex) in cells\"\n :key=\"weekIndex\"\n class=\"tree-date-picker__row\"\n role=\"row\"\n >\n <div\n v-for=\"cell in week\"\n :key=\"cell.key\"\n class=\"tree-date-picker__cell\"\n role=\"gridcell\"\n :aria-selected=\"cell.isSelected\"\n >\n <button\n :ref=\"(element) => setDayRef(element, cell.key)\"\n type=\"button\"\n class=\"tree-date-picker__day\"\n :class=\"{\n 'is-muted': !cell.inMonth,\n 'is-selected': cell.isSelected,\n 'is-today': cell.isToday,\n }\"\n :data-date=\"cell.key\"\n :disabled=\"cell.disabled\"\n :tabindex=\"cell.isFocused ? 0 : -1\"\n :aria-current=\"cell.isToday ? 'date' : undefined\"\n :aria-label=\"cell.key\"\n @click=\"selectDate(cell.date)\"\n @keydown=\"onDayKeydown($event, cell.date)\"\n >\n {{ cell.dayLabel }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n addDays,\n addMonths,\n createId,\n isActivationKey,\n isEscapeKey,\n isSameDay,\n startOfDay,\n startOfMonth,\n startOfWeek,\n toDateValue,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n type ComponentPublicInstance,\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\ninterface CalendarCell {\n date: Date;\n dayLabel: number;\n disabled: boolean;\n inMonth: boolean;\n isFocused: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n}\n\ninterface TimeOption {\n disabled: boolean;\n label: string;\n value: number;\n}\n\nconst CalendarIcon = getTreeIcon('calendar');\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst dateOnlyPattern = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nconst dateTimePattern = /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})(?::(\\d{2}))?$/;\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n open?: boolean;\n defaultOpen?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n locale?: string;\n min?: string;\n max?: string;\n weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n id?: string;\n step?: number;\n }>(),\n {\n modelValue: '',\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: 'Select date and time',\n locale: 'en-US',\n min: '',\n max: '',\n weekStartsOn: 0,\n id: undefined,\n step: 60,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n change: [value: string];\n select: [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst cloneDate = (value: Date) => new Date(value.getTime());\n\nconst formatPart = (value: number) => `${value}`.padStart(2, '0');\n\nconst endOfDay = (date: Date) =>\n new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);\n\nconst parseBoundaryValue = (\n value: string | null | undefined,\n boundary: 'exact' | 'start' | 'end' = 'exact',\n) => {\n if (!value) {\n return null;\n }\n\n const dateOnlyMatch = value.match(dateOnlyPattern);\n if (dateOnlyMatch) {\n const [, yearToken, monthToken, dayToken] = dateOnlyMatch;\n const year = Number.parseInt(yearToken, 10);\n const month = Number.parseInt(monthToken, 10);\n const day = Number.parseInt(dayToken, 10);\n const hour = boundary === 'end' ? 23 : 0;\n const minute = boundary === 'end' ? 59 : 0;\n const second = boundary === 'end' ? 59 : 0;\n const millisecond = boundary === 'end' ? 999 : 0;\n const date = new Date(year, month - 1, day, hour, minute, second, millisecond);\n\n if (\n Number.isNaN(date.getTime()) ||\n date.getFullYear() !== year ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day\n ) {\n return null;\n }\n\n return date;\n }\n\n const dateTimeMatch = value.match(dateTimePattern);\n if (!dateTimeMatch) {\n return null;\n }\n\n const [, yearToken, monthToken, dayToken, hourToken, minuteToken, secondToken] =\n dateTimeMatch;\n const year = Number.parseInt(yearToken, 10);\n const month = Number.parseInt(monthToken, 10);\n const day = Number.parseInt(dayToken, 10);\n const hour = Number.parseInt(hourToken, 10);\n const minute = Number.parseInt(minuteToken, 10);\n const second = secondToken ? Number.parseInt(secondToken, 10) : 0;\n const date = new Date(year, month - 1, day, hour, minute, second, 0);\n\n if (\n Number.isNaN(date.getTime()) ||\n date.getFullYear() !== year ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day ||\n date.getHours() !== hour ||\n date.getMinutes() !== minute ||\n date.getSeconds() !== second\n ) {\n return null;\n }\n\n return date;\n};\n\nconst toDateTimeValue = (date: Date) =>\n `${toDateValue(date)}T${formatPart(date.getHours())}:${formatPart(date.getMinutes())}`;\n\nconst setDatePart = (source: Date, targetDate: Date) =>\n new Date(\n targetDate.getFullYear(),\n targetDate.getMonth(),\n targetDate.getDate(),\n source.getHours(),\n source.getMinutes(),\n 0,\n 0,\n );\n\nconst setTimePart = (source: Date, hour: number, minute: number) =>\n new Date(\n source.getFullYear(),\n source.getMonth(),\n source.getDate(),\n hour,\n minute,\n 0,\n 0,\n );\n\nconst resolveMinuteStep = (step: number) => {\n if (!Number.isFinite(step) || step <= 0 || step % 60 !== 0) {\n return 1;\n }\n\n const minuteStep = step / 60;\n return minuteStep >= 60 ? 1 : minuteStep;\n};\n\nconst today = startOfDay(new Date());\nconst selectedDateTime = computed(() => parseBoundaryValue(props.modelValue, 'exact'));\nconst minDateTime = computed(() => parseBoundaryValue(props.min, 'start'));\nconst maxDateTime = computed(() => parseBoundaryValue(props.max, 'end'));\nconst pickerId = props.id ?? createId('tree-date-time-picker');\nconst captionId = `${pickerId}-caption`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst dayRefs = new Map<string, HTMLButtonElement>();\n\nconst clampToRange = (value: Date) => {\n let nextValue = cloneDate(value);\n\n if (minDateTime.value && nextValue < minDateTime.value) {\n nextValue = cloneDate(minDateTime.value);\n }\n\n if (maxDateTime.value && nextValue > maxDateTime.value) {\n nextValue = cloneDate(maxDateTime.value);\n }\n\n return nextValue;\n};\n\nconst createDefaultDraftDateTime = () => {\n const reference = new Date();\n const stepMilliseconds = Math.max(props.step, 60) * 1000;\n const rounded = new Date(Math.ceil(reference.getTime() / stepMilliseconds) * stepMilliseconds);\n\n rounded.setSeconds(0, 0);\n return clampToRange(rounded);\n};\n\nconst initialDateTime = selectedDateTime.value ?? createDefaultDraftDateTime();\nconst draftDateTime = ref(initialDateTime);\nconst focusedDate = ref(startOfDay(initialDateTime));\nconst viewMonth = ref(startOfMonth(initialDateTime));\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, name: _name, ...rest } = attrs;\n return rest;\n});\n\nconst hiddenInputName = computed(() =>\n typeof attrs.name === 'string' ? attrs.name : undefined,\n);\n\nconst rootClasses = computed(() => [\n 'tree-date-picker',\n 'tree-date-time-picker',\n `tree-date-picker--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst triggerText = computed(() => {\n if (!selectedDateTime.value) {\n return props.placeholder;\n }\n\n return new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n month: 'long',\n year: 'numeric',\n }).format(selectedDateTime.value);\n});\n\nconst draftPreview = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n month: 'long',\n year: 'numeric',\n }).format(draftDateTime.value),\n);\n\nconst monthLabel = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n month: 'long',\n year: 'numeric',\n }).format(viewMonth.value),\n);\n\nconst weekdayLabels = computed(() => {\n const formatter = new Intl.DateTimeFormat(props.locale, { weekday: 'short' });\n const weekBase = startOfWeek(new Date(2024, 0, 7), props.weekStartsOn);\n\n return Array.from({ length: 7 }, (_, index) =>\n formatter.format(addDays(weekBase, index)),\n );\n});\n\nconst minuteStep = computed(() => resolveMinuteStep(props.step));\n\nconst minuteValues = computed(() => {\n const values = new Set<number>();\n\n for (let minute = 0; minute < 60; minute += minuteStep.value) {\n values.add(minute);\n }\n\n values.add(draftDateTime.value.getMinutes());\n\n return [...values].sort((left, right) => left - right);\n});\n\nconst isDateDisabled = (date: Date) => {\n if (props.disabled) {\n return true;\n }\n\n const dayStart = startOfDay(date);\n const dayEnd = endOfDay(date);\n\n if (minDateTime.value && dayEnd < minDateTime.value) {\n return true;\n }\n\n if (maxDateTime.value && dayStart > maxDateTime.value) {\n return true;\n }\n\n return false;\n};\n\nconst isDateTimeDisabled = (value: Date) => {\n if (props.disabled) {\n return true;\n }\n\n if (minDateTime.value && value < minDateTime.value) {\n return true;\n }\n\n if (maxDateTime.value && value > maxDateTime.value) {\n return true;\n }\n\n return false;\n};\n\nconst syncCalendarView = (date: Date) => {\n focusedDate.value = startOfDay(date);\n viewMonth.value = startOfMonth(date);\n};\n\nconst syncDraftState = (dateTime: Date) => {\n const nextValue = clampToRange(dateTime);\n draftDateTime.value = nextValue;\n syncCalendarView(nextValue);\n};\n\nwatch(\n selectedDateTime,\n (value) => {\n if (isOpen.value) {\n return;\n }\n\n syncDraftState(value ?? createDefaultDraftDateTime());\n },\n { immediate: true },\n);\n\nconst draftDate = computed(() => startOfDay(draftDateTime.value));\n\nconst cells = computed(() => {\n const startDate = startOfWeek(startOfMonth(viewMonth.value), props.weekStartsOn);\n\n return Array.from({ length: 6 }, (_, weekIndex) =>\n Array.from({ length: 7 }, (_, dayIndex) => {\n const date = addDays(startDate, weekIndex * 7 + dayIndex);\n const key = toDateValue(date);\n\n return {\n date,\n dayLabel: date.getDate(),\n disabled: isDateDisabled(date),\n inMonth: date.getMonth() === viewMonth.value.getMonth(),\n isFocused: isSameDay(date, focusedDate.value),\n isSelected: isSameDay(date, draftDate.value),\n isToday: isSameDay(date, today),\n key,\n } satisfies CalendarCell;\n }),\n );\n});\n\nconst canMovePrev = computed(() => {\n if (!minDateTime.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) > startOfMonth(minDateTime.value);\n});\n\nconst canMoveNext = computed(() => {\n if (!maxDateTime.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) < startOfMonth(maxDateTime.value);\n});\n\nconst isTimeOptionEnabled = (hour: number, minute: number) => {\n const candidate = setTimePart(draftDateTime.value, hour, minute);\n return !isDateTimeDisabled(candidate);\n};\n\nconst hourOptions = computed<TimeOption[]>(() =>\n Array.from({ length: 24 }, (_, hour) => ({\n disabled: !minuteValues.value.some((minute) => isTimeOptionEnabled(hour, minute)),\n label: formatPart(hour),\n value: hour,\n })),\n);\n\nconst minuteOptions = computed<TimeOption[]>(() =>\n minuteValues.value.map((minute) => ({\n disabled: !isTimeOptionEnabled(draftDateTime.value.getHours(), minute),\n label: formatPart(minute),\n value: minute,\n })),\n);\n\nconst focusCurrentDay = () => {\n const key = toDateValue(focusedDate.value);\n nextTick(() => {\n dayRefs.get(key)?.focus();\n });\n};\n\nconst setDayRef = (\n element: Element | ComponentPublicInstance | null,\n key: string,\n) => {\n if (element instanceof HTMLButtonElement) {\n dayRefs.set(key, element);\n return;\n }\n\n dayRefs.delete(key);\n};\n\nconst openCalendar = () => {\n if (props.disabled) {\n return;\n }\n\n syncDraftState(selectedDateTime.value ?? createDefaultDraftDateTime());\n setValue(true);\n focusCurrentDay();\n};\n\nconst closeCalendar = (restoreFocus = false) => {\n setValue(false);\n\n if (restoreFocus) {\n nextTick(() => {\n triggerRef.value?.focus();\n });\n }\n};\n\nconst toggleCalendar = () => {\n if (isOpen.value) {\n closeCalendar();\n return;\n }\n\n openCalendar();\n};\n\nconst moveCalendar = (direction: 1 | -1) => {\n const nextMonth = addMonths(viewMonth.value, direction);\n syncCalendarView(nextMonth);\n focusCurrentDay();\n};\n\nconst moveFocus = (nextDate: Date) => {\n if (isDateDisabled(nextDate)) {\n return;\n }\n\n syncCalendarView(nextDate);\n focusCurrentDay();\n};\n\nconst selectDate = (date: Date) => {\n if (isDateDisabled(date)) {\n return;\n }\n\n const candidate = clampToRange(setDatePart(draftDateTime.value, date));\n draftDateTime.value = candidate;\n syncCalendarView(candidate);\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeCalendar();\n return;\n }\n\n if (\n isActivationKey(event) ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n openCalendar();\n }\n};\n\nconst onDayKeydown = (event: KeyboardEvent, date: Date) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeCalendar(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectDate(date);\n return;\n }\n\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(addDays(date, -1));\n break;\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(addDays(date, 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(addDays(date, -7));\n break;\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(addDays(date, 7));\n break;\n case 'Home':\n event.preventDefault();\n moveFocus(startOfWeek(date, props.weekStartsOn));\n break;\n case 'End':\n event.preventDefault();\n moveFocus(addDays(startOfWeek(date, props.weekStartsOn), 6));\n break;\n case 'PageUp':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? -12 : -1));\n break;\n case 'PageDown':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? 12 : 1));\n break;\n default:\n break;\n }\n};\n\nconst updateHour = (event: Event) => {\n const nextHour = Number.parseInt((event.target as HTMLSelectElement).value, 10);\n const currentMinute = draftDateTime.value.getMinutes();\n\n if (Number.isNaN(nextHour)) {\n return;\n }\n\n const availableMinutes = minuteValues.value.filter((minute) =>\n isTimeOptionEnabled(nextHour, minute),\n );\n\n if (!availableMinutes.length) {\n return;\n }\n\n const nextMinute = availableMinutes.includes(currentMinute)\n ? currentMinute\n : availableMinutes[0];\n\n draftDateTime.value = setTimePart(draftDateTime.value, nextHour, nextMinute);\n};\n\nconst updateMinute = (event: Event) => {\n const nextMinute = Number.parseInt((event.target as HTMLSelectElement).value, 10);\n const nextHour = draftDateTime.value.getHours();\n\n if (Number.isNaN(nextMinute) || !isTimeOptionEnabled(nextHour, nextMinute)) {\n return;\n }\n\n draftDateTime.value = setTimePart(draftDateTime.value, nextHour, nextMinute);\n};\n\nconst commitDraft = () => {\n const value = toDateTimeValue(draftDateTime.value);\n\n emit('update:modelValue', value);\n emit('change', value);\n emit('select', value);\n closeCalendar(true);\n};\n\nconst clearSelection = () => {\n emit('update:modelValue', '');\n emit('change', '');\n emit('select', '');\n closeCalendar(true);\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeCalendar();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n return;\n }\n\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <input\n v-if=\"hiddenInputName\"\n type=\"hidden\"\n :name=\"hiddenInputName\"\n :value=\"modelValue\"\n >\n\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"tree-date-picker__trigger tree-date-time-picker__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? pickerId : undefined\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n @click=\"toggleCalendar\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-date-picker__slot tree-date-picker__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n\n <span\n class=\"tree-date-picker__value\"\n :data-placeholder=\"selectedDateTime ? undefined : true\"\n >\n {{ triggerText }}\n </span>\n\n <span class=\"tree-date-picker__slot tree-date-picker__slot--suffix\">\n <slot name=\"suffix\">\n <TreeSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <CalendarIcon\n v-else\n v-bind=\"treeIconDefaults\"\n />\n </slot>\n </span>\n </button>\n\n <transition name=\"tree-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"pickerId\"\n class=\"tree-date-picker__content tree-date-time-picker__content\"\n role=\"dialog\"\n aria-modal=\"false\"\n :aria-labelledby=\"captionId\"\n >\n <div class=\"tree-date-time-picker__calendar\">\n <div class=\"tree-date-picker__header\">\n <button\n type=\"button\"\n class=\"tree-date-picker__nav\"\n :disabled=\"!canMovePrev\"\n aria-label=\"Previous month\"\n @click=\"moveCalendar(-1)\"\n >\n <ChevronLeftIcon v-bind=\"treeIconDefaults\" />\n </button>\n\n <p\n :id=\"captionId\"\n class=\"tree-date-picker__month\"\n >\n {{ monthLabel }}\n </p>\n\n <button\n type=\"button\"\n class=\"tree-date-picker__nav\"\n :disabled=\"!canMoveNext\"\n aria-label=\"Next month\"\n @click=\"moveCalendar(1)\"\n >\n <ChevronRightIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <div\n class=\"tree-date-picker__weekdays\"\n aria-hidden=\"true\"\n >\n <span\n v-for=\"label in weekdayLabels\"\n :key=\"label\"\n class=\"tree-date-picker__weekday\"\n >\n {{ label }}\n </span>\n </div>\n\n <div\n class=\"tree-date-picker__grid\"\n role=\"grid\"\n :aria-labelledby=\"captionId\"\n >\n <div\n v-for=\"(week, weekIndex) in cells\"\n :key=\"weekIndex\"\n class=\"tree-date-picker__row\"\n role=\"row\"\n >\n <div\n v-for=\"cell in week\"\n :key=\"cell.key\"\n class=\"tree-date-picker__cell\"\n role=\"gridcell\"\n :aria-selected=\"cell.isSelected\"\n >\n <button\n :ref=\"(element) => setDayRef(element, cell.key)\"\n type=\"button\"\n class=\"tree-date-picker__day\"\n :class=\"{\n 'is-muted': !cell.inMonth,\n 'is-selected': cell.isSelected,\n 'is-today': cell.isToday,\n }\"\n :data-date=\"cell.key\"\n :tabindex=\"cell.isFocused ? 0 : -1\"\n :disabled=\"cell.disabled\"\n :aria-pressed=\"cell.isSelected\"\n @click=\"selectDate(cell.date)\"\n @keydown=\"onDayKeydown($event, cell.date)\"\n >\n {{ cell.dayLabel }}\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"tree-date-time-picker__summary\">\n <p class=\"tree-date-time-picker__eyebrow\">\n Selected slot\n </p>\n <p class=\"tree-date-time-picker__summary-value\">\n {{ draftPreview }}\n </p>\n </div>\n\n <div class=\"tree-date-time-picker__time\">\n <label class=\"tree-date-time-picker__time-field\">\n <span class=\"tree-date-time-picker__time-label\">Hour</span>\n <select\n class=\"tree-date-time-picker__select\"\n :value=\"draftDateTime.getHours()\"\n aria-label=\"Select hour\"\n @change=\"updateHour\"\n >\n <option\n v-for=\"option in hourOptions\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </option>\n </select>\n </label>\n\n <label class=\"tree-date-time-picker__time-field\">\n <span class=\"tree-date-time-picker__time-label\">Minute</span>\n <select\n class=\"tree-date-time-picker__select\"\n :value=\"draftDateTime.getMinutes()\"\n aria-label=\"Select minute\"\n @change=\"updateMinute\"\n >\n <option\n v-for=\"option in minuteOptions\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </option>\n </select>\n </label>\n </div>\n\n <div class=\"tree-date-time-picker__footer\">\n <button\n type=\"button\"\n class=\"tree-button tree-button--ghost tree-button--sm\"\n @click=\"clearSelection\"\n >\n Clear\n </button>\n <button\n type=\"button\"\n class=\"tree-button tree-button--solid tree-button--sm\"\n @click=\"commitDraft\"\n >\n Apply\n </button>\n </div>\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n addDays,\n addMonths,\n createId,\n isActivationKey,\n isEscapeKey,\n isSameDay,\n startOfDay,\n startOfMonth,\n startOfWeek,\n toDateValue,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n type ComponentPublicInstance,\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\ninterface CalendarCell {\n date: Date;\n dayLabel: number;\n disabled: boolean;\n inMonth: boolean;\n isFocused: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n}\n\ninterface TimeOption {\n disabled: boolean;\n label: string;\n value: number;\n}\n\nconst CalendarIcon = getTreeIcon('calendar');\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst dateOnlyPattern = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nconst dateTimePattern = /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})(?::(\\d{2}))?$/;\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n open?: boolean;\n defaultOpen?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n locale?: string;\n min?: string;\n max?: string;\n weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n id?: string;\n step?: number;\n }>(),\n {\n modelValue: '',\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: 'Select date and time',\n locale: 'en-US',\n min: '',\n max: '',\n weekStartsOn: 0,\n id: undefined,\n step: 60,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n change: [value: string];\n select: [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst cloneDate = (value: Date) => new Date(value.getTime());\n\nconst formatPart = (value: number) => `${value}`.padStart(2, '0');\n\nconst endOfDay = (date: Date) =>\n new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);\n\nconst parseBoundaryValue = (\n value: string | null | undefined,\n boundary: 'exact' | 'start' | 'end' = 'exact',\n) => {\n if (!value) {\n return null;\n }\n\n const dateOnlyMatch = value.match(dateOnlyPattern);\n if (dateOnlyMatch) {\n const [, yearToken, monthToken, dayToken] = dateOnlyMatch;\n const year = Number.parseInt(yearToken, 10);\n const month = Number.parseInt(monthToken, 10);\n const day = Number.parseInt(dayToken, 10);\n const hour = boundary === 'end' ? 23 : 0;\n const minute = boundary === 'end' ? 59 : 0;\n const second = boundary === 'end' ? 59 : 0;\n const millisecond = boundary === 'end' ? 999 : 0;\n const date = new Date(year, month - 1, day, hour, minute, second, millisecond);\n\n if (\n Number.isNaN(date.getTime()) ||\n date.getFullYear() !== year ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day\n ) {\n return null;\n }\n\n return date;\n }\n\n const dateTimeMatch = value.match(dateTimePattern);\n if (!dateTimeMatch) {\n return null;\n }\n\n const [, yearToken, monthToken, dayToken, hourToken, minuteToken, secondToken] =\n dateTimeMatch;\n const year = Number.parseInt(yearToken, 10);\n const month = Number.parseInt(monthToken, 10);\n const day = Number.parseInt(dayToken, 10);\n const hour = Number.parseInt(hourToken, 10);\n const minute = Number.parseInt(minuteToken, 10);\n const second = secondToken ? Number.parseInt(secondToken, 10) : 0;\n const date = new Date(year, month - 1, day, hour, minute, second, 0);\n\n if (\n Number.isNaN(date.getTime()) ||\n date.getFullYear() !== year ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day ||\n date.getHours() !== hour ||\n date.getMinutes() !== minute ||\n date.getSeconds() !== second\n ) {\n return null;\n }\n\n return date;\n};\n\nconst toDateTimeValue = (date: Date) =>\n `${toDateValue(date)}T${formatPart(date.getHours())}:${formatPart(date.getMinutes())}`;\n\nconst setDatePart = (source: Date, targetDate: Date) =>\n new Date(\n targetDate.getFullYear(),\n targetDate.getMonth(),\n targetDate.getDate(),\n source.getHours(),\n source.getMinutes(),\n 0,\n 0,\n );\n\nconst setTimePart = (source: Date, hour: number, minute: number) =>\n new Date(\n source.getFullYear(),\n source.getMonth(),\n source.getDate(),\n hour,\n minute,\n 0,\n 0,\n );\n\nconst resolveMinuteStep = (step: number) => {\n if (!Number.isFinite(step) || step <= 0 || step % 60 !== 0) {\n return 1;\n }\n\n const minuteStep = step / 60;\n return minuteStep >= 60 ? 1 : minuteStep;\n};\n\nconst today = startOfDay(new Date());\nconst selectedDateTime = computed(() => parseBoundaryValue(props.modelValue, 'exact'));\nconst minDateTime = computed(() => parseBoundaryValue(props.min, 'start'));\nconst maxDateTime = computed(() => parseBoundaryValue(props.max, 'end'));\nconst pickerId = props.id ?? createId('tree-date-time-picker');\nconst captionId = `${pickerId}-caption`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst dayRefs = new Map<string, HTMLButtonElement>();\n\nconst clampToRange = (value: Date) => {\n let nextValue = cloneDate(value);\n\n if (minDateTime.value && nextValue < minDateTime.value) {\n nextValue = cloneDate(minDateTime.value);\n }\n\n if (maxDateTime.value && nextValue > maxDateTime.value) {\n nextValue = cloneDate(maxDateTime.value);\n }\n\n return nextValue;\n};\n\nconst createDefaultDraftDateTime = () => {\n const reference = new Date();\n const stepMilliseconds = Math.max(props.step, 60) * 1000;\n const rounded = new Date(Math.ceil(reference.getTime() / stepMilliseconds) * stepMilliseconds);\n\n rounded.setSeconds(0, 0);\n return clampToRange(rounded);\n};\n\nconst initialDateTime = selectedDateTime.value ?? createDefaultDraftDateTime();\nconst draftDateTime = ref(initialDateTime);\nconst focusedDate = ref(startOfDay(initialDateTime));\nconst viewMonth = ref(startOfMonth(initialDateTime));\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, name: _name, ...rest } = attrs;\n return rest;\n});\n\nconst hiddenInputName = computed(() =>\n typeof attrs.name === 'string' ? attrs.name : undefined,\n);\n\nconst rootClasses = computed(() => [\n 'tree-date-picker',\n 'tree-date-time-picker',\n `tree-date-picker--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst triggerText = computed(() => {\n if (!selectedDateTime.value) {\n return props.placeholder;\n }\n\n return new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n month: 'long',\n year: 'numeric',\n }).format(selectedDateTime.value);\n});\n\nconst draftPreview = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n month: 'long',\n year: 'numeric',\n }).format(draftDateTime.value),\n);\n\nconst monthLabel = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n month: 'long',\n year: 'numeric',\n }).format(viewMonth.value),\n);\n\nconst weekdayLabels = computed(() => {\n const formatter = new Intl.DateTimeFormat(props.locale, { weekday: 'short' });\n const weekBase = startOfWeek(new Date(2024, 0, 7), props.weekStartsOn);\n\n return Array.from({ length: 7 }, (_, index) =>\n formatter.format(addDays(weekBase, index)),\n );\n});\n\nconst minuteStep = computed(() => resolveMinuteStep(props.step));\n\nconst minuteValues = computed(() => {\n const values = new Set<number>();\n\n for (let minute = 0; minute < 60; minute += minuteStep.value) {\n values.add(minute);\n }\n\n values.add(draftDateTime.value.getMinutes());\n\n return [...values].sort((left, right) => left - right);\n});\n\nconst isDateDisabled = (date: Date) => {\n if (props.disabled) {\n return true;\n }\n\n const dayStart = startOfDay(date);\n const dayEnd = endOfDay(date);\n\n if (minDateTime.value && dayEnd < minDateTime.value) {\n return true;\n }\n\n if (maxDateTime.value && dayStart > maxDateTime.value) {\n return true;\n }\n\n return false;\n};\n\nconst isDateTimeDisabled = (value: Date) => {\n if (props.disabled) {\n return true;\n }\n\n if (minDateTime.value && value < minDateTime.value) {\n return true;\n }\n\n if (maxDateTime.value && value > maxDateTime.value) {\n return true;\n }\n\n return false;\n};\n\nconst syncCalendarView = (date: Date) => {\n focusedDate.value = startOfDay(date);\n viewMonth.value = startOfMonth(date);\n};\n\nconst syncDraftState = (dateTime: Date) => {\n const nextValue = clampToRange(dateTime);\n draftDateTime.value = nextValue;\n syncCalendarView(nextValue);\n};\n\nwatch(\n selectedDateTime,\n (value) => {\n if (isOpen.value) {\n return;\n }\n\n syncDraftState(value ?? createDefaultDraftDateTime());\n },\n { immediate: true },\n);\n\nconst draftDate = computed(() => startOfDay(draftDateTime.value));\n\nconst cells = computed(() => {\n const startDate = startOfWeek(startOfMonth(viewMonth.value), props.weekStartsOn);\n\n return Array.from({ length: 6 }, (_, weekIndex) =>\n Array.from({ length: 7 }, (_, dayIndex) => {\n const date = addDays(startDate, weekIndex * 7 + dayIndex);\n const key = toDateValue(date);\n\n return {\n date,\n dayLabel: date.getDate(),\n disabled: isDateDisabled(date),\n inMonth: date.getMonth() === viewMonth.value.getMonth(),\n isFocused: isSameDay(date, focusedDate.value),\n isSelected: isSameDay(date, draftDate.value),\n isToday: isSameDay(date, today),\n key,\n } satisfies CalendarCell;\n }),\n );\n});\n\nconst canMovePrev = computed(() => {\n if (!minDateTime.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) > startOfMonth(minDateTime.value);\n});\n\nconst canMoveNext = computed(() => {\n if (!maxDateTime.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) < startOfMonth(maxDateTime.value);\n});\n\nconst isTimeOptionEnabled = (hour: number, minute: number) => {\n const candidate = setTimePart(draftDateTime.value, hour, minute);\n return !isDateTimeDisabled(candidate);\n};\n\nconst hourOptions = computed<TimeOption[]>(() =>\n Array.from({ length: 24 }, (_, hour) => ({\n disabled: !minuteValues.value.some((minute) => isTimeOptionEnabled(hour, minute)),\n label: formatPart(hour),\n value: hour,\n })),\n);\n\nconst minuteOptions = computed<TimeOption[]>(() =>\n minuteValues.value.map((minute) => ({\n disabled: !isTimeOptionEnabled(draftDateTime.value.getHours(), minute),\n label: formatPart(minute),\n value: minute,\n })),\n);\n\nconst focusCurrentDay = () => {\n const key = toDateValue(focusedDate.value);\n nextTick(() => {\n dayRefs.get(key)?.focus();\n });\n};\n\nconst setDayRef = (\n element: Element | ComponentPublicInstance | null,\n key: string,\n) => {\n if (element instanceof HTMLButtonElement) {\n dayRefs.set(key, element);\n return;\n }\n\n dayRefs.delete(key);\n};\n\nconst openCalendar = () => {\n if (props.disabled) {\n return;\n }\n\n syncDraftState(selectedDateTime.value ?? createDefaultDraftDateTime());\n setValue(true);\n focusCurrentDay();\n};\n\nconst closeCalendar = (restoreFocus = false) => {\n setValue(false);\n\n if (restoreFocus) {\n nextTick(() => {\n triggerRef.value?.focus();\n });\n }\n};\n\nconst toggleCalendar = () => {\n if (isOpen.value) {\n closeCalendar();\n return;\n }\n\n openCalendar();\n};\n\nconst moveCalendar = (direction: 1 | -1) => {\n const nextMonth = addMonths(viewMonth.value, direction);\n syncCalendarView(nextMonth);\n focusCurrentDay();\n};\n\nconst moveFocus = (nextDate: Date) => {\n if (isDateDisabled(nextDate)) {\n return;\n }\n\n syncCalendarView(nextDate);\n focusCurrentDay();\n};\n\nconst selectDate = (date: Date) => {\n if (isDateDisabled(date)) {\n return;\n }\n\n const candidate = clampToRange(setDatePart(draftDateTime.value, date));\n draftDateTime.value = candidate;\n syncCalendarView(candidate);\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeCalendar();\n return;\n }\n\n if (\n isActivationKey(event) ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n openCalendar();\n }\n};\n\nconst onDayKeydown = (event: KeyboardEvent, date: Date) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeCalendar(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectDate(date);\n return;\n }\n\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(addDays(date, -1));\n break;\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(addDays(date, 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(addDays(date, -7));\n break;\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(addDays(date, 7));\n break;\n case 'Home':\n event.preventDefault();\n moveFocus(startOfWeek(date, props.weekStartsOn));\n break;\n case 'End':\n event.preventDefault();\n moveFocus(addDays(startOfWeek(date, props.weekStartsOn), 6));\n break;\n case 'PageUp':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? -12 : -1));\n break;\n case 'PageDown':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? 12 : 1));\n break;\n default:\n break;\n }\n};\n\nconst updateHour = (event: Event) => {\n const nextHour = Number.parseInt((event.target as HTMLSelectElement).value, 10);\n const currentMinute = draftDateTime.value.getMinutes();\n\n if (Number.isNaN(nextHour)) {\n return;\n }\n\n const availableMinutes = minuteValues.value.filter((minute) =>\n isTimeOptionEnabled(nextHour, minute),\n );\n\n if (!availableMinutes.length) {\n return;\n }\n\n const nextMinute = availableMinutes.includes(currentMinute)\n ? currentMinute\n : availableMinutes[0];\n\n draftDateTime.value = setTimePart(draftDateTime.value, nextHour, nextMinute);\n};\n\nconst updateMinute = (event: Event) => {\n const nextMinute = Number.parseInt((event.target as HTMLSelectElement).value, 10);\n const nextHour = draftDateTime.value.getHours();\n\n if (Number.isNaN(nextMinute) || !isTimeOptionEnabled(nextHour, nextMinute)) {\n return;\n }\n\n draftDateTime.value = setTimePart(draftDateTime.value, nextHour, nextMinute);\n};\n\nconst commitDraft = () => {\n const value = toDateTimeValue(draftDateTime.value);\n\n emit('update:modelValue', value);\n emit('change', value);\n emit('select', value);\n closeCalendar(true);\n};\n\nconst clearSelection = () => {\n emit('update:modelValue', '');\n emit('change', '');\n emit('select', '');\n closeCalendar(true);\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeCalendar();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n return;\n }\n\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <input\n v-if=\"hiddenInputName\"\n type=\"hidden\"\n :name=\"hiddenInputName\"\n :value=\"modelValue\"\n >\n\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"tree-date-picker__trigger tree-date-time-picker__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? pickerId : undefined\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n @click=\"toggleCalendar\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-date-picker__slot tree-date-picker__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n\n <span\n class=\"tree-date-picker__value\"\n :data-placeholder=\"selectedDateTime ? undefined : true\"\n >\n {{ triggerText }}\n </span>\n\n <span class=\"tree-date-picker__slot tree-date-picker__slot--suffix\">\n <slot name=\"suffix\">\n <TreeSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <CalendarIcon\n v-else\n v-bind=\"treeIconDefaults\"\n />\n </slot>\n </span>\n </button>\n\n <transition name=\"tree-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"pickerId\"\n class=\"tree-date-picker__content tree-date-time-picker__content\"\n role=\"dialog\"\n aria-modal=\"false\"\n :aria-labelledby=\"captionId\"\n >\n <div class=\"tree-date-time-picker__calendar\">\n <div class=\"tree-date-picker__header\">\n <button\n type=\"button\"\n class=\"tree-date-picker__nav\"\n :disabled=\"!canMovePrev\"\n aria-label=\"Previous month\"\n @click=\"moveCalendar(-1)\"\n >\n <ChevronLeftIcon v-bind=\"treeIconDefaults\" />\n </button>\n\n <p\n :id=\"captionId\"\n class=\"tree-date-picker__month\"\n >\n {{ monthLabel }}\n </p>\n\n <button\n type=\"button\"\n class=\"tree-date-picker__nav\"\n :disabled=\"!canMoveNext\"\n aria-label=\"Next month\"\n @click=\"moveCalendar(1)\"\n >\n <ChevronRightIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <div\n class=\"tree-date-picker__weekdays\"\n aria-hidden=\"true\"\n >\n <span\n v-for=\"label in weekdayLabels\"\n :key=\"label\"\n class=\"tree-date-picker__weekday\"\n >\n {{ label }}\n </span>\n </div>\n\n <div\n class=\"tree-date-picker__grid\"\n role=\"grid\"\n :aria-labelledby=\"captionId\"\n >\n <div\n v-for=\"(week, weekIndex) in cells\"\n :key=\"weekIndex\"\n class=\"tree-date-picker__row\"\n role=\"row\"\n >\n <div\n v-for=\"cell in week\"\n :key=\"cell.key\"\n class=\"tree-date-picker__cell\"\n role=\"gridcell\"\n :aria-selected=\"cell.isSelected\"\n >\n <button\n :ref=\"(element) => setDayRef(element, cell.key)\"\n type=\"button\"\n class=\"tree-date-picker__day\"\n :class=\"{\n 'is-muted': !cell.inMonth,\n 'is-selected': cell.isSelected,\n 'is-today': cell.isToday,\n }\"\n :data-date=\"cell.key\"\n :tabindex=\"cell.isFocused ? 0 : -1\"\n :disabled=\"cell.disabled\"\n :aria-pressed=\"cell.isSelected\"\n @click=\"selectDate(cell.date)\"\n @keydown=\"onDayKeydown($event, cell.date)\"\n >\n {{ cell.dayLabel }}\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"tree-date-time-picker__summary\">\n <p class=\"tree-date-time-picker__eyebrow\">\n Selected slot\n </p>\n <p class=\"tree-date-time-picker__summary-value\">\n {{ draftPreview }}\n </p>\n </div>\n\n <div class=\"tree-date-time-picker__time\">\n <label class=\"tree-date-time-picker__time-field\">\n <span class=\"tree-date-time-picker__time-label\">Hour</span>\n <select\n class=\"tree-date-time-picker__select\"\n :value=\"draftDateTime.getHours()\"\n aria-label=\"Select hour\"\n @change=\"updateHour\"\n >\n <option\n v-for=\"option in hourOptions\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </option>\n </select>\n </label>\n\n <label class=\"tree-date-time-picker__time-field\">\n <span class=\"tree-date-time-picker__time-label\">Minute</span>\n <select\n class=\"tree-date-time-picker__select\"\n :value=\"draftDateTime.getMinutes()\"\n aria-label=\"Select minute\"\n @change=\"updateMinute\"\n >\n <option\n v-for=\"option in minuteOptions\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </option>\n </select>\n </label>\n </div>\n\n <div class=\"tree-date-time-picker__footer\">\n <button\n type=\"button\"\n class=\"tree-button tree-button--ghost tree-button--sm\"\n @click=\"clearSelection\"\n >\n Clear\n </button>\n <button\n type=\"button\"\n class=\"tree-button tree-button--solid tree-button--sm\"\n @click=\"commitDraft\"\n >\n Apply\n </button>\n </div>\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n createId,\n focusFirst,\n focusLast,\n getFocusableElements,\n isEscapeKey,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeDrawerSide, TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n side?: TreeDrawerSide;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n side: 'right',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close drawer',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst drawerId = props.id ?? createId('tree-drawer');\nconst titleId = `${drawerId}-title`;\nconst descriptionId = `${drawerId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['tree-drawer', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 'tree-drawer__surface',\n `tree-drawer__surface--${props.size}`,\n `tree-drawer__surface--${props.side}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\n};\n\nconst focusSurface = () => {\n nextTick(() => {\n if (!surfaceRef.value) {\n return;\n }\n\n const focused = focusFirst(surfaceRef.value);\n if (!focused) {\n surfaceRef.value.focus();\n }\n });\n};\n\nconst openDrawer = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeDrawer = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openDrawer();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeDrawer();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeDrawer();\n return;\n }\n\n if (event.key !== 'Tab' || !surfaceRef.value) {\n return;\n }\n\n const focusable = getFocusableElements(surfaceRef.value);\n\n if (!focusable.length) {\n event.preventDefault();\n surfaceRef.value.focus();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n focusLast(surfaceRef.value);\n }\n\n if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n focusFirst(surfaceRef.value);\n }\n};\n\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"tree-drawer__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"tree-drawer-fade\">\n <div\n v-if=\"isOpen\"\n class=\"tree-drawer__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"tree-drawer__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div\n :id=\"drawerId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"tree-drawer__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"tree-drawer__header\"\n >\n <slot name=\"header\">\n <h2 class=\"tree-drawer__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"tree-drawer__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeDrawer\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"tree-drawer__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"tree-drawer__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"tree-drawer__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n createId,\n focusFirst,\n focusLast,\n getFocusableElements,\n isEscapeKey,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeDrawerSide, TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n side?: TreeDrawerSide;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n side: 'right',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close drawer',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst drawerId = props.id ?? createId('tree-drawer');\nconst titleId = `${drawerId}-title`;\nconst descriptionId = `${drawerId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['tree-drawer', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 'tree-drawer__surface',\n `tree-drawer__surface--${props.size}`,\n `tree-drawer__surface--${props.side}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\n};\n\nconst focusSurface = () => {\n nextTick(() => {\n if (!surfaceRef.value) {\n return;\n }\n\n const focused = focusFirst(surfaceRef.value);\n if (!focused) {\n surfaceRef.value.focus();\n }\n });\n};\n\nconst openDrawer = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeDrawer = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openDrawer();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeDrawer();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeDrawer();\n return;\n }\n\n if (event.key !== 'Tab' || !surfaceRef.value) {\n return;\n }\n\n const focusable = getFocusableElements(surfaceRef.value);\n\n if (!focusable.length) {\n event.preventDefault();\n surfaceRef.value.focus();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n focusLast(surfaceRef.value);\n }\n\n if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n focusFirst(surfaceRef.value);\n }\n};\n\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"tree-drawer__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"tree-drawer-fade\">\n <div\n v-if=\"isOpen\"\n class=\"tree-drawer__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"tree-drawer__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div\n :id=\"drawerId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"tree-drawer__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"tree-drawer__header\"\n >\n <slot name=\"header\">\n <h2 class=\"tree-drawer__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"tree-drawer__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeDrawer\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"tree-drawer__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"tree-drawer__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"tree-drawer__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeDropdownItem {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TreeDropdownItem[];\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n label?: string;\n }>(),\n {\n items: () => [],\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n label: '',\n },\n);\n\nconst emit = defineEmits<{\n select: [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n trigger(props: { isOpen: boolean }): unknown;\n item(props: { item: TreeDropdownItem; index: number }): unknown;\n}>();\n\nconst attrs = useAttrs();\nconst menuId = createId('tree-dropdown');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-dropdown',\n `tree-dropdown--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst enabledItems = computed(() => props.items.filter((i) => !i.disabled));\n\nconst openMenu = () => {\n if (props.disabled) return;\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n setValue(true);\n nextTick(() => focusItem(focusedIndex.value));\n};\n\nconst closeMenu = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst toggleMenu = () => {\n if (isOpen.value) {\n closeMenu();\n } else {\n openMenu();\n }\n};\n\nconst selectItem = (item: TreeDropdownItem) => {\n if (item.disabled) return;\n emit('select', item.value);\n closeMenu(true);\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n if (!item) return;\n const el = itemRefs.value.get(item.value);\n el?.focus();\n};\n\nconst setItemRef = (el: Element | null, value: string) => {\n if (el instanceof HTMLElement) {\n itemRefs.value.set(value, el);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.items.length) {\n if (!props.items[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusItem(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeMenu();\n return;\n }\n\n if (isActivationKey(event) || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n openMenu();\n }\n};\n\nconst onItemKeydown = (event: KeyboardEvent, item: TreeDropdownItem) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeMenu(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(item);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n focusItem(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[enabledItems.value.length - 1])\n : props.items.length - 1;\n focusItem(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeMenu();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span class=\"tree-dropdown__trigger-wrapper\">\n <slot\n name=\"trigger\"\n :is-open=\"isOpen\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"tree-dropdown__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? menuId : undefined\"\n aria-haspopup=\"menu\"\n :aria-expanded=\"isOpen\"\n @click=\"toggleMenu\"\n @keydown=\"onTriggerKeydown\"\n >\n <span class=\"tree-dropdown__label\">{{ label }}</span>\n <svg\n class=\"tree-dropdown__chevron\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </button>\n </slot>\n </span>\n <transition name=\"tree-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"menuId\"\n role=\"menu\"\n class=\"tree-dropdown__menu\"\n :aria-label=\"label || undefined\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n :ref=\"(el) => setItemRef(el as Element | null, item.value)\"\n role=\"menuitem\"\n class=\"tree-dropdown__item\"\n :class=\"{\n 'is-disabled': item.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-disabled=\"item.disabled || undefined\"\n :tabindex=\"item.disabled ? -1 : 0\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n {{ item.label }}\n </slot>\n </li>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeDropdownItem {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TreeDropdownItem[];\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n label?: string;\n }>(),\n {\n items: () => [],\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n label: '',\n },\n);\n\nconst emit = defineEmits<{\n select: [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n trigger(props: { isOpen: boolean }): unknown;\n item(props: { item: TreeDropdownItem; index: number }): unknown;\n}>();\n\nconst attrs = useAttrs();\nconst menuId = createId('tree-dropdown');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-dropdown',\n `tree-dropdown--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst enabledItems = computed(() => props.items.filter((i) => !i.disabled));\n\nconst openMenu = () => {\n if (props.disabled) return;\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n setValue(true);\n nextTick(() => focusItem(focusedIndex.value));\n};\n\nconst closeMenu = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst toggleMenu = () => {\n if (isOpen.value) {\n closeMenu();\n } else {\n openMenu();\n }\n};\n\nconst selectItem = (item: TreeDropdownItem) => {\n if (item.disabled) return;\n emit('select', item.value);\n closeMenu(true);\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n if (!item) return;\n const el = itemRefs.value.get(item.value);\n el?.focus();\n};\n\nconst setItemRef = (el: Element | null, value: string) => {\n if (el instanceof HTMLElement) {\n itemRefs.value.set(value, el);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.items.length) {\n if (!props.items[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusItem(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeMenu();\n return;\n }\n\n if (isActivationKey(event) || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n openMenu();\n }\n};\n\nconst onItemKeydown = (event: KeyboardEvent, item: TreeDropdownItem) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeMenu(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(item);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n focusItem(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[enabledItems.value.length - 1])\n : props.items.length - 1;\n focusItem(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeMenu();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span class=\"tree-dropdown__trigger-wrapper\">\n <slot\n name=\"trigger\"\n :is-open=\"isOpen\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"tree-dropdown__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? menuId : undefined\"\n aria-haspopup=\"menu\"\n :aria-expanded=\"isOpen\"\n @click=\"toggleMenu\"\n @keydown=\"onTriggerKeydown\"\n >\n <span class=\"tree-dropdown__label\">{{ label }}</span>\n <svg\n class=\"tree-dropdown__chevron\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </button>\n </slot>\n </span>\n <transition name=\"tree-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"menuId\"\n role=\"menu\"\n class=\"tree-dropdown__menu\"\n :aria-label=\"label || undefined\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n :ref=\"(el) => setItemRef(el as Element | null, item.value)\"\n role=\"menuitem\"\n class=\"tree-dropdown__item\"\n :class=\"{\n 'is-disabled': item.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-disabled=\"item.disabled || undefined\"\n :tabindex=\"item.disabled ? -1 : 0\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n {{ item.label }}\n </slot>\n </li>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst slots = defineSlots<{\n icon?: () => unknown;\n title?: () => unknown;\n description?: () => unknown;\n default?: () => unknown;\n actions?: () => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TreeSize;\n title?: string;\n description?: string;\n }>(),\n {\n as: 'section',\n size: 'md',\n title: '',\n description: '',\n },\n);\n\nconst attrs = useAttrs();\nconst emptyStateId = createId('tree-empty-state');\nconst titleId = `${emptyStateId}-title`;\nconst descriptionId = `${emptyStateId}-description`;\n\nconst hasTitle = computed(() => Boolean(props.title || slots.title));\nconst hasDescription = computed(() => Boolean(props.description || slots.description));\n\nconst classes = computed(() => [\n 'tree-empty-state',\n `tree-empty-state--${props.size}`,\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"classes\"\n :style=\"rootStyle\"\n :aria-labelledby=\"hasTitle ? titleId : undefined\"\n :aria-describedby=\"hasDescription ? descriptionId : undefined\"\n >\n <div\n v-if=\"$slots.icon\"\n class=\"tree-empty-state__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div class=\"tree-empty-state__content\">\n <h2\n v-if=\"hasTitle\"\n :id=\"titleId\"\n class=\"tree-empty-state__title\"\n >\n <slot name=\"title\">\n {{ title }}\n </slot>\n </h2>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n class=\"tree-empty-state__description\"\n >\n <slot name=\"description\">\n {{ description }}\n </slot>\n </p>\n\n <div\n v-if=\"$slots.default\"\n class=\"tree-empty-state__body\"\n >\n <slot />\n </div>\n\n <div\n v-if=\"$slots.actions\"\n class=\"tree-empty-state__actions\"\n >\n <slot name=\"actions\" />\n </div>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst slots = defineSlots<{\n icon?: () => unknown;\n title?: () => unknown;\n description?: () => unknown;\n default?: () => unknown;\n actions?: () => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TreeSize;\n title?: string;\n description?: string;\n }>(),\n {\n as: 'section',\n size: 'md',\n title: '',\n description: '',\n },\n);\n\nconst attrs = useAttrs();\nconst emptyStateId = createId('tree-empty-state');\nconst titleId = `${emptyStateId}-title`;\nconst descriptionId = `${emptyStateId}-description`;\n\nconst hasTitle = computed(() => Boolean(props.title || slots.title));\nconst hasDescription = computed(() => Boolean(props.description || slots.description));\n\nconst classes = computed(() => [\n 'tree-empty-state',\n `tree-empty-state--${props.size}`,\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"classes\"\n :style=\"rootStyle\"\n :aria-labelledby=\"hasTitle ? titleId : undefined\"\n :aria-describedby=\"hasDescription ? descriptionId : undefined\"\n >\n <div\n v-if=\"$slots.icon\"\n class=\"tree-empty-state__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div class=\"tree-empty-state__content\">\n <h2\n v-if=\"hasTitle\"\n :id=\"titleId\"\n class=\"tree-empty-state__title\"\n >\n <slot name=\"title\">\n {{ title }}\n </slot>\n </h2>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n class=\"tree-empty-state__description\"\n >\n <slot name=\"description\">\n {{ description }}\n </slot>\n </p>\n\n <div\n v-if=\"$slots.default\"\n class=\"tree-empty-state__body\"\n >\n <slot />\n </div>\n\n <div\n v-if=\"$slots.actions\"\n class=\"tree-empty-state__actions\"\n >\n <slot name=\"actions\" />\n </div>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey } from '@treeui/utils';\nimport { computed, onBeforeUnmount, onMounted, ref, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport type TreeFileUploadRejectionReason =\n | 'file-invalid-type'\n | 'file-too-large'\n | 'too-many-files';\n\nexport interface TreeFileUploadRejection {\n file: File;\n reason: TreeFileUploadRejectionReason;\n message: string;\n}\n\nconst slots = defineSlots<{\n icon?: () => unknown;\n default?: (props: {\n files: File[];\n isDragActive: boolean;\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n file?: (props: {\n file: File;\n index: number;\n removeFile: () => void;\n }) => unknown;\n actions?: (props: {\n files: File[];\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: File[];\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n accept?: string;\n multiple?: boolean;\n maxFiles?: number | null;\n maxFileSize?: number | null;\n label?: string;\n description?: string;\n buttonLabel?: string;\n filesLabel?: string;\n paste?: boolean;\n drop?: boolean;\n showFileList?: boolean;\n }>(),\n {\n modelValue: () => [],\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n accept: '',\n multiple: true,\n label: 'Drop files here',\n description: 'Click to browse, drag and drop, or paste with Ctrl+V.',\n buttonLabel: 'Browse files',\n filesLabel: 'Selected files',\n maxFiles: null,\n maxFileSize: null,\n paste: true,\n drop: true,\n showFileList: true,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [files: File[]];\n 'files-accepted': [files: File[]];\n 'files-rejected': [rejections: TreeFileUploadRejection[]];\n}>();\n\nconst attrs = useAttrs();\nconst rootRef = ref<HTMLElement | null>(null);\nconst inputRef = ref<HTMLInputElement | null>(null);\nconst isDragActive = ref(false);\nconst isFocusedWithin = ref(false);\nconst dragDepth = ref(0);\nconst feedbackMessages = ref<string[]>([]);\n\nconst uploadId = createId('tree-file-upload');\nconst descriptionId = `${uploadId}-description`;\nconst feedbackId = `${uploadId}-feedback`;\nconst filesId = `${uploadId}-files`;\n\nconst isUnavailable = computed(() => props.disabled || props.loading);\nconst hasFiles = computed(() => props.modelValue.length > 0);\nconst hasCustomBody = computed(() => Boolean(slots.default));\n\nconst effectiveMaxFiles = computed(() => {\n if (!props.multiple) {\n return 1;\n }\n\n if (typeof props.maxFiles !== 'number') {\n return Number.POSITIVE_INFINITY;\n }\n\n return Math.max(props.maxFiles, 0);\n});\n\nconst rootClasses = computed(() => [\n 'tree-file-upload',\n `tree-file-upload--${props.size}`,\n {\n 'is-disabled': isUnavailable.value,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-drag-active': isDragActive.value,\n 'has-files': hasFiles.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst describedBy = computed(() => {\n const ids: string[] = [];\n\n if (props.description && !hasCustomBody.value) {\n ids.push(descriptionId);\n }\n\n if (feedbackMessages.value.length > 0) {\n ids.push(feedbackId);\n }\n\n if (props.showFileList && hasFiles.value) {\n ids.push(filesId);\n }\n\n return ids.length > 0 ? ids.join(' ') : undefined;\n});\n\nconst selectedFilesLabel = computed(() => `${props.filesLabel} (${props.modelValue.length})`);\n\nconst formatFileSize = (size: number) => {\n if (size < 1024) {\n return `${size} B`;\n }\n\n const units = ['KB', 'MB', 'GB'];\n let value = size / 1024;\n let unitIndex = 0;\n\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex += 1;\n }\n\n const roundedValue = value >= 10 || Number.isInteger(value)\n ? Math.round(value)\n : Number(value.toFixed(1));\n\n return `${roundedValue} ${units[unitIndex]}`;\n};\n\nconst fileKey = (file: File, index: number) =>\n `${file.name}-${file.size}-${file.lastModified}-${index}`;\n\nconst matchesAccept = (file: File) => {\n if (!props.accept.trim()) {\n return true;\n }\n\n const tokens = props.accept\n .split(',')\n .map((token) => token.trim().toLowerCase())\n .filter(Boolean);\n\n const fileName = file.name.toLowerCase();\n const fileType = file.type.toLowerCase();\n\n return tokens.some((token) => {\n if (token.startsWith('.')) {\n return fileName.endsWith(token);\n }\n\n if (token.endsWith('/*')) {\n return fileType.startsWith(token.slice(0, -1));\n }\n\n return fileType === token;\n });\n};\n\nconst buildRejectionMessage = (\n file: File,\n reason: TreeFileUploadRejectionReason,\n) => {\n switch (reason) {\n case 'file-invalid-type':\n return `${file.name} is not an accepted file type.`;\n case 'file-too-large':\n return `${file.name} exceeds the ${formatFileSize(props.maxFileSize ?? 0)} limit.`;\n case 'too-many-files':\n return `You can only add up to ${effectiveMaxFiles.value} file${effectiveMaxFiles.value === 1 ? '' : 's'}.`;\n default:\n return `${file.name} could not be added.`;\n }\n};\n\nconst resetInputValue = () => {\n if (inputRef.value) {\n inputRef.value.value = '';\n }\n};\n\nconst openFileDialog = () => {\n if (isUnavailable.value) {\n return;\n }\n\n inputRef.value?.click();\n};\n\nconst emitFiles = (\n nextFiles: File[],\n acceptedFiles: File[],\n rejections: TreeFileUploadRejection[],\n) => {\n feedbackMessages.value = rejections.map((rejection) => rejection.message);\n\n if (rejections.length > 0) {\n emit('files-rejected', rejections);\n }\n\n if (acceptedFiles.length > 0) {\n emit('update:modelValue', nextFiles);\n emit('files-accepted', acceptedFiles);\n }\n};\n\nconst processFiles = (incomingFiles: File[]) => {\n if (isUnavailable.value || incomingFiles.length === 0) {\n return;\n }\n\n const nextFiles = props.multiple ? [...props.modelValue] : [];\n const acceptedFiles: File[] = [];\n const rejections: TreeFileUploadRejection[] = [];\n let remainingSlots = Number.isFinite(effectiveMaxFiles.value)\n ? Math.max(effectiveMaxFiles.value - nextFiles.length, 0)\n : Number.POSITIVE_INFINITY;\n\n for (const file of incomingFiles) {\n if (remainingSlots <= 0) {\n rejections.push({\n file,\n reason: 'too-many-files',\n message: buildRejectionMessage(file, 'too-many-files'),\n });\n continue;\n }\n\n if (!matchesAccept(file)) {\n rejections.push({\n file,\n reason: 'file-invalid-type',\n message: buildRejectionMessage(file, 'file-invalid-type'),\n });\n continue;\n }\n\n if (\n typeof props.maxFileSize === 'number' &&\n props.maxFileSize > 0 &&\n file.size > props.maxFileSize\n ) {\n rejections.push({\n file,\n reason: 'file-too-large',\n message: buildRejectionMessage(file, 'file-too-large'),\n });\n continue;\n }\n\n acceptedFiles.push(file);\n nextFiles.push(file);\n\n if (Number.isFinite(remainingSlots)) {\n remainingSlots -= 1;\n }\n }\n\n emitFiles(nextFiles, acceptedFiles, rejections);\n};\n\nconst removeFile = (index: number) => {\n if (isUnavailable.value) {\n return;\n }\n\n feedbackMessages.value = [];\n emit('update:modelValue', props.modelValue.filter((_, fileIndex) => fileIndex !== index));\n};\n\nconst clearFiles = () => {\n if (isUnavailable.value || !hasFiles.value) {\n return;\n }\n\n feedbackMessages.value = [];\n emit('update:modelValue', []);\n};\n\nconst hasTransferFiles = (dataTransfer?: DataTransfer | null) => {\n if (!dataTransfer) {\n return false;\n }\n\n return dataTransfer.files.length > 0 || Array.from(dataTransfer.types).includes('Files');\n};\n\nconst getClipboardFiles = (\n clipboardData?: Pick<DataTransfer, 'items'> | null,\n) => {\n if (!clipboardData?.items) {\n return [];\n }\n\n return Array.from(clipboardData.items)\n .map((item) => item.getAsFile?.() ?? null)\n .filter((file): file is File => file instanceof File);\n};\n\nconst onInputChange = (event: Event) => {\n const target = event.target as HTMLInputElement;\n processFiles(Array.from(target.files ?? []));\n resetInputValue();\n};\n\nconst onDropzoneKeydown = (event: KeyboardEvent) => {\n if (!isActivationKey(event) || isUnavailable.value) {\n return;\n }\n\n event.preventDefault();\n openFileDialog();\n};\n\nconst onFocusIn = () => {\n isFocusedWithin.value = true;\n};\n\nconst onFocusOut = (event: FocusEvent) => {\n const nextTarget = event.relatedTarget as Node | null;\n\n if (nextTarget && rootRef.value?.contains(nextTarget)) {\n return;\n }\n\n isFocusedWithin.value = false;\n};\n\nconst onPaste = (event: ClipboardEvent) => {\n if (!props.paste || isUnavailable.value) {\n return;\n }\n\n const clipboardFiles = getClipboardFiles(event.clipboardData);\n\n if (clipboardFiles.length === 0) {\n return;\n }\n\n event.preventDefault();\n processFiles(clipboardFiles);\n};\n\nconst onDocumentPaste = (event: Event) => {\n if (!isFocusedWithin.value || event.defaultPrevented) {\n return;\n }\n\n onPaste(event as ClipboardEvent);\n};\n\nconst onDragEnter = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value += 1;\n isDragActive.value = true;\n};\n\nconst onDragOver = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'copy';\n }\n\n isDragActive.value = true;\n};\n\nconst onDragLeave = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = Math.max(dragDepth.value - 1, 0);\n\n if (dragDepth.value === 0) {\n isDragActive.value = false;\n }\n};\n\nconst onDrop = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = 0;\n isDragActive.value = false;\n processFiles(Array.from(event.dataTransfer?.files ?? []));\n};\n\nonMounted(() => {\n document.addEventListener('paste', onDocumentPaste);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('paste', onDocumentPaste);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n @paste=\"onPaste\"\n >\n <input\n :id=\"uploadId\"\n ref=\"inputRef\"\n class=\"tree-visually-hidden\"\n type=\"file\"\n :accept=\"accept || undefined\"\n :multiple=\"multiple\"\n :disabled=\"isUnavailable\"\n @change=\"onInputChange\"\n >\n\n <div\n class=\"tree-file-upload__dropzone\"\n :aria-busy=\"loading || undefined\"\n :aria-controls=\"showFileList && hasFiles ? filesId : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-disabled=\"isUnavailable || undefined\"\n :aria-invalid=\"invalid || undefined\"\n role=\"button\"\n :tabindex=\"isUnavailable ? -1 : 0\"\n @click=\"openFileDialog\"\n @keydown=\"onDropzoneKeydown\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <div\n v-if=\"$slots.icon || !$slots.default\"\n class=\"tree-file-upload__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\">\n <span class=\"tree-file-upload__icon-mark\">+</span>\n </slot>\n </div>\n\n <div class=\"tree-file-upload__content\">\n <slot\n :files=\"modelValue\"\n :is-drag-active=\"isDragActive\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n >\n <p class=\"tree-file-upload__label\">\n {{ label }}\n </p>\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"tree-file-upload__description\"\n >\n {{ description }}\n </p>\n <span class=\"tree-file-upload__browse\">\n {{ buttonLabel }}\n </span>\n </slot>\n </div>\n\n <TreeSpinner\n v-if=\"loading\"\n class=\"tree-file-upload__spinner\"\n size=\"sm\"\n label=\"Uploading files\"\n />\n </div>\n\n <ul\n v-if=\"feedbackMessages.length > 0\"\n :id=\"feedbackId\"\n class=\"tree-file-upload__feedback\"\n aria-live=\"polite\"\n >\n <li\n v-for=\"message in feedbackMessages\"\n :key=\"message\"\n >\n {{ message }}\n </li>\n </ul>\n\n <div\n v-if=\"showFileList && hasFiles\"\n class=\"tree-file-upload__files\"\n >\n <div class=\"tree-file-upload__files-header\">\n <p\n :id=\"filesId\"\n class=\"tree-file-upload__files-label\"\n >\n {{ selectedFilesLabel }}\n </p>\n\n <button\n class=\"tree-file-upload__clear\"\n type=\"button\"\n :disabled=\"isUnavailable\"\n @click=\"clearFiles\"\n >\n Clear all\n </button>\n </div>\n\n <ul class=\"tree-file-upload__list\">\n <li\n v-for=\"(file, index) in modelValue\"\n :key=\"fileKey(file, index)\"\n class=\"tree-file-upload__file\"\n >\n <slot\n name=\"file\"\n :file=\"file\"\n :index=\"index\"\n :remove-file=\"() => removeFile(index)\"\n >\n <div class=\"tree-file-upload__file-copy\">\n <p class=\"tree-file-upload__file-name\">\n {{ file.name }}\n </p>\n <p class=\"tree-file-upload__file-meta\">\n {{ formatFileSize(file.size) }}\n </p>\n </div>\n\n <button\n class=\"tree-file-upload__remove\"\n type=\"button\"\n :disabled=\"isUnavailable\"\n :aria-label=\"`Remove ${file.name}`\"\n @click=\"removeFile(index)\"\n >\n Remove\n </button>\n </slot>\n </li>\n </ul>\n </div>\n\n <div\n v-if=\"$slots.actions\"\n class=\"tree-file-upload__actions\"\n >\n <slot\n name=\"actions\"\n :files=\"modelValue\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey } from '@treeui/utils';\nimport { computed, onBeforeUnmount, onMounted, ref, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport type TreeFileUploadRejectionReason =\n | 'file-invalid-type'\n | 'file-too-large'\n | 'too-many-files';\n\nexport interface TreeFileUploadRejection {\n file: File;\n reason: TreeFileUploadRejectionReason;\n message: string;\n}\n\nconst slots = defineSlots<{\n icon?: () => unknown;\n default?: (props: {\n files: File[];\n isDragActive: boolean;\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n file?: (props: {\n file: File;\n index: number;\n removeFile: () => void;\n }) => unknown;\n actions?: (props: {\n files: File[];\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: File[];\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n accept?: string;\n multiple?: boolean;\n maxFiles?: number | null;\n maxFileSize?: number | null;\n label?: string;\n description?: string;\n buttonLabel?: string;\n filesLabel?: string;\n paste?: boolean;\n drop?: boolean;\n showFileList?: boolean;\n }>(),\n {\n modelValue: () => [],\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n accept: '',\n multiple: true,\n label: 'Drop files here',\n description: 'Click to browse, drag and drop, or paste with Ctrl+V.',\n buttonLabel: 'Browse files',\n filesLabel: 'Selected files',\n maxFiles: null,\n maxFileSize: null,\n paste: true,\n drop: true,\n showFileList: true,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [files: File[]];\n 'files-accepted': [files: File[]];\n 'files-rejected': [rejections: TreeFileUploadRejection[]];\n}>();\n\nconst attrs = useAttrs();\nconst rootRef = ref<HTMLElement | null>(null);\nconst inputRef = ref<HTMLInputElement | null>(null);\nconst isDragActive = ref(false);\nconst isFocusedWithin = ref(false);\nconst dragDepth = ref(0);\nconst feedbackMessages = ref<string[]>([]);\n\nconst uploadId = createId('tree-file-upload');\nconst descriptionId = `${uploadId}-description`;\nconst feedbackId = `${uploadId}-feedback`;\nconst filesId = `${uploadId}-files`;\n\nconst isUnavailable = computed(() => props.disabled || props.loading);\nconst hasFiles = computed(() => props.modelValue.length > 0);\nconst hasCustomBody = computed(() => Boolean(slots.default));\n\nconst effectiveMaxFiles = computed(() => {\n if (!props.multiple) {\n return 1;\n }\n\n if (typeof props.maxFiles !== 'number') {\n return Number.POSITIVE_INFINITY;\n }\n\n return Math.max(props.maxFiles, 0);\n});\n\nconst rootClasses = computed(() => [\n 'tree-file-upload',\n `tree-file-upload--${props.size}`,\n {\n 'is-disabled': isUnavailable.value,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-drag-active': isDragActive.value,\n 'has-files': hasFiles.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst describedBy = computed(() => {\n const ids: string[] = [];\n\n if (props.description && !hasCustomBody.value) {\n ids.push(descriptionId);\n }\n\n if (feedbackMessages.value.length > 0) {\n ids.push(feedbackId);\n }\n\n if (props.showFileList && hasFiles.value) {\n ids.push(filesId);\n }\n\n return ids.length > 0 ? ids.join(' ') : undefined;\n});\n\nconst selectedFilesLabel = computed(() => `${props.filesLabel} (${props.modelValue.length})`);\n\nconst formatFileSize = (size: number) => {\n if (size < 1024) {\n return `${size} B`;\n }\n\n const units = ['KB', 'MB', 'GB'];\n let value = size / 1024;\n let unitIndex = 0;\n\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex += 1;\n }\n\n const roundedValue = value >= 10 || Number.isInteger(value)\n ? Math.round(value)\n : Number(value.toFixed(1));\n\n return `${roundedValue} ${units[unitIndex]}`;\n};\n\nconst fileKey = (file: File, index: number) =>\n `${file.name}-${file.size}-${file.lastModified}-${index}`;\n\nconst matchesAccept = (file: File) => {\n if (!props.accept.trim()) {\n return true;\n }\n\n const tokens = props.accept\n .split(',')\n .map((token) => token.trim().toLowerCase())\n .filter(Boolean);\n\n const fileName = file.name.toLowerCase();\n const fileType = file.type.toLowerCase();\n\n return tokens.some((token) => {\n if (token.startsWith('.')) {\n return fileName.endsWith(token);\n }\n\n if (token.endsWith('/*')) {\n return fileType.startsWith(token.slice(0, -1));\n }\n\n return fileType === token;\n });\n};\n\nconst buildRejectionMessage = (\n file: File,\n reason: TreeFileUploadRejectionReason,\n) => {\n switch (reason) {\n case 'file-invalid-type':\n return `${file.name} is not an accepted file type.`;\n case 'file-too-large':\n return `${file.name} exceeds the ${formatFileSize(props.maxFileSize ?? 0)} limit.`;\n case 'too-many-files':\n return `You can only add up to ${effectiveMaxFiles.value} file${effectiveMaxFiles.value === 1 ? '' : 's'}.`;\n default:\n return `${file.name} could not be added.`;\n }\n};\n\nconst resetInputValue = () => {\n if (inputRef.value) {\n inputRef.value.value = '';\n }\n};\n\nconst openFileDialog = () => {\n if (isUnavailable.value) {\n return;\n }\n\n inputRef.value?.click();\n};\n\nconst emitFiles = (\n nextFiles: File[],\n acceptedFiles: File[],\n rejections: TreeFileUploadRejection[],\n) => {\n feedbackMessages.value = rejections.map((rejection) => rejection.message);\n\n if (rejections.length > 0) {\n emit('files-rejected', rejections);\n }\n\n if (acceptedFiles.length > 0) {\n emit('update:modelValue', nextFiles);\n emit('files-accepted', acceptedFiles);\n }\n};\n\nconst processFiles = (incomingFiles: File[]) => {\n if (isUnavailable.value || incomingFiles.length === 0) {\n return;\n }\n\n const nextFiles = props.multiple ? [...props.modelValue] : [];\n const acceptedFiles: File[] = [];\n const rejections: TreeFileUploadRejection[] = [];\n let remainingSlots = Number.isFinite(effectiveMaxFiles.value)\n ? Math.max(effectiveMaxFiles.value - nextFiles.length, 0)\n : Number.POSITIVE_INFINITY;\n\n for (const file of incomingFiles) {\n if (remainingSlots <= 0) {\n rejections.push({\n file,\n reason: 'too-many-files',\n message: buildRejectionMessage(file, 'too-many-files'),\n });\n continue;\n }\n\n if (!matchesAccept(file)) {\n rejections.push({\n file,\n reason: 'file-invalid-type',\n message: buildRejectionMessage(file, 'file-invalid-type'),\n });\n continue;\n }\n\n if (\n typeof props.maxFileSize === 'number' &&\n props.maxFileSize > 0 &&\n file.size > props.maxFileSize\n ) {\n rejections.push({\n file,\n reason: 'file-too-large',\n message: buildRejectionMessage(file, 'file-too-large'),\n });\n continue;\n }\n\n acceptedFiles.push(file);\n nextFiles.push(file);\n\n if (Number.isFinite(remainingSlots)) {\n remainingSlots -= 1;\n }\n }\n\n emitFiles(nextFiles, acceptedFiles, rejections);\n};\n\nconst removeFile = (index: number) => {\n if (isUnavailable.value) {\n return;\n }\n\n feedbackMessages.value = [];\n emit('update:modelValue', props.modelValue.filter((_, fileIndex) => fileIndex !== index));\n};\n\nconst clearFiles = () => {\n if (isUnavailable.value || !hasFiles.value) {\n return;\n }\n\n feedbackMessages.value = [];\n emit('update:modelValue', []);\n};\n\nconst hasTransferFiles = (dataTransfer?: DataTransfer | null) => {\n if (!dataTransfer) {\n return false;\n }\n\n return dataTransfer.files.length > 0 || Array.from(dataTransfer.types).includes('Files');\n};\n\nconst getClipboardFiles = (\n clipboardData?: Pick<DataTransfer, 'items'> | null,\n) => {\n if (!clipboardData?.items) {\n return [];\n }\n\n return Array.from(clipboardData.items)\n .map((item) => item.getAsFile?.() ?? null)\n .filter((file): file is File => file instanceof File);\n};\n\nconst onInputChange = (event: Event) => {\n const target = event.target as HTMLInputElement;\n processFiles(Array.from(target.files ?? []));\n resetInputValue();\n};\n\nconst onDropzoneKeydown = (event: KeyboardEvent) => {\n if (!isActivationKey(event) || isUnavailable.value) {\n return;\n }\n\n event.preventDefault();\n openFileDialog();\n};\n\nconst onFocusIn = () => {\n isFocusedWithin.value = true;\n};\n\nconst onFocusOut = (event: FocusEvent) => {\n const nextTarget = event.relatedTarget as Node | null;\n\n if (nextTarget && rootRef.value?.contains(nextTarget)) {\n return;\n }\n\n isFocusedWithin.value = false;\n};\n\nconst onPaste = (event: ClipboardEvent) => {\n if (!props.paste || isUnavailable.value) {\n return;\n }\n\n const clipboardFiles = getClipboardFiles(event.clipboardData);\n\n if (clipboardFiles.length === 0) {\n return;\n }\n\n event.preventDefault();\n processFiles(clipboardFiles);\n};\n\nconst onDocumentPaste = (event: Event) => {\n if (!isFocusedWithin.value || event.defaultPrevented) {\n return;\n }\n\n onPaste(event as ClipboardEvent);\n};\n\nconst onDragEnter = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value += 1;\n isDragActive.value = true;\n};\n\nconst onDragOver = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'copy';\n }\n\n isDragActive.value = true;\n};\n\nconst onDragLeave = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = Math.max(dragDepth.value - 1, 0);\n\n if (dragDepth.value === 0) {\n isDragActive.value = false;\n }\n};\n\nconst onDrop = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = 0;\n isDragActive.value = false;\n processFiles(Array.from(event.dataTransfer?.files ?? []));\n};\n\nonMounted(() => {\n document.addEventListener('paste', onDocumentPaste);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('paste', onDocumentPaste);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n @paste=\"onPaste\"\n >\n <input\n :id=\"uploadId\"\n ref=\"inputRef\"\n class=\"tree-visually-hidden\"\n type=\"file\"\n :accept=\"accept || undefined\"\n :multiple=\"multiple\"\n :disabled=\"isUnavailable\"\n @change=\"onInputChange\"\n >\n\n <div\n class=\"tree-file-upload__dropzone\"\n :aria-busy=\"loading || undefined\"\n :aria-controls=\"showFileList && hasFiles ? filesId : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-disabled=\"isUnavailable || undefined\"\n :aria-invalid=\"invalid || undefined\"\n role=\"button\"\n :tabindex=\"isUnavailable ? -1 : 0\"\n @click=\"openFileDialog\"\n @keydown=\"onDropzoneKeydown\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <div\n v-if=\"$slots.icon || !$slots.default\"\n class=\"tree-file-upload__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\">\n <span class=\"tree-file-upload__icon-mark\">+</span>\n </slot>\n </div>\n\n <div class=\"tree-file-upload__content\">\n <slot\n :files=\"modelValue\"\n :is-drag-active=\"isDragActive\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n >\n <p class=\"tree-file-upload__label\">\n {{ label }}\n </p>\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"tree-file-upload__description\"\n >\n {{ description }}\n </p>\n <span class=\"tree-file-upload__browse\">\n {{ buttonLabel }}\n </span>\n </slot>\n </div>\n\n <TreeSpinner\n v-if=\"loading\"\n class=\"tree-file-upload__spinner\"\n size=\"sm\"\n label=\"Uploading files\"\n />\n </div>\n\n <ul\n v-if=\"feedbackMessages.length > 0\"\n :id=\"feedbackId\"\n class=\"tree-file-upload__feedback\"\n aria-live=\"polite\"\n >\n <li\n v-for=\"message in feedbackMessages\"\n :key=\"message\"\n >\n {{ message }}\n </li>\n </ul>\n\n <div\n v-if=\"showFileList && hasFiles\"\n class=\"tree-file-upload__files\"\n >\n <div class=\"tree-file-upload__files-header\">\n <p\n :id=\"filesId\"\n class=\"tree-file-upload__files-label\"\n >\n {{ selectedFilesLabel }}\n </p>\n\n <button\n class=\"tree-file-upload__clear\"\n type=\"button\"\n :disabled=\"isUnavailable\"\n @click=\"clearFiles\"\n >\n Clear all\n </button>\n </div>\n\n <ul class=\"tree-file-upload__list\">\n <li\n v-for=\"(file, index) in modelValue\"\n :key=\"fileKey(file, index)\"\n class=\"tree-file-upload__file\"\n >\n <slot\n name=\"file\"\n :file=\"file\"\n :index=\"index\"\n :remove-file=\"() => removeFile(index)\"\n >\n <div class=\"tree-file-upload__file-copy\">\n <p class=\"tree-file-upload__file-name\">\n {{ file.name }}\n </p>\n <p class=\"tree-file-upload__file-meta\">\n {{ formatFileSize(file.size) }}\n </p>\n </div>\n\n <button\n class=\"tree-file-upload__remove\"\n type=\"button\"\n :disabled=\"isUnavailable\"\n :aria-label=\"`Remove ${file.name}`\"\n @click=\"removeFile(index)\"\n >\n Remove\n </button>\n </slot>\n </li>\n </ul>\n </div>\n\n <div\n v-if=\"$slots.actions\"\n class=\"tree-file-upload__actions\"\n >\n <slot\n name=\"actions\"\n :files=\"modelValue\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { createId, getNextEnabledIndex, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeMultiSelectOption {\n label: string;\n value: string;\n description?: string;\n keywords?: string[];\n disabled?: boolean;\n}\n\nconst ChevronDownIcon = getTreeIcon('chevron-down');\nconst CheckIcon = getTreeIcon('check');\nconst XIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string[];\n options?: TreeMultiSelectOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n emptyText?: string;\n maxVisibleTags?: number;\n }>(),\n {\n modelValue: () => [],\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n emptyText: 'No results found.',\n maxVisibleTags: 2,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string[]];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n 'input-change': [value: string];\n}>();\n\ndefineSlots<{\n prefix?: () => unknown;\n tag?: (props: { option: TreeMultiSelectOption; remove: () => void }) => unknown;\n option?: (props: {\n option: TreeMultiSelectOption;\n selected: boolean;\n active: boolean;\n }) => unknown;\n empty?: (props: { query: string }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('tree-multi-select');\nconst rootRef = ref<HTMLElement | null>(null);\nconst inputRef = ref<HTMLInputElement | null>(null);\nconst query = ref('');\nconst activeIndex = ref(-1);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, autocomplete, ...rest } = attrs;\n return {\n autocomplete: typeof autocomplete === 'string' ? autocomplete : 'off',\n ...rest,\n };\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-multi-select',\n `tree-multi-select--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst normalize = (value: string) => value.trim().toLowerCase();\n\nconst filteredOptions = computed(() => {\n const normalizedQuery = normalize(query.value);\n\n if (!normalizedQuery) {\n return props.options;\n }\n\n return props.options.filter((option) => {\n const fields = [option.label, option.description ?? '', ...(option.keywords ?? [])];\n return fields.some((field) => field.toLowerCase().includes(normalizedQuery));\n });\n});\n\nconst selectedOptions = computed(() =>\n props.options.filter((option) => props.modelValue.includes(option.value)),\n);\n\nconst visibleTags = computed(() => selectedOptions.value.slice(0, props.maxVisibleTags));\nconst hiddenTagCount = computed(() =>\n Math.max(selectedOptions.value.length - visibleTags.value.length, 0),\n);\n\nconst enabledFilteredOptions = computed(() => filteredOptions.value.filter((option) => !option.disabled));\n\nconst activeOption = computed(() =>\n activeIndex.value >= 0 ? filteredOptions.value[activeIndex.value] : undefined,\n);\n\nconst activeDescendant = computed(() =>\n isOpen.value && activeOption.value\n ? `${listboxId}-option-${activeOption.value.value}`\n : undefined,\n);\n\nconst inputPlaceholder = computed(() =>\n props.modelValue.length === 0 && !query.value ? props.placeholder : '',\n);\n\nconst isSelected = (value: string) => props.modelValue.includes(value);\n\nconst setInitialActiveIndex = (fallback: 'first' | 'last' = 'first') => {\n const selectedIndex = filteredOptions.value.findIndex(\n (option) => isSelected(option.value) && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n activeIndex.value = selectedIndex;\n return;\n }\n\n if (enabledFilteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const targetOption =\n fallback === 'last'\n ? enabledFilteredOptions.value[enabledFilteredOptions.value.length - 1]\n : enabledFilteredOptions.value[0];\n\n activeIndex.value = filteredOptions.value.findIndex(\n (option) => option.value === targetOption.value,\n );\n};\n\nconst openListbox = (fallback: 'first' | 'last' = 'first') => {\n if (props.disabled) {\n return;\n }\n\n setValue(true);\n setInitialActiveIndex(fallback);\n};\n\nconst closeListbox = () => {\n setValue(false);\n activeIndex.value = -1;\n};\n\nconst focusInput = () => {\n nextTick(() => inputRef.value?.focus());\n};\n\nconst updateValues = (nextValues: string[]) => {\n emit('update:modelValue', nextValues);\n};\n\nconst toggleOption = (option: TreeMultiSelectOption) => {\n if (props.disabled || option.disabled) {\n return;\n }\n\n const nextValues = isSelected(option.value)\n ? props.modelValue.filter((value) => value !== option.value)\n : [...props.modelValue, option.value];\n\n updateValues(nextValues);\n query.value = '';\n setInitialActiveIndex('first');\n focusInput();\n};\n\nconst removeValue = (value: string) => {\n if (props.disabled) {\n return;\n }\n\n updateValues(props.modelValue.filter((item) => item !== value));\n focusInput();\n};\n\nconst moveActive = (direction: 1 | -1) => {\n if (filteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const nextIndex = getNextEnabledIndex(activeIndex.value, filteredOptions.value, direction);\n activeIndex.value = nextIndex;\n};\n\nconst onInput = (event: Event) => {\n query.value = (event.target as HTMLInputElement).value;\n emit('input-change', query.value);\n\n if (!props.disabled && !isOpen.value) {\n openListbox('first');\n return;\n }\n\n setInitialActiveIndex('first');\n};\n\nconst onInputFocus = () => {\n openListbox('first');\n};\n\nconst onInputKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Tab') {\n closeListbox();\n return;\n }\n\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeListbox();\n return;\n }\n\n if (event.key === 'Backspace' && !query.value && props.modelValue.length > 0) {\n event.preventDefault();\n removeValue(props.modelValue[props.modelValue.length - 1]);\n return;\n }\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('first');\n return;\n }\n\n moveActive(1);\n return;\n }\n\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('last');\n return;\n }\n\n moveActive(-1);\n return;\n }\n\n if (event.key === 'Home' && isOpen.value) {\n event.preventDefault();\n setInitialActiveIndex('first');\n return;\n }\n\n if (event.key === 'End' && isOpen.value) {\n event.preventDefault();\n setInitialActiveIndex('last');\n return;\n }\n\n if (event.key === 'Enter' && activeOption.value) {\n event.preventDefault();\n toggleOption(activeOption.value);\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeListbox();\n};\n\nwatch(\n isOpen,\n (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n },\n);\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <div\n class=\"tree-multi-select__control\"\n @click=\"focusInput\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-multi-select__slot\"\n >\n <slot name=\"prefix\" />\n </span>\n\n <div class=\"tree-multi-select__values\">\n <span\n v-for=\"option in visibleTags\"\n :key=\"option.value\"\n class=\"tree-multi-select__tag\"\n >\n <slot\n name=\"tag\"\n :option=\"option\"\n :remove=\"() => removeValue(option.value)\"\n >\n <span class=\"tree-multi-select__tag-label\">{{ option.label }}</span>\n <button\n type=\"button\"\n class=\"tree-multi-select__tag-remove\"\n :disabled=\"disabled\"\n aria-label=\"Remove selection\"\n @mousedown.prevent\n @click.stop=\"removeValue(option.value)\"\n >\n <XIcon :size=\"12\" />\n </button>\n </slot>\n </span>\n\n <span\n v-if=\"hiddenTagCount > 0\"\n class=\"tree-multi-select__overflow\"\n >\n +{{ hiddenTagCount }}\n </span>\n\n <input\n ref=\"inputRef\"\n v-bind=\"inputAttrs\"\n :value=\"query\"\n type=\"text\"\n class=\"tree-multi-select__input\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n :aria-activedescendant=\"activeDescendant\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n :disabled=\"disabled\"\n :placeholder=\"inputPlaceholder\"\n @focus=\"onInputFocus\"\n @input=\"onInput\"\n @keydown=\"onInputKeydown\"\n >\n </div>\n\n <TreeSpinner\n v-if=\"loading\"\n class=\"tree-multi-select__indicator\"\n size=\"sm\"\n />\n <ChevronDownIcon\n v-else\n class=\"tree-multi-select__indicator\"\n :size=\"16\"\n />\n </div>\n\n <Transition name=\"tree-fade\">\n <ul\n v-if=\"isOpen\"\n :id=\"listboxId\"\n class=\"tree-multi-select__listbox\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n >\n <li\n v-if=\"filteredOptions.length === 0\"\n class=\"tree-multi-select__empty\"\n >\n <slot\n name=\"empty\"\n :query=\"query\"\n >\n {{ emptyText }}\n </slot>\n </li>\n\n <template v-else>\n <li\n v-for=\"(option, index) in filteredOptions\"\n :key=\"option.value\"\n >\n <button\n :id=\"`${listboxId}-option-${option.value}`\"\n type=\"button\"\n class=\"tree-multi-select__option\"\n :class=\"{\n 'is-active': index === activeIndex,\n 'is-selected': isSelected(option.value),\n 'is-disabled': option.disabled,\n }\"\n role=\"option\"\n :aria-selected=\"isSelected(option.value)\"\n :aria-disabled=\"option.disabled || undefined\"\n :disabled=\"option.disabled\"\n @mousedown.prevent\n @click=\"toggleOption(option)\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"isSelected(option.value)\"\n :active=\"index === activeIndex\"\n >\n <span class=\"tree-multi-select__option-copy\">\n <span class=\"tree-multi-select__option-label\">{{ option.label }}</span>\n <span\n v-if=\"option.description\"\n class=\"tree-multi-select__option-description\"\n >\n {{ option.description }}\n </span>\n </span>\n\n <span\n class=\"tree-multi-select__check\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"isSelected(option.value)\"\n :size=\"16\"\n />\n </span>\n </slot>\n </button>\n </li>\n </template>\n </ul>\n </Transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { createId, getNextEnabledIndex, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeMultiSelectOption {\n label: string;\n value: string;\n description?: string;\n keywords?: string[];\n disabled?: boolean;\n}\n\nconst ChevronDownIcon = getTreeIcon('chevron-down');\nconst CheckIcon = getTreeIcon('check');\nconst XIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string[];\n options?: TreeMultiSelectOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n emptyText?: string;\n maxVisibleTags?: number;\n }>(),\n {\n modelValue: () => [],\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n emptyText: 'No results found.',\n maxVisibleTags: 2,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string[]];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n 'input-change': [value: string];\n}>();\n\ndefineSlots<{\n prefix?: () => unknown;\n tag?: (props: { option: TreeMultiSelectOption; remove: () => void }) => unknown;\n option?: (props: {\n option: TreeMultiSelectOption;\n selected: boolean;\n active: boolean;\n }) => unknown;\n empty?: (props: { query: string }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('tree-multi-select');\nconst rootRef = ref<HTMLElement | null>(null);\nconst inputRef = ref<HTMLInputElement | null>(null);\nconst query = ref('');\nconst activeIndex = ref(-1);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, autocomplete, ...rest } = attrs;\n return {\n autocomplete: typeof autocomplete === 'string' ? autocomplete : 'off',\n ...rest,\n };\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-multi-select',\n `tree-multi-select--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst normalize = (value: string) => value.trim().toLowerCase();\n\nconst filteredOptions = computed(() => {\n const normalizedQuery = normalize(query.value);\n\n if (!normalizedQuery) {\n return props.options;\n }\n\n return props.options.filter((option) => {\n const fields = [option.label, option.description ?? '', ...(option.keywords ?? [])];\n return fields.some((field) => field.toLowerCase().includes(normalizedQuery));\n });\n});\n\nconst selectedOptions = computed(() =>\n props.options.filter((option) => props.modelValue.includes(option.value)),\n);\n\nconst visibleTags = computed(() => selectedOptions.value.slice(0, props.maxVisibleTags));\nconst hiddenTagCount = computed(() =>\n Math.max(selectedOptions.value.length - visibleTags.value.length, 0),\n);\n\nconst enabledFilteredOptions = computed(() => filteredOptions.value.filter((option) => !option.disabled));\n\nconst activeOption = computed(() =>\n activeIndex.value >= 0 ? filteredOptions.value[activeIndex.value] : undefined,\n);\n\nconst activeDescendant = computed(() =>\n isOpen.value && activeOption.value\n ? `${listboxId}-option-${activeOption.value.value}`\n : undefined,\n);\n\nconst inputPlaceholder = computed(() =>\n props.modelValue.length === 0 && !query.value ? props.placeholder : '',\n);\n\nconst isSelected = (value: string) => props.modelValue.includes(value);\n\nconst setInitialActiveIndex = (fallback: 'first' | 'last' = 'first') => {\n const selectedIndex = filteredOptions.value.findIndex(\n (option) => isSelected(option.value) && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n activeIndex.value = selectedIndex;\n return;\n }\n\n if (enabledFilteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const targetOption =\n fallback === 'last'\n ? enabledFilteredOptions.value[enabledFilteredOptions.value.length - 1]\n : enabledFilteredOptions.value[0];\n\n activeIndex.value = filteredOptions.value.findIndex(\n (option) => option.value === targetOption.value,\n );\n};\n\nconst openListbox = (fallback: 'first' | 'last' = 'first') => {\n if (props.disabled) {\n return;\n }\n\n setValue(true);\n setInitialActiveIndex(fallback);\n};\n\nconst closeListbox = () => {\n setValue(false);\n activeIndex.value = -1;\n};\n\nconst focusInput = () => {\n nextTick(() => inputRef.value?.focus());\n};\n\nconst updateValues = (nextValues: string[]) => {\n emit('update:modelValue', nextValues);\n};\n\nconst toggleOption = (option: TreeMultiSelectOption) => {\n if (props.disabled || option.disabled) {\n return;\n }\n\n const nextValues = isSelected(option.value)\n ? props.modelValue.filter((value) => value !== option.value)\n : [...props.modelValue, option.value];\n\n updateValues(nextValues);\n query.value = '';\n setInitialActiveIndex('first');\n focusInput();\n};\n\nconst removeValue = (value: string) => {\n if (props.disabled) {\n return;\n }\n\n updateValues(props.modelValue.filter((item) => item !== value));\n focusInput();\n};\n\nconst moveActive = (direction: 1 | -1) => {\n if (filteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const nextIndex = getNextEnabledIndex(activeIndex.value, filteredOptions.value, direction);\n activeIndex.value = nextIndex;\n};\n\nconst onInput = (event: Event) => {\n query.value = (event.target as HTMLInputElement).value;\n emit('input-change', query.value);\n\n if (!props.disabled && !isOpen.value) {\n openListbox('first');\n return;\n }\n\n setInitialActiveIndex('first');\n};\n\nconst onInputFocus = () => {\n openListbox('first');\n};\n\nconst onInputKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Tab') {\n closeListbox();\n return;\n }\n\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeListbox();\n return;\n }\n\n if (event.key === 'Backspace' && !query.value && props.modelValue.length > 0) {\n event.preventDefault();\n removeValue(props.modelValue[props.modelValue.length - 1]);\n return;\n }\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('first');\n return;\n }\n\n moveActive(1);\n return;\n }\n\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('last');\n return;\n }\n\n moveActive(-1);\n return;\n }\n\n if (event.key === 'Home' && isOpen.value) {\n event.preventDefault();\n setInitialActiveIndex('first');\n return;\n }\n\n if (event.key === 'End' && isOpen.value) {\n event.preventDefault();\n setInitialActiveIndex('last');\n return;\n }\n\n if (event.key === 'Enter' && activeOption.value) {\n event.preventDefault();\n toggleOption(activeOption.value);\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeListbox();\n};\n\nwatch(\n isOpen,\n (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n },\n);\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <div\n class=\"tree-multi-select__control\"\n @click=\"focusInput\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-multi-select__slot\"\n >\n <slot name=\"prefix\" />\n </span>\n\n <div class=\"tree-multi-select__values\">\n <span\n v-for=\"option in visibleTags\"\n :key=\"option.value\"\n class=\"tree-multi-select__tag\"\n >\n <slot\n name=\"tag\"\n :option=\"option\"\n :remove=\"() => removeValue(option.value)\"\n >\n <span class=\"tree-multi-select__tag-label\">{{ option.label }}</span>\n <button\n type=\"button\"\n class=\"tree-multi-select__tag-remove\"\n :disabled=\"disabled\"\n aria-label=\"Remove selection\"\n @mousedown.prevent\n @click.stop=\"removeValue(option.value)\"\n >\n <XIcon :size=\"12\" />\n </button>\n </slot>\n </span>\n\n <span\n v-if=\"hiddenTagCount > 0\"\n class=\"tree-multi-select__overflow\"\n >\n +{{ hiddenTagCount }}\n </span>\n\n <input\n ref=\"inputRef\"\n v-bind=\"inputAttrs\"\n :value=\"query\"\n type=\"text\"\n class=\"tree-multi-select__input\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n :aria-activedescendant=\"activeDescendant\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n :disabled=\"disabled\"\n :placeholder=\"inputPlaceholder\"\n @focus=\"onInputFocus\"\n @input=\"onInput\"\n @keydown=\"onInputKeydown\"\n >\n </div>\n\n <TreeSpinner\n v-if=\"loading\"\n class=\"tree-multi-select__indicator\"\n size=\"sm\"\n />\n <ChevronDownIcon\n v-else\n class=\"tree-multi-select__indicator\"\n :size=\"16\"\n />\n </div>\n\n <Transition name=\"tree-fade\">\n <ul\n v-if=\"isOpen\"\n :id=\"listboxId\"\n class=\"tree-multi-select__listbox\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n >\n <li\n v-if=\"filteredOptions.length === 0\"\n class=\"tree-multi-select__empty\"\n >\n <slot\n name=\"empty\"\n :query=\"query\"\n >\n {{ emptyText }}\n </slot>\n </li>\n\n <template v-else>\n <li\n v-for=\"(option, index) in filteredOptions\"\n :key=\"option.value\"\n >\n <button\n :id=\"`${listboxId}-option-${option.value}`\"\n type=\"button\"\n class=\"tree-multi-select__option\"\n :class=\"{\n 'is-active': index === activeIndex,\n 'is-selected': isSelected(option.value),\n 'is-disabled': option.disabled,\n }\"\n role=\"option\"\n :aria-selected=\"isSelected(option.value)\"\n :aria-disabled=\"option.disabled || undefined\"\n :disabled=\"option.disabled\"\n @mousedown.prevent\n @click=\"toggleOption(option)\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"isSelected(option.value)\"\n :active=\"index === activeIndex\"\n >\n <span class=\"tree-multi-select__option-copy\">\n <span class=\"tree-multi-select__option-label\">{{ option.label }}</span>\n <span\n v-if=\"option.description\"\n class=\"tree-multi-select__option-description\"\n >\n {{ option.description }}\n </span>\n </span>\n\n <span\n class=\"tree-multi-select__check\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"isSelected(option.value)\"\n :size=\"16\"\n />\n </span>\n </slot>\n </button>\n </li>\n </template>\n </ul>\n </Transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n columns?: number;\n minItemWidth?: string;\n gap?: string;\n rowGap?: string;\n align?: string;\n justify?: string;\n dense?: boolean;\n }>(),\n {\n as: 'div',\n columns: undefined,\n minItemWidth: '16rem',\n gap: 'var(--tree-space-4)',\n rowGap: undefined,\n align: 'stretch',\n justify: 'stretch',\n dense: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-grid',\n {\n 'is-dense': props.dense,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n gap: props.gap,\n rowGap: props.rowGap ?? props.gap,\n alignItems: props.align,\n justifyItems: props.justify,\n gridTemplateColumns:\n typeof props.columns === 'number' && props.columns > 0\n ? `repeat(${props.columns}, minmax(0, 1fr))`\n : `repeat(auto-fit, minmax(min(${props.minItemWidth}, 100%), 1fr))`,\n gridAutoFlow: props.dense ? 'dense' : 'row',\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n columns?: number;\n minItemWidth?: string;\n gap?: string;\n rowGap?: string;\n align?: string;\n justify?: string;\n dense?: boolean;\n }>(),\n {\n as: 'div',\n columns: undefined,\n minItemWidth: '16rem',\n gap: 'var(--tree-space-4)',\n rowGap: undefined,\n align: 'stretch',\n justify: 'stretch',\n dense: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-grid',\n {\n 'is-dense': props.dense,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n gap: props.gap,\n rowGap: props.rowGap ?? props.gap,\n alignItems: props.align,\n justifyItems: props.justify,\n gridTemplateColumns:\n typeof props.columns === 'number' && props.columns > 0\n ? `repeat(${props.columns}, minmax(0, 1fr))`\n : `repeat(auto-fit, minmax(min(${props.minItemWidth}, 100%), 1fr))`,\n gridAutoFlow: props.dense ? 'dense' : 'row',\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TreeSize;\n sticky?: boolean;\n bordered?: boolean;\n elevated?: boolean;\n }>(),\n {\n as: 'header',\n size: 'md',\n sticky: false,\n bordered: true,\n elevated: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-navbar',\n `tree-navbar--${props.size}`,\n {\n 'is-sticky': props.sticky,\n 'is-bordered': props.bordered,\n 'is-elevated': props.elevated,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <div class=\"tree-navbar__inner\">\n <div\n v-if=\"$slots.start\"\n class=\"tree-navbar__section tree-navbar__section--start\"\n >\n <slot name=\"start\" />\n </div>\n\n <div\n v-if=\"$slots.default || $slots.center\"\n class=\"tree-navbar__section tree-navbar__section--center\"\n >\n <slot name=\"center\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.end\"\n class=\"tree-navbar__section tree-navbar__section--end\"\n >\n <slot name=\"end\" />\n </div>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TreeSize;\n sticky?: boolean;\n bordered?: boolean;\n elevated?: boolean;\n }>(),\n {\n as: 'header',\n size: 'md',\n sticky: false,\n bordered: true,\n elevated: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-navbar',\n `tree-navbar--${props.size}`,\n {\n 'is-sticky': props.sticky,\n 'is-bordered': props.bordered,\n 'is-elevated': props.elevated,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <div class=\"tree-navbar__inner\">\n <div\n v-if=\"$slots.start\"\n class=\"tree-navbar__section tree-navbar__section--start\"\n >\n <slot name=\"start\" />\n </div>\n\n <div\n v-if=\"$slots.default || $slots.center\"\n class=\"tree-navbar__section tree-navbar__section--center\"\n >\n <slot name=\"center\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.end\"\n class=\"tree-navbar__section tree-navbar__section--end\"\n >\n <slot name=\"end\" />\n </div>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, type Component } from 'vue';\n\nexport type TreeLinkVariant = 'default' | 'muted' | 'danger';\n\nconst props = withDefaults(\n defineProps<{\n to?: string | Record<string, unknown>;\n href?: string;\n external?: boolean;\n disabled?: boolean;\n variant?: TreeLinkVariant;\n }>(),\n {\n to: undefined,\n href: undefined,\n external: false,\n disabled: false,\n variant: 'default',\n },\n);\n\nconst instance = getCurrentInstance();\n\nconst routerLinkComponent = computed<Component | null>(() => {\n if (!props.to) return null;\n\n return (instance?.appContext.components.RouterLink as Component | undefined) ?? null;\n});\n\nconst hasRouterLink = computed(() => {\n return Boolean(routerLinkComponent.value);\n});\n\nconst tag = computed<string | Component>(() => {\n if (props.disabled) return 'span';\n if (props.to && routerLinkComponent.value) return routerLinkComponent.value;\n return 'a';\n});\n\nconst linkProps = computed(() => {\n if (props.disabled) return {};\n if (props.to && hasRouterLink.value) return { to: props.to };\n const href = props.href ?? (typeof props.to === 'string' ? props.to : undefined);\n return {\n href,\n ...(props.external ? { target: '_blank', rel: 'noopener noreferrer' } : {}),\n };\n});\n\nconst classes = computed(() => [\n 'tree-link',\n `tree-link--${props.variant}`,\n {\n 'is-disabled': props.disabled,\n },\n]);\n</script>\n\n<template>\n <component\n :is=\"tag\"\n v-bind=\"linkProps\"\n :class=\"classes\"\n :aria-disabled=\"disabled || undefined\"\n :tabindex=\"disabled ? -1 : undefined\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, type Component } from 'vue';\n\nexport type TreeLinkVariant = 'default' | 'muted' | 'danger';\n\nconst props = withDefaults(\n defineProps<{\n to?: string | Record<string, unknown>;\n href?: string;\n external?: boolean;\n disabled?: boolean;\n variant?: TreeLinkVariant;\n }>(),\n {\n to: undefined,\n href: undefined,\n external: false,\n disabled: false,\n variant: 'default',\n },\n);\n\nconst instance = getCurrentInstance();\n\nconst routerLinkComponent = computed<Component | null>(() => {\n if (!props.to) return null;\n\n return (instance?.appContext.components.RouterLink as Component | undefined) ?? null;\n});\n\nconst hasRouterLink = computed(() => {\n return Boolean(routerLinkComponent.value);\n});\n\nconst tag = computed<string | Component>(() => {\n if (props.disabled) return 'span';\n if (props.to && routerLinkComponent.value) return routerLinkComponent.value;\n return 'a';\n});\n\nconst linkProps = computed(() => {\n if (props.disabled) return {};\n if (props.to && hasRouterLink.value) return { to: props.to };\n const href = props.href ?? (typeof props.to === 'string' ? props.to : undefined);\n return {\n href,\n ...(props.external ? { target: '_blank', rel: 'noopener noreferrer' } : {}),\n };\n});\n\nconst classes = computed(() => [\n 'tree-link',\n `tree-link--${props.variant}`,\n {\n 'is-disabled': props.disabled,\n },\n]);\n</script>\n\n<template>\n <component\n :is=\"tag\"\n v-bind=\"linkProps\"\n :class=\"classes\"\n :aria-disabled=\"disabled || undefined\"\n :tabindex=\"disabled ? -1 : undefined\"\n >\n <slot />\n </component>\n</template>\n","import type { ComputedRef, InjectionKey } from 'vue';\n\nexport interface TreeSidebarContext {\n collapsed: ComputedRef<boolean>;\n}\n\nexport const treeSidebarInjectionKey: InjectionKey<TreeSidebarContext> =\n Symbol('tree-sidebar');\n","<script setup lang=\"ts\">\nimport { getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, getCurrentInstance, inject, nextTick, ref, useAttrs, watch, type Component, type ComponentPublicInstance } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeNavMenuItem {\n label: string;\n value: string;\n shortLabel?: string;\n description?: string;\n icon?: Component;\n to?: string | Record<string, unknown>;\n badge?: string | number;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TreeNavMenuItem[];\n size?: TreeSize;\n collapsed?: boolean;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n collapsed: undefined,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n select: [value: string, item: TreeNavMenuItem];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TreeNavMenuItem;\n selected: boolean;\n focused: boolean;\n collapsed: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst sidebar = inject(treeSidebarInjectionKey, null);\nconst internalValue = ref(props.defaultValue);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst instance = getCurrentInstance();\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\nconst resolvedCollapsed = computed(() => props.collapsed ?? sidebar?.collapsed.value ?? false);\n\nconst routerLinkComponent = computed<Component | null>(() => (\n (instance?.appContext.components.RouterLink as Component | undefined) ?? null\n));\n\nconst itemTag = (item: TreeNavMenuItem) => {\n if (item.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n return 'button';\n};\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 'tree-nav-menu',\n `tree-nav-menu--${props.size}`,\n {\n 'is-collapsed': resolvedCollapsed.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TreeNavMenuItem) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n emit('select', item.value, item);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n focusItem(firstIndex);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n focusItem(props.items.length - 1 - lastIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n focusItem(nextIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n focusItem(previousIndex);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index]);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <nav\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"items.length > 0\"\n class=\"tree-nav-menu__list\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"tree-nav-menu__entry\"\n >\n <component\n :is=\"itemTag(item)\"\n :ref=\"(element: Element | ComponentPublicInstance | null) => setItemRef(element, item.value)\"\n :type=\"item.to ? undefined : 'button'\"\n :to=\"item.to || undefined\"\n class=\"tree-nav-menu__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n :disabled=\"(!item.to && (disabled || item.disabled)) || undefined\"\n :aria-disabled=\"(item.to && (disabled || item.disabled)) || undefined\"\n :aria-current=\"isSelected(item.value) ? 'page' : undefined\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :title=\"resolvedCollapsed ? item.label : undefined\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n :collapsed=\"resolvedCollapsed\"\n >\n <component\n :is=\"item.icon\"\n v-if=\"item.icon\"\n class=\"tree-nav-menu__icon\"\n aria-hidden=\"true\"\n />\n <span\n v-else\n class=\"tree-nav-menu__marker\"\n aria-hidden=\"true\"\n >\n {{ (item.shortLabel ?? item.label.charAt(0)).toUpperCase() }}\n </span>\n\n <span class=\"tree-nav-menu__copy\">\n <span class=\"tree-nav-menu__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"tree-nav-menu__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.badge !== undefined && item.badge !== null\"\n class=\"tree-nav-menu__badge\"\n >\n {{ item.badge }}\n </span>\n </slot>\n </component>\n </li>\n </ul>\n\n <div\n v-else\n class=\"tree-nav-menu__empty\"\n >\n <slot name=\"empty\">\n No navigation items.\n </slot>\n </div>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, getCurrentInstance, inject, nextTick, ref, useAttrs, watch, type Component, type ComponentPublicInstance } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeNavMenuItem {\n label: string;\n value: string;\n shortLabel?: string;\n description?: string;\n icon?: Component;\n to?: string | Record<string, unknown>;\n badge?: string | number;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TreeNavMenuItem[];\n size?: TreeSize;\n collapsed?: boolean;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n collapsed: undefined,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n select: [value: string, item: TreeNavMenuItem];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TreeNavMenuItem;\n selected: boolean;\n focused: boolean;\n collapsed: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst sidebar = inject(treeSidebarInjectionKey, null);\nconst internalValue = ref(props.defaultValue);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst instance = getCurrentInstance();\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\nconst resolvedCollapsed = computed(() => props.collapsed ?? sidebar?.collapsed.value ?? false);\n\nconst routerLinkComponent = computed<Component | null>(() => (\n (instance?.appContext.components.RouterLink as Component | undefined) ?? null\n));\n\nconst itemTag = (item: TreeNavMenuItem) => {\n if (item.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n return 'button';\n};\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 'tree-nav-menu',\n `tree-nav-menu--${props.size}`,\n {\n 'is-collapsed': resolvedCollapsed.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TreeNavMenuItem) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n emit('select', item.value, item);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n focusItem(firstIndex);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n focusItem(props.items.length - 1 - lastIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n focusItem(nextIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n focusItem(previousIndex);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index]);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <nav\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"items.length > 0\"\n class=\"tree-nav-menu__list\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"tree-nav-menu__entry\"\n >\n <component\n :is=\"itemTag(item)\"\n :ref=\"(element: Element | ComponentPublicInstance | null) => setItemRef(element, item.value)\"\n :type=\"item.to ? undefined : 'button'\"\n :to=\"item.to || undefined\"\n class=\"tree-nav-menu__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n :disabled=\"(!item.to && (disabled || item.disabled)) || undefined\"\n :aria-disabled=\"(item.to && (disabled || item.disabled)) || undefined\"\n :aria-current=\"isSelected(item.value) ? 'page' : undefined\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :title=\"resolvedCollapsed ? item.label : undefined\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n :collapsed=\"resolvedCollapsed\"\n >\n <component\n :is=\"item.icon\"\n v-if=\"item.icon\"\n class=\"tree-nav-menu__icon\"\n aria-hidden=\"true\"\n />\n <span\n v-else\n class=\"tree-nav-menu__marker\"\n aria-hidden=\"true\"\n >\n {{ (item.shortLabel ?? item.label.charAt(0)).toUpperCase() }}\n </span>\n\n <span class=\"tree-nav-menu__copy\">\n <span class=\"tree-nav-menu__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"tree-nav-menu__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.badge !== undefined && item.badge !== null\"\n class=\"tree-nav-menu__badge\"\n >\n {{ item.badge }}\n </span>\n </slot>\n </component>\n </li>\n </ul>\n\n <div\n v-else\n class=\"tree-nav-menu__empty\"\n >\n <slot name=\"empty\">\n No navigation items.\n </slot>\n </div>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n invalid?: boolean;\n size?: TreeSize;\n }>(),\n {\n disabled: false,\n invalid: false,\n size: undefined,\n },\n);\n\nconst group = inject<{\n modelValue: () => string | undefined;\n name: () => string | undefined;\n disabled: () => boolean;\n invalid: () => boolean;\n size: () => TreeSize;\n onChange: (value: string) => void;\n} | null>('tree-radio-group', null);\n\nconst attrs = useAttrs();\n\nconst isChecked = computed(() => {\n return group ? group.modelValue() === props.value : false;\n});\n\nconst isDisabled = computed(() => props.disabled || (group?.disabled() ?? false));\nconst isInvalid = computed(() => props.invalid || (group?.invalid() ?? false));\nconst resolvedSize = computed(() => props.size ?? group?.size() ?? 'md');\n\nconst rootClasses = computed(() => [\n 'tree-radio',\n `tree-radio--${resolvedSize.value}`,\n {\n 'is-checked': isChecked.value,\n 'is-disabled': isDisabled.value,\n 'is-invalid': isInvalid.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n if (group) {\n group.onChange(props.value);\n }\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n v-bind=\"inputAttrs\"\n type=\"radio\"\n class=\"tree-radio__input\"\n :value=\"value\"\n :checked=\"isChecked\"\n :disabled=\"isDisabled\"\n :name=\"group?.name()\"\n :aria-checked=\"isChecked\"\n :aria-invalid=\"isInvalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"tree-radio__control\"\n aria-hidden=\"true\"\n >\n <span\n v-if=\"isChecked\"\n class=\"tree-radio__dot\"\n />\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"tree-radio__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n invalid?: boolean;\n size?: TreeSize;\n }>(),\n {\n disabled: false,\n invalid: false,\n size: undefined,\n },\n);\n\nconst group = inject<{\n modelValue: () => string | undefined;\n name: () => string | undefined;\n disabled: () => boolean;\n invalid: () => boolean;\n size: () => TreeSize;\n onChange: (value: string) => void;\n} | null>('tree-radio-group', null);\n\nconst attrs = useAttrs();\n\nconst isChecked = computed(() => {\n return group ? group.modelValue() === props.value : false;\n});\n\nconst isDisabled = computed(() => props.disabled || (group?.disabled() ?? false));\nconst isInvalid = computed(() => props.invalid || (group?.invalid() ?? false));\nconst resolvedSize = computed(() => props.size ?? group?.size() ?? 'md');\n\nconst rootClasses = computed(() => [\n 'tree-radio',\n `tree-radio--${resolvedSize.value}`,\n {\n 'is-checked': isChecked.value,\n 'is-disabled': isDisabled.value,\n 'is-invalid': isInvalid.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n if (group) {\n group.onChange(props.value);\n }\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n v-bind=\"inputAttrs\"\n type=\"radio\"\n class=\"tree-radio__input\"\n :value=\"value\"\n :checked=\"isChecked\"\n :disabled=\"isDisabled\"\n :name=\"group?.name()\"\n :aria-checked=\"isChecked\"\n :aria-invalid=\"isInvalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"tree-radio__control\"\n aria-hidden=\"true\"\n >\n <span\n v-if=\"isChecked\"\n class=\"tree-radio__dot\"\n />\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"tree-radio__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, provide, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n name?: string;\n disabled?: boolean;\n invalid?: boolean;\n size?: TreeSize;\n }>(),\n {\n modelValue: undefined,\n name: undefined,\n disabled: false,\n invalid: false,\n size: 'md',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nprovide('tree-radio-group', {\n modelValue: () => props.modelValue,\n name: () => props.name,\n disabled: () => props.disabled,\n invalid: () => props.invalid,\n size: () => props.size,\n onChange: (value: string) => {\n emit('update:modelValue', value);\n },\n});\n\nconst rootClasses = computed(() => [\n 'tree-radio-group',\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst groupAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <div\n v-bind=\"groupAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n role=\"radiogroup\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, provide, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n name?: string;\n disabled?: boolean;\n invalid?: boolean;\n size?: TreeSize;\n }>(),\n {\n modelValue: undefined,\n name: undefined,\n disabled: false,\n invalid: false,\n size: 'md',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nprovide('tree-radio-group', {\n modelValue: () => props.modelValue,\n name: () => props.name,\n disabled: () => props.disabled,\n invalid: () => props.invalid,\n size: () => props.size,\n onChange: (value: string) => {\n emit('update:modelValue', value);\n },\n});\n\nconst rootClasses = computed(() => [\n 'tree-radio-group',\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst groupAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <div\n v-bind=\"groupAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n role=\"radiogroup\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeSelectOption {\n label: string;\n value: string | number;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n options?: TreeSelectOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('tree-select');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst optionRefs = ref<Map<string | number, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-select',\n `tree-select--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst selectedLabel = computed(() => {\n const opt = props.options.find((o) => o.value === props.modelValue);\n return opt?.label ?? '';\n});\n\nconst enabledOptions = computed(() =>\n props.options.filter((o) => !o.disabled),\n);\n\nconst openDropdown = () => {\n if (props.disabled) return;\n const selectedIdx = props.options.findIndex((o) => o.value === props.modelValue);\n focusedIndex.value = selectedIdx >= 0 ? selectedIdx : 0;\n setValue(true);\n nextTick(() => focusOption(focusedIndex.value));\n};\n\nconst closeDropdown = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst toggleDropdown = () => {\n if (isOpen.value) {\n closeDropdown();\n } else {\n openDropdown();\n }\n};\n\nconst selectOption = (opt: TreeSelectOption) => {\n if (opt.disabled) return;\n emit('update:modelValue', opt.value);\n closeDropdown(true);\n};\n\nconst focusOption = (index: number) => {\n const opt = props.options[index];\n if (!opt) return;\n const el = optionRefs.value.get(opt.value);\n el?.focus();\n};\n\nconst setOptionRef = (el: Element | null, value: string | number) => {\n if (el instanceof HTMLElement) {\n optionRefs.value.set(value, el);\n } else {\n optionRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.options.length) {\n if (!props.options[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusOption(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeDropdown();\n return;\n }\n\n if (isActivationKey(event) || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n openDropdown();\n }\n};\n\nconst onOptionKeydown = (event: KeyboardEvent, opt: TreeSelectOption, _index: number) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeDropdown(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectOption(opt);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledOptions.value.length > 0\n ? props.options.indexOf(enabledOptions.value[0])\n : 0;\n focusOption(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledOptions.value.length > 0\n ? props.options.indexOf(enabledOptions.value[enabledOptions.value.length - 1])\n : props.options.length - 1;\n focusOption(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeDropdown();\n};\n\nconst hasSelection = computed(() =>\n props.modelValue !== '' && props.modelValue !== null && props.modelValue !== undefined,\n);\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"tree-select__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n aria-haspopup=\"listbox\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n @click=\"toggleDropdown\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-select__slot tree-select__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <span\n class=\"tree-select__value\"\n :data-placeholder=\"!hasSelection ? true : undefined\"\n >\n {{ selectedLabel || placeholder }}\n </span>\n <TreeSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <svg\n v-else\n class=\"tree-select__chevron\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </button>\n <transition name=\"tree-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"listboxId\"\n role=\"listbox\"\n class=\"tree-select__listbox\"\n :aria-label=\"typeof triggerAttrs['aria-label'] === 'string' ? triggerAttrs['aria-label'] : undefined\"\n >\n <li\n v-for=\"(opt, index) in options\"\n :key=\"opt.value\"\n :ref=\"(el) => setOptionRef(el as Element | null, opt.value)\"\n role=\"option\"\n class=\"tree-select__option\"\n :class=\"{\n 'is-selected': opt.value === modelValue,\n 'is-disabled': opt.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-selected=\"opt.value === modelValue\"\n :aria-disabled=\"opt.disabled || undefined\"\n :tabindex=\"opt.disabled ? -1 : 0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt, index)\"\n >\n {{ opt.label }}\n <svg\n v-if=\"opt.value === modelValue\"\n class=\"tree-select__check\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n </li>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeSelectOption {\n label: string;\n value: string | number;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n options?: TreeSelectOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('tree-select');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst optionRefs = ref<Map<string | number, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-select',\n `tree-select--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst selectedLabel = computed(() => {\n const opt = props.options.find((o) => o.value === props.modelValue);\n return opt?.label ?? '';\n});\n\nconst enabledOptions = computed(() =>\n props.options.filter((o) => !o.disabled),\n);\n\nconst openDropdown = () => {\n if (props.disabled) return;\n const selectedIdx = props.options.findIndex((o) => o.value === props.modelValue);\n focusedIndex.value = selectedIdx >= 0 ? selectedIdx : 0;\n setValue(true);\n nextTick(() => focusOption(focusedIndex.value));\n};\n\nconst closeDropdown = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst toggleDropdown = () => {\n if (isOpen.value) {\n closeDropdown();\n } else {\n openDropdown();\n }\n};\n\nconst selectOption = (opt: TreeSelectOption) => {\n if (opt.disabled) return;\n emit('update:modelValue', opt.value);\n closeDropdown(true);\n};\n\nconst focusOption = (index: number) => {\n const opt = props.options[index];\n if (!opt) return;\n const el = optionRefs.value.get(opt.value);\n el?.focus();\n};\n\nconst setOptionRef = (el: Element | null, value: string | number) => {\n if (el instanceof HTMLElement) {\n optionRefs.value.set(value, el);\n } else {\n optionRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.options.length) {\n if (!props.options[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusOption(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeDropdown();\n return;\n }\n\n if (isActivationKey(event) || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n openDropdown();\n }\n};\n\nconst onOptionKeydown = (event: KeyboardEvent, opt: TreeSelectOption, _index: number) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeDropdown(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectOption(opt);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledOptions.value.length > 0\n ? props.options.indexOf(enabledOptions.value[0])\n : 0;\n focusOption(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledOptions.value.length > 0\n ? props.options.indexOf(enabledOptions.value[enabledOptions.value.length - 1])\n : props.options.length - 1;\n focusOption(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeDropdown();\n};\n\nconst hasSelection = computed(() =>\n props.modelValue !== '' && props.modelValue !== null && props.modelValue !== undefined,\n);\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"tree-select__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n aria-haspopup=\"listbox\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n @click=\"toggleDropdown\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-select__slot tree-select__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <span\n class=\"tree-select__value\"\n :data-placeholder=\"!hasSelection ? true : undefined\"\n >\n {{ selectedLabel || placeholder }}\n </span>\n <TreeSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <svg\n v-else\n class=\"tree-select__chevron\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </button>\n <transition name=\"tree-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"listboxId\"\n role=\"listbox\"\n class=\"tree-select__listbox\"\n :aria-label=\"typeof triggerAttrs['aria-label'] === 'string' ? triggerAttrs['aria-label'] : undefined\"\n >\n <li\n v-for=\"(opt, index) in options\"\n :key=\"opt.value\"\n :ref=\"(el) => setOptionRef(el as Element | null, opt.value)\"\n role=\"option\"\n class=\"tree-select__option\"\n :class=\"{\n 'is-selected': opt.value === modelValue,\n 'is-disabled': opt.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-selected=\"opt.value === modelValue\"\n :aria-disabled=\"opt.disabled || undefined\"\n :tabindex=\"opt.disabled ? -1 : 0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt, index)\"\n >\n {{ opt.label }}\n <svg\n v-if=\"opt.value === modelValue\"\n class=\"tree-select__check\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n </li>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { computed, provide, toRef, useAttrs } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeSidebarSides = ['left', 'right'] as const;\n\nexport type TreeSidebarSide = (typeof _treeSidebarSides)[number];\n\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n collapsed?: boolean;\n defaultCollapsed?: boolean;\n collapsible?: boolean;\n size?: TreeSize;\n side?: TreeSidebarSide;\n sticky?: boolean;\n bordered?: boolean;\n width?: string;\n collapsedWidth?: string;\n collapseLabel?: string;\n expandLabel?: string;\n }>(),\n {\n as: 'aside',\n collapsed: undefined,\n defaultCollapsed: false,\n collapsible: true,\n size: 'md',\n side: 'left',\n sticky: false,\n bordered: true,\n width: '17.5rem',\n collapsedWidth: '4.75rem',\n collapseLabel: 'Collapse sidebar',\n expandLabel: 'Expand sidebar',\n },\n);\n\nconst emit = defineEmits<{\n 'update:collapsed': [value: boolean];\n 'collapse-change': [value: boolean];\n}>();\n\ndefineSlots<{\n header?: (props: { collapsed: boolean }) => unknown;\n default?: (props: { collapsed: boolean }) => unknown;\n footer?: (props: { collapsed: boolean }) => unknown;\n toggle?: (props: { collapsed: boolean }) => unknown;\n}>();\n\nconst attrs = useAttrs();\n\nconst { value: isCollapsed, setValue } = useControllableOpen(\n toRef(props, 'collapsed'),\n props.defaultCollapsed,\n (value) => {\n emit('update:collapsed', value);\n emit('collapse-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-sidebar',\n `tree-sidebar--${props.size}`,\n `tree-sidebar--${props.side}`,\n {\n 'is-collapsed': isCollapsed.value,\n 'is-sticky': props.sticky,\n 'is-bordered': props.bordered,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n '--tree-sidebar-width': props.width,\n '--tree-sidebar-collapsed-width': props.collapsedWidth,\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst toggleCollapsed = () => {\n if (!props.collapsible) {\n return;\n }\n\n setValue(!isCollapsed.value);\n};\n\nconst ToggleIcon = computed(() => {\n if (props.side === 'right') {\n return isCollapsed.value ? ChevronLeftIcon : ChevronRightIcon;\n }\n\n return isCollapsed.value ? ChevronRightIcon : ChevronLeftIcon;\n});\n\nconst toggleLabel = computed(() =>\n isCollapsed.value ? props.expandLabel : props.collapseLabel,\n);\n\nprovide(treeSidebarInjectionKey, {\n collapsed: computed(() => isCollapsed.value),\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isCollapsed ? 'collapsed' : 'expanded'\"\n >\n <div\n v-if=\"$slots.header\"\n class=\"tree-sidebar__header\"\n >\n <slot\n name=\"header\"\n :collapsed=\"isCollapsed\"\n />\n </div>\n\n <div class=\"tree-sidebar__body\">\n <slot :collapsed=\"isCollapsed\" />\n </div>\n\n <div\n v-if=\"$slots.footer || collapsible\"\n class=\"tree-sidebar__footer\"\n >\n <slot\n v-if=\"$slots.footer\"\n name=\"footer\"\n :collapsed=\"isCollapsed\"\n />\n\n <button\n v-if=\"collapsible\"\n type=\"button\"\n class=\"tree-sidebar__toggle\"\n :aria-label=\"toggleLabel\"\n :aria-expanded=\"!isCollapsed\"\n @click=\"toggleCollapsed\"\n >\n <slot\n name=\"toggle\"\n :collapsed=\"isCollapsed\"\n >\n <component\n :is=\"ToggleIcon\"\n :size=\"16\"\n />\n <span v-if=\"!isCollapsed\">{{ toggleLabel }}</span>\n </slot>\n </button>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { computed, provide, toRef, useAttrs } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeSidebarSides = ['left', 'right'] as const;\n\nexport type TreeSidebarSide = (typeof _treeSidebarSides)[number];\n\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n collapsed?: boolean;\n defaultCollapsed?: boolean;\n collapsible?: boolean;\n size?: TreeSize;\n side?: TreeSidebarSide;\n sticky?: boolean;\n bordered?: boolean;\n width?: string;\n collapsedWidth?: string;\n collapseLabel?: string;\n expandLabel?: string;\n }>(),\n {\n as: 'aside',\n collapsed: undefined,\n defaultCollapsed: false,\n collapsible: true,\n size: 'md',\n side: 'left',\n sticky: false,\n bordered: true,\n width: '17.5rem',\n collapsedWidth: '4.75rem',\n collapseLabel: 'Collapse sidebar',\n expandLabel: 'Expand sidebar',\n },\n);\n\nconst emit = defineEmits<{\n 'update:collapsed': [value: boolean];\n 'collapse-change': [value: boolean];\n}>();\n\ndefineSlots<{\n header?: (props: { collapsed: boolean }) => unknown;\n default?: (props: { collapsed: boolean }) => unknown;\n footer?: (props: { collapsed: boolean }) => unknown;\n toggle?: (props: { collapsed: boolean }) => unknown;\n}>();\n\nconst attrs = useAttrs();\n\nconst { value: isCollapsed, setValue } = useControllableOpen(\n toRef(props, 'collapsed'),\n props.defaultCollapsed,\n (value) => {\n emit('update:collapsed', value);\n emit('collapse-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-sidebar',\n `tree-sidebar--${props.size}`,\n `tree-sidebar--${props.side}`,\n {\n 'is-collapsed': isCollapsed.value,\n 'is-sticky': props.sticky,\n 'is-bordered': props.bordered,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n '--tree-sidebar-width': props.width,\n '--tree-sidebar-collapsed-width': props.collapsedWidth,\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst toggleCollapsed = () => {\n if (!props.collapsible) {\n return;\n }\n\n setValue(!isCollapsed.value);\n};\n\nconst ToggleIcon = computed(() => {\n if (props.side === 'right') {\n return isCollapsed.value ? ChevronLeftIcon : ChevronRightIcon;\n }\n\n return isCollapsed.value ? ChevronRightIcon : ChevronLeftIcon;\n});\n\nconst toggleLabel = computed(() =>\n isCollapsed.value ? props.expandLabel : props.collapseLabel,\n);\n\nprovide(treeSidebarInjectionKey, {\n collapsed: computed(() => isCollapsed.value),\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isCollapsed ? 'collapsed' : 'expanded'\"\n >\n <div\n v-if=\"$slots.header\"\n class=\"tree-sidebar__header\"\n >\n <slot\n name=\"header\"\n :collapsed=\"isCollapsed\"\n />\n </div>\n\n <div class=\"tree-sidebar__body\">\n <slot :collapsed=\"isCollapsed\" />\n </div>\n\n <div\n v-if=\"$slots.footer || collapsible\"\n class=\"tree-sidebar__footer\"\n >\n <slot\n v-if=\"$slots.footer\"\n name=\"footer\"\n :collapsed=\"isCollapsed\"\n />\n\n <button\n v-if=\"collapsible\"\n type=\"button\"\n class=\"tree-sidebar__toggle\"\n :aria-label=\"toggleLabel\"\n :aria-expanded=\"!isCollapsed\"\n @click=\"toggleCollapsed\"\n >\n <slot\n name=\"toggle\"\n :collapsed=\"isCollapsed\"\n >\n <component\n :is=\"ToggleIcon\"\n :size=\"16\"\n />\n <span v-if=\"!isCollapsed\">{{ toggleLabel }}</span>\n </slot>\n </button>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-input',\n `tree-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-input__slot tree-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"tree-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TreeSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"tree-input__slot tree-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-input',\n `tree-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"tree-input__slot tree-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"tree-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TreeSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"tree-input__slot tree-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { clamp } from '@treeui/utils';\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: number | null;\n min?: number;\n max?: number;\n step?: number;\n size?: TreeSize;\n disabled?: boolean;\n invalid?: boolean;\n placeholder?: string;\n controls?: boolean;\n }>(),\n {\n modelValue: null,\n min: undefined,\n max: undefined,\n step: 1,\n size: 'md',\n disabled: false,\n invalid: false,\n placeholder: '',\n controls: true,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number | null];\n}>();\n\nconst attrs = useAttrs();\nconst displayValue = ref(\n props.modelValue === null || props.modelValue === undefined ? '' : `${props.modelValue}`,\n);\n\nconst precision = computed(() => {\n const normalizedStep = `${props.step}`;\n const fractionalPart = normalizedStep.split('.')[1];\n return fractionalPart ? fractionalPart.length : 0;\n});\n\nconst rootClasses = computed(() => [\n 'tree-number-input',\n `tree-number-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'has-controls': props.controls,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst formatValue = (value: number | null | undefined) =>\n value === null || value === undefined ? '' : `${value}`;\n\nconst normalizeValue = (value: number) => {\n const clamped = clamp(\n value,\n props.min ?? Number.NEGATIVE_INFINITY,\n props.max ?? Number.POSITIVE_INFINITY,\n );\n\n return Number(clamped.toFixed(precision.value));\n};\n\nconst parseValue = (value: string) => {\n const normalized = value.trim().replace(',', '.');\n\n if (!normalized) {\n return null;\n }\n\n const parsed = Number(normalized);\n return Number.isNaN(parsed) ? null : parsed;\n};\n\nconst currentNumericValue = computed(() => {\n const parsed = parseValue(displayValue.value);\n return parsed ?? props.modelValue ?? null;\n});\n\nconst canDecrement = computed(() => {\n if (props.disabled) {\n return false;\n }\n\n if (props.min === undefined || currentNumericValue.value === null) {\n return true;\n }\n\n return normalizeValue(currentNumericValue.value) > props.min;\n});\n\nconst canIncrement = computed(() => {\n if (props.disabled) {\n return false;\n }\n\n if (props.max === undefined || currentNumericValue.value === null) {\n return true;\n }\n\n return normalizeValue(currentNumericValue.value) < props.max;\n});\n\nconst commitValue = (value: number | null) => {\n if (value === null) {\n displayValue.value = '';\n emit('update:modelValue', null);\n return;\n }\n\n const normalized = normalizeValue(value);\n displayValue.value = `${normalized}`;\n emit('update:modelValue', normalized);\n};\n\nconst stepValue = (direction: 1 | -1) => {\n if (props.disabled) {\n return;\n }\n\n let baseValue = currentNumericValue.value ?? 0;\n\n if (currentNumericValue.value === null) {\n if (direction === 1 && props.min !== undefined) {\n baseValue = props.min - props.step;\n }\n\n if (direction === -1 && props.max !== undefined) {\n baseValue = props.max + props.step;\n }\n }\n\n commitValue(baseValue + direction * props.step);\n};\n\nconst onInput = (event: Event) => {\n const nextValue = (event.target as HTMLInputElement).value;\n displayValue.value = nextValue;\n\n if (!nextValue.trim()) {\n emit('update:modelValue', null);\n return;\n }\n\n const parsedValue = parseValue(nextValue);\n\n if (parsedValue === null) {\n return;\n }\n\n emit('update:modelValue', normalizeValue(parsedValue));\n};\n\nconst onBlur = () => {\n if (!displayValue.value.trim()) {\n displayValue.value = '';\n return;\n }\n\n const parsedValue = parseValue(displayValue.value);\n\n if (parsedValue === null) {\n displayValue.value = formatValue(props.modelValue);\n return;\n }\n\n displayValue.value = `${normalizeValue(parsedValue)}`;\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n stepValue(1);\n return;\n }\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n stepValue(-1);\n return;\n }\n\n if (event.key === 'Home' && props.min !== undefined) {\n event.preventDefault();\n commitValue(props.min);\n return;\n }\n\n if (event.key === 'End' && props.max !== undefined) {\n event.preventDefault();\n commitValue(props.max);\n }\n};\n\nwatch(\n () => props.modelValue,\n (value) => {\n const nextDisplayValue = formatValue(value);\n\n if (nextDisplayValue !== displayValue.value) {\n displayValue.value = nextDisplayValue;\n }\n },\n);\n</script>\n\n<template>\n <div\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <button\n v-if=\"controls\"\n type=\"button\"\n class=\"tree-number-input__stepper tree-number-input__stepper--decrement\"\n :disabled=\"!canDecrement\"\n aria-label=\"Decrease value\"\n @click=\"stepValue(-1)\"\n >\n <span aria-hidden=\"true\">-</span>\n </button>\n\n <input\n v-bind=\"inputAttrs\"\n :value=\"displayValue\"\n type=\"text\"\n inputmode=\"decimal\"\n class=\"tree-number-input__field\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n @blur=\"onBlur\"\n @keydown=\"onKeydown\"\n >\n\n <button\n v-if=\"controls\"\n type=\"button\"\n class=\"tree-number-input__stepper tree-number-input__stepper--increment\"\n :disabled=\"!canIncrement\"\n aria-label=\"Increase value\"\n @click=\"stepValue(1)\"\n >\n <span aria-hidden=\"true\">+</span>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { clamp } from '@treeui/utils';\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: number | null;\n min?: number;\n max?: number;\n step?: number;\n size?: TreeSize;\n disabled?: boolean;\n invalid?: boolean;\n placeholder?: string;\n controls?: boolean;\n }>(),\n {\n modelValue: null,\n min: undefined,\n max: undefined,\n step: 1,\n size: 'md',\n disabled: false,\n invalid: false,\n placeholder: '',\n controls: true,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number | null];\n}>();\n\nconst attrs = useAttrs();\nconst displayValue = ref(\n props.modelValue === null || props.modelValue === undefined ? '' : `${props.modelValue}`,\n);\n\nconst precision = computed(() => {\n const normalizedStep = `${props.step}`;\n const fractionalPart = normalizedStep.split('.')[1];\n return fractionalPart ? fractionalPart.length : 0;\n});\n\nconst rootClasses = computed(() => [\n 'tree-number-input',\n `tree-number-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'has-controls': props.controls,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst formatValue = (value: number | null | undefined) =>\n value === null || value === undefined ? '' : `${value}`;\n\nconst normalizeValue = (value: number) => {\n const clamped = clamp(\n value,\n props.min ?? Number.NEGATIVE_INFINITY,\n props.max ?? Number.POSITIVE_INFINITY,\n );\n\n return Number(clamped.toFixed(precision.value));\n};\n\nconst parseValue = (value: string) => {\n const normalized = value.trim().replace(',', '.');\n\n if (!normalized) {\n return null;\n }\n\n const parsed = Number(normalized);\n return Number.isNaN(parsed) ? null : parsed;\n};\n\nconst currentNumericValue = computed(() => {\n const parsed = parseValue(displayValue.value);\n return parsed ?? props.modelValue ?? null;\n});\n\nconst canDecrement = computed(() => {\n if (props.disabled) {\n return false;\n }\n\n if (props.min === undefined || currentNumericValue.value === null) {\n return true;\n }\n\n return normalizeValue(currentNumericValue.value) > props.min;\n});\n\nconst canIncrement = computed(() => {\n if (props.disabled) {\n return false;\n }\n\n if (props.max === undefined || currentNumericValue.value === null) {\n return true;\n }\n\n return normalizeValue(currentNumericValue.value) < props.max;\n});\n\nconst commitValue = (value: number | null) => {\n if (value === null) {\n displayValue.value = '';\n emit('update:modelValue', null);\n return;\n }\n\n const normalized = normalizeValue(value);\n displayValue.value = `${normalized}`;\n emit('update:modelValue', normalized);\n};\n\nconst stepValue = (direction: 1 | -1) => {\n if (props.disabled) {\n return;\n }\n\n let baseValue = currentNumericValue.value ?? 0;\n\n if (currentNumericValue.value === null) {\n if (direction === 1 && props.min !== undefined) {\n baseValue = props.min - props.step;\n }\n\n if (direction === -1 && props.max !== undefined) {\n baseValue = props.max + props.step;\n }\n }\n\n commitValue(baseValue + direction * props.step);\n};\n\nconst onInput = (event: Event) => {\n const nextValue = (event.target as HTMLInputElement).value;\n displayValue.value = nextValue;\n\n if (!nextValue.trim()) {\n emit('update:modelValue', null);\n return;\n }\n\n const parsedValue = parseValue(nextValue);\n\n if (parsedValue === null) {\n return;\n }\n\n emit('update:modelValue', normalizeValue(parsedValue));\n};\n\nconst onBlur = () => {\n if (!displayValue.value.trim()) {\n displayValue.value = '';\n return;\n }\n\n const parsedValue = parseValue(displayValue.value);\n\n if (parsedValue === null) {\n displayValue.value = formatValue(props.modelValue);\n return;\n }\n\n displayValue.value = `${normalizeValue(parsedValue)}`;\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n stepValue(1);\n return;\n }\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n stepValue(-1);\n return;\n }\n\n if (event.key === 'Home' && props.min !== undefined) {\n event.preventDefault();\n commitValue(props.min);\n return;\n }\n\n if (event.key === 'End' && props.max !== undefined) {\n event.preventDefault();\n commitValue(props.max);\n }\n};\n\nwatch(\n () => props.modelValue,\n (value) => {\n const nextDisplayValue = formatValue(value);\n\n if (nextDisplayValue !== displayValue.value) {\n displayValue.value = nextDisplayValue;\n }\n },\n);\n</script>\n\n<template>\n <div\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <button\n v-if=\"controls\"\n type=\"button\"\n class=\"tree-number-input__stepper tree-number-input__stepper--decrement\"\n :disabled=\"!canDecrement\"\n aria-label=\"Decrease value\"\n @click=\"stepValue(-1)\"\n >\n <span aria-hidden=\"true\">-</span>\n </button>\n\n <input\n v-bind=\"inputAttrs\"\n :value=\"displayValue\"\n type=\"text\"\n inputmode=\"decimal\"\n class=\"tree-number-input__field\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n @blur=\"onBlur\"\n @keydown=\"onKeydown\"\n >\n\n <button\n v-if=\"controls\"\n type=\"button\"\n class=\"tree-number-input__stepper tree-number-input__stepper--increment\"\n :disabled=\"!canIncrement\"\n aria-label=\"Increase value\"\n @click=\"stepValue(1)\"\n >\n <span aria-hidden=\"true\">+</span>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, ref, useAttrs, watch, type ComponentPublicInstance } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeSelectableListItem {\n label: string;\n value: string;\n description?: string;\n meta?: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TreeSelectableListItem[];\n size?: TreeSize;\n disabled?: boolean;\n emptyText?: string;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n disabled: false,\n emptyText: 'No items available.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TreeSelectableListItem;\n selected: boolean;\n focused: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('tree-selectable-list');\nconst itemRefs = ref<Map<string, HTMLButtonElement>>(new Map());\nconst internalValue = ref(props.defaultValue);\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 'tree-selectable-list',\n `tree-selectable-list--${props.size}`,\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLButtonElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLButtonElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLButtonElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TreeSelectableListItem, focus = false) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n\n if (focus) {\n const index = props.items.findIndex((candidate) => candidate.value === item.value);\n\n if (index >= 0) {\n focusItem(index);\n }\n }\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n selectItem(props.items[firstIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n const resolvedIndex = props.items.length - 1 - lastIndex;\n selectItem(props.items[resolvedIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n selectItem(props.items[nextIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n selectItem(props.items[previousIndex], true);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index], true);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <div\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n role=\"listbox\"\n :aria-disabled=\"disabled || undefined\"\n >\n <template v-if=\"items.length > 0\">\n <button\n v-for=\"(item, index) in items\"\n :id=\"`${baseId}-${item.value}`\"\n :ref=\"(element) => setItemRef(element, item.value)\"\n :key=\"item.value\"\n type=\"button\"\n class=\"tree-selectable-list__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n role=\"option\"\n :aria-selected=\"isSelected(item.value)\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :disabled=\"disabled || item.disabled\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n >\n <span\n class=\"tree-selectable-list__indicator\"\n aria-hidden=\"true\"\n />\n\n <span class=\"tree-selectable-list__copy\">\n <span class=\"tree-selectable-list__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"tree-selectable-list__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.meta\"\n class=\"tree-selectable-list__meta\"\n >\n {{ item.meta }}\n </span>\n </slot>\n </button>\n </template>\n\n <div\n v-else\n class=\"tree-selectable-list__empty\"\n >\n <slot name=\"empty\">\n {{ emptyText }}\n </slot>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, ref, useAttrs, watch, type ComponentPublicInstance } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeSelectableListItem {\n label: string;\n value: string;\n description?: string;\n meta?: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TreeSelectableListItem[];\n size?: TreeSize;\n disabled?: boolean;\n emptyText?: string;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n disabled: false,\n emptyText: 'No items available.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TreeSelectableListItem;\n selected: boolean;\n focused: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('tree-selectable-list');\nconst itemRefs = ref<Map<string, HTMLButtonElement>>(new Map());\nconst internalValue = ref(props.defaultValue);\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 'tree-selectable-list',\n `tree-selectable-list--${props.size}`,\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLButtonElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLButtonElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLButtonElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TreeSelectableListItem, focus = false) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n\n if (focus) {\n const index = props.items.findIndex((candidate) => candidate.value === item.value);\n\n if (index >= 0) {\n focusItem(index);\n }\n }\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n selectItem(props.items[firstIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n const resolvedIndex = props.items.length - 1 - lastIndex;\n selectItem(props.items[resolvedIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n selectItem(props.items[nextIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n selectItem(props.items[previousIndex], true);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index], true);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <div\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n role=\"listbox\"\n :aria-disabled=\"disabled || undefined\"\n >\n <template v-if=\"items.length > 0\">\n <button\n v-for=\"(item, index) in items\"\n :id=\"`${baseId}-${item.value}`\"\n :ref=\"(element) => setItemRef(element, item.value)\"\n :key=\"item.value\"\n type=\"button\"\n class=\"tree-selectable-list__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n role=\"option\"\n :aria-selected=\"isSelected(item.value)\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :disabled=\"disabled || item.disabled\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n >\n <span\n class=\"tree-selectable-list__indicator\"\n aria-hidden=\"true\"\n />\n\n <span class=\"tree-selectable-list__copy\">\n <span class=\"tree-selectable-list__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"tree-selectable-list__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.meta\"\n class=\"tree-selectable-list__meta\"\n >\n {{ item.meta }}\n </span>\n </slot>\n </button>\n </template>\n\n <div\n v-else\n class=\"tree-selectable-list__empty\"\n >\n <slot name=\"empty\">\n {{ emptyText }}\n </slot>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeStackDirections = ['vertical', 'horizontal'] as const;\n\nexport type TreeStackDirection = (typeof _treeStackDirections)[number];\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n direction?: TreeStackDirection;\n gap?: string;\n align?: string;\n justify?: string;\n wrap?: boolean;\n reverse?: boolean;\n }>(),\n {\n as: 'div',\n direction: 'vertical',\n gap: 'var(--tree-space-4)',\n align: 'stretch',\n justify: 'flex-start',\n wrap: false,\n reverse: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-stack',\n `tree-stack--${props.direction}`,\n {\n 'is-wrapping': props.wrap,\n 'is-reversed': props.reverse,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n gap: props.gap,\n alignItems: props.align,\n justifyContent: props.justify,\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeStackDirections = ['vertical', 'horizontal'] as const;\n\nexport type TreeStackDirection = (typeof _treeStackDirections)[number];\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n direction?: TreeStackDirection;\n gap?: string;\n align?: string;\n justify?: string;\n wrap?: boolean;\n reverse?: boolean;\n }>(),\n {\n as: 'div',\n direction: 'vertical',\n gap: 'var(--tree-space-4)',\n align: 'stretch',\n justify: 'flex-start',\n wrap: false,\n reverse: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-stack',\n `tree-stack--${props.direction}`,\n {\n 'is-wrapping': props.wrap,\n 'is-reversed': props.reverse,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n gap: props.gap,\n alignItems: props.align,\n justifyContent: props.justify,\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","import type { ComputedRef, InjectionKey, Ref } from 'vue';\n\nexport interface TreeTreeViewNode {\n id: string;\n label: string;\n description?: string;\n meta?: string;\n disabled?: boolean;\n children?: TreeTreeViewNode[];\n}\n\nexport const treeTreeViewSelectionModes = ['single', 'multiple'] as const;\n\nexport type TreeTreeViewSelectionMode = (typeof treeTreeViewSelectionModes)[number];\n\nexport interface TreeTreeViewRecord {\n node: TreeTreeViewNode;\n level: number;\n parentId?: string;\n}\n\nexport interface TreeTreeViewContext {\n baseId: string;\n disabled: ComputedRef<boolean>;\n selectionMode: ComputedRef<TreeTreeViewSelectionMode>;\n focusedId: Ref<string>;\n isExpanded: (id: string) => boolean;\n toggleExpanded: (id: string) => void;\n isSelected: (id: string) => boolean;\n toggleSelected: (id: string) => void;\n setFocusedId: (id: string, shouldFocus?: boolean) => void;\n onItemKeydown: (event: KeyboardEvent, id: string) => void;\n registerItem: (id: string, element: HTMLElement) => void;\n unregisterItem: (id: string) => void;\n}\n\nexport const treeTreeViewInjectionKey: InjectionKey<TreeTreeViewContext> =\n Symbol('tree-tree-view');\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { computed, inject, type ComponentPublicInstance } from 'vue';\nimport { treeTreeViewInjectionKey, type TreeTreeViewNode } from './tree-view';\n\ndefineOptions({\n name: 'TreeTreeViewItem',\n});\n\nconst ChevronRightIcon = getTreeIcon('chevron-right');\nconst CheckIcon = getTreeIcon('check');\n\nconst props = defineProps<{\n node: TreeTreeViewNode;\n level: number;\n}>();\n\nconst ctx = inject(treeTreeViewInjectionKey);\n\nif (!ctx) {\n throw new Error('[TreeUI] TTreeView items must be rendered inside a TTreeView.');\n}\n\nconst hasChildren = computed(() => Boolean(props.node.children?.length));\nconst isExpanded = computed(() => (hasChildren.value ? ctx.isExpanded(props.node.id) : false));\nconst isSelected = computed(() => ctx.isSelected(props.node.id));\nconst isDisabled = computed(() => ctx.disabled.value || props.node.disabled);\nconst isFocused = computed(() => ctx.focusedId.value === props.node.id);\nconst itemId = computed(() => `${ctx.baseId}-${props.node.id}`);\n\nconst rowClasses = computed(() => ({\n 'is-expanded': isExpanded.value,\n 'is-selected': isSelected.value,\n 'is-disabled': isDisabled.value,\n 'is-focused': isFocused.value,\n}));\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLElement) {\n ctx.registerItem(props.node.id, resolvedElement);\n } else {\n ctx.unregisterItem(props.node.id);\n }\n};\n\nconst onRowClick = () => {\n ctx.setFocusedId(props.node.id);\n ctx.toggleSelected(props.node.id);\n};\n\nconst onToggleClick = () => {\n if (isDisabled.value || !hasChildren.value) {\n return;\n }\n\n ctx.toggleExpanded(props.node.id);\n ctx.setFocusedId(props.node.id);\n};\n</script>\n\n<template>\n <li\n class=\"tree-tree-view__node\"\n role=\"none\"\n >\n <div\n :id=\"itemId\"\n :ref=\"setItemRef\"\n class=\"tree-tree-view__row\"\n :class=\"rowClasses\"\n :style=\"{ '--tree-tree-view-level': `${level}` }\"\n role=\"treeitem\"\n :aria-level=\"level\"\n :aria-expanded=\"hasChildren ? isExpanded : undefined\"\n :aria-selected=\"isSelected\"\n :aria-disabled=\"isDisabled || undefined\"\n :tabindex=\"isDisabled ? -1 : isFocused ? 0 : -1\"\n @click=\"onRowClick\"\n @keydown=\"ctx.onItemKeydown($event, node.id)\"\n @focus=\"ctx.setFocusedId(node.id)\"\n >\n <button\n v-if=\"hasChildren\"\n type=\"button\"\n class=\"tree-tree-view__toggle\"\n :class=\"{ 'is-expanded': isExpanded }\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :aria-label=\"isExpanded ? 'Collapse node' : 'Expand node'\"\n @click.stop=\"onToggleClick\"\n >\n <ChevronRightIcon :size=\"16\" />\n </button>\n\n <span\n v-else\n class=\"tree-tree-view__spacer\"\n aria-hidden=\"true\"\n />\n\n <span\n class=\"tree-tree-view__marker\"\n :class=\"{\n 'is-selected': isSelected,\n 'is-multiple': ctx.selectionMode.value === 'multiple',\n }\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"ctx.selectionMode.value === 'multiple' && isSelected\"\n :size=\"14\"\n />\n </span>\n\n <span class=\"tree-tree-view__copy\">\n <span class=\"tree-tree-view__label\">{{ node.label }}</span>\n <span\n v-if=\"node.description\"\n class=\"tree-tree-view__description\"\n >\n {{ node.description }}\n </span>\n </span>\n\n <span\n v-if=\"node.meta\"\n class=\"tree-tree-view__meta\"\n >\n {{ node.meta }}\n </span>\n </div>\n\n <ul\n v-if=\"hasChildren && isExpanded\"\n class=\"tree-tree-view__group\"\n role=\"group\"\n >\n <TreeTreeViewItem\n v-for=\"child in node.children\"\n :key=\"child.id\"\n :node=\"child\"\n :level=\"level + 1\"\n />\n </ul>\n </li>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { computed, inject, type ComponentPublicInstance } from 'vue';\nimport { treeTreeViewInjectionKey, type TreeTreeViewNode } from './tree-view';\n\ndefineOptions({\n name: 'TreeTreeViewItem',\n});\n\nconst ChevronRightIcon = getTreeIcon('chevron-right');\nconst CheckIcon = getTreeIcon('check');\n\nconst props = defineProps<{\n node: TreeTreeViewNode;\n level: number;\n}>();\n\nconst ctx = inject(treeTreeViewInjectionKey);\n\nif (!ctx) {\n throw new Error('[TreeUI] TTreeView items must be rendered inside a TTreeView.');\n}\n\nconst hasChildren = computed(() => Boolean(props.node.children?.length));\nconst isExpanded = computed(() => (hasChildren.value ? ctx.isExpanded(props.node.id) : false));\nconst isSelected = computed(() => ctx.isSelected(props.node.id));\nconst isDisabled = computed(() => ctx.disabled.value || props.node.disabled);\nconst isFocused = computed(() => ctx.focusedId.value === props.node.id);\nconst itemId = computed(() => `${ctx.baseId}-${props.node.id}`);\n\nconst rowClasses = computed(() => ({\n 'is-expanded': isExpanded.value,\n 'is-selected': isSelected.value,\n 'is-disabled': isDisabled.value,\n 'is-focused': isFocused.value,\n}));\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLElement) {\n ctx.registerItem(props.node.id, resolvedElement);\n } else {\n ctx.unregisterItem(props.node.id);\n }\n};\n\nconst onRowClick = () => {\n ctx.setFocusedId(props.node.id);\n ctx.toggleSelected(props.node.id);\n};\n\nconst onToggleClick = () => {\n if (isDisabled.value || !hasChildren.value) {\n return;\n }\n\n ctx.toggleExpanded(props.node.id);\n ctx.setFocusedId(props.node.id);\n};\n</script>\n\n<template>\n <li\n class=\"tree-tree-view__node\"\n role=\"none\"\n >\n <div\n :id=\"itemId\"\n :ref=\"setItemRef\"\n class=\"tree-tree-view__row\"\n :class=\"rowClasses\"\n :style=\"{ '--tree-tree-view-level': `${level}` }\"\n role=\"treeitem\"\n :aria-level=\"level\"\n :aria-expanded=\"hasChildren ? isExpanded : undefined\"\n :aria-selected=\"isSelected\"\n :aria-disabled=\"isDisabled || undefined\"\n :tabindex=\"isDisabled ? -1 : isFocused ? 0 : -1\"\n @click=\"onRowClick\"\n @keydown=\"ctx.onItemKeydown($event, node.id)\"\n @focus=\"ctx.setFocusedId(node.id)\"\n >\n <button\n v-if=\"hasChildren\"\n type=\"button\"\n class=\"tree-tree-view__toggle\"\n :class=\"{ 'is-expanded': isExpanded }\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :aria-label=\"isExpanded ? 'Collapse node' : 'Expand node'\"\n @click.stop=\"onToggleClick\"\n >\n <ChevronRightIcon :size=\"16\" />\n </button>\n\n <span\n v-else\n class=\"tree-tree-view__spacer\"\n aria-hidden=\"true\"\n />\n\n <span\n class=\"tree-tree-view__marker\"\n :class=\"{\n 'is-selected': isSelected,\n 'is-multiple': ctx.selectionMode.value === 'multiple',\n }\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"ctx.selectionMode.value === 'multiple' && isSelected\"\n :size=\"14\"\n />\n </span>\n\n <span class=\"tree-tree-view__copy\">\n <span class=\"tree-tree-view__label\">{{ node.label }}</span>\n <span\n v-if=\"node.description\"\n class=\"tree-tree-view__description\"\n >\n {{ node.description }}\n </span>\n </span>\n\n <span\n v-if=\"node.meta\"\n class=\"tree-tree-view__meta\"\n >\n {{ node.meta }}\n </span>\n </div>\n\n <ul\n v-if=\"hasChildren && isExpanded\"\n class=\"tree-tree-view__group\"\n role=\"group\"\n >\n <TreeTreeViewItem\n v-for=\"child in node.children\"\n :key=\"child.id\"\n :node=\"child\"\n :level=\"level + 1\"\n />\n </ul>\n </li>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, provide, ref, useAttrs, watch } from 'vue';\nimport TreeTreeViewItem from './TreeTreeViewItem.vue';\nimport {\n treeTreeViewInjectionKey,\n type TreeTreeViewNode,\n type TreeTreeViewRecord,\n type TreeTreeViewSelectionMode,\n} from './tree-view';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | string[];\n defaultValue?: string | string[];\n nodes?: TreeTreeViewNode[];\n selectionMode?: TreeTreeViewSelectionMode;\n expanded?: string[];\n defaultExpanded?: string[];\n disabled?: boolean;\n emptyText?: string;\n }>(),\n {\n modelValue: undefined,\n defaultValue: undefined,\n nodes: () => [],\n selectionMode: 'single',\n expanded: undefined,\n defaultExpanded: () => [],\n disabled: false,\n emptyText: 'No items available.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined];\n 'update:expanded': [value: string[]];\n 'selection-change': [value: string | string[] | undefined];\n 'expanded-change': [value: string[]];\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('tree-tree-view');\nconst internalValue = ref<string | string[] | undefined>(props.defaultValue);\nconst internalExpanded = ref<string[]>(props.defaultExpanded);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\n\nconst rootClasses = computed(() => [\n 'tree-tree-view',\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst treeAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst selectedValues = computed(() => {\n const value = props.modelValue ?? internalValue.value;\n\n if (value === undefined || value === null || value === '') {\n return [] as string[];\n }\n\n return Array.isArray(value) ? value : [value];\n});\n\nconst expandedValues = computed(() => props.expanded ?? internalExpanded.value);\n\nconst updateSelection = (nextValues: string[]) => {\n if (props.selectionMode === 'multiple') {\n if (props.modelValue === undefined) {\n internalValue.value = nextValues;\n }\n\n emit('update:modelValue', nextValues);\n emit('selection-change', nextValues);\n return;\n }\n\n const nextValue = nextValues[0];\n\n if (props.modelValue === undefined) {\n internalValue.value = nextValue;\n }\n\n emit('update:modelValue', nextValue);\n emit('selection-change', nextValue);\n};\n\nconst updateExpanded = (nextValues: string[]) => {\n if (props.expanded === undefined) {\n internalExpanded.value = nextValues;\n }\n\n emit('update:expanded', nextValues);\n emit('expanded-change', nextValues);\n};\n\nconst isSelected = (id: string) => selectedValues.value.includes(id);\nconst isExpanded = (id: string) => expandedValues.value.includes(id);\n\nconst flattenNodes = (\n nodes: TreeTreeViewNode[],\n level = 1,\n parentId?: string,\n): TreeTreeViewRecord[] =>\n nodes.reduce<TreeTreeViewRecord[]>((records, node) => {\n records.push({\n node,\n level,\n parentId,\n });\n\n if (node.children?.length && isExpanded(node.id)) {\n records.push(...flattenNodes(node.children, level + 1, node.id));\n }\n\n return records;\n }, []);\n\nconst visibleNodes = computed(() => flattenNodes(props.nodes));\nconst enabledNodes = computed(() => visibleNodes.value.filter((record) => !record.node.disabled));\n\nconst getInitialFocusedId = () => {\n const selectedId = selectedValues.value.find((value) =>\n visibleNodes.value.some((record) => record.node.id === value && !record.node.disabled),\n );\n\n if (selectedId) {\n return selectedId;\n }\n\n return enabledNodes.value[0]?.node.id ?? '';\n};\n\nconst focusedId = ref(getInitialFocusedId());\n\nconst registerItem = (id: string, element: HTMLElement) => {\n itemRefs.value.set(id, element);\n};\n\nconst unregisterItem = (id: string) => {\n itemRefs.value.delete(id);\n};\n\nconst focusItem = (id: string) => {\n nextTick(() => itemRefs.value.get(id)?.focus());\n};\n\nconst setFocusedId = (id: string, shouldFocus = false) => {\n focusedId.value = id;\n\n if (shouldFocus) {\n focusItem(id);\n }\n};\n\nconst getVisibleRecord = (id: string) =>\n visibleNodes.value.find((record) => record.node.id === id);\n\nconst focusBoundary = (position: 'first' | 'last') => {\n const target =\n position === 'first' ? enabledNodes.value[0] : enabledNodes.value[enabledNodes.value.length - 1];\n\n if (target) {\n setFocusedId(target.node.id, true);\n }\n};\n\nconst focusAdjacent = (direction: 1 | -1) => {\n const currentIndex = enabledNodes.value.findIndex((record) => record.node.id === focusedId.value);\n\n if (currentIndex === -1) {\n focusBoundary(direction === 1 ? 'first' : 'last');\n return;\n }\n\n const nextIndex = currentIndex + direction;\n\n if (nextIndex < 0 || nextIndex >= enabledNodes.value.length) {\n return;\n }\n\n setFocusedId(enabledNodes.value[nextIndex].node.id, true);\n};\n\nconst toggleExpanded = (id: string) => {\n const nextValues = isExpanded(id)\n ? expandedValues.value.filter((value) => value !== id)\n : [...expandedValues.value, id];\n\n updateExpanded(nextValues);\n};\n\nconst toggleSelected = (id: string) => {\n const record = getVisibleRecord(id);\n\n if (!record || record.node.disabled || props.disabled) {\n return;\n }\n\n if (props.selectionMode === 'multiple') {\n const nextValues = isSelected(id)\n ? selectedValues.value.filter((value) => value !== id)\n : [...selectedValues.value, id];\n\n updateSelection(nextValues);\n return;\n }\n\n updateSelection([id]);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, id: string) => {\n const record = getVisibleRecord(id);\n\n if (!record || record.node.disabled || props.disabled) {\n return;\n }\n\n const hasChildren = Boolean(record.node.children?.length);\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusAdjacent(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusAdjacent(-1);\n break;\n case 'ArrowRight':\n event.preventDefault();\n\n if (hasChildren && !isExpanded(id)) {\n toggleExpanded(id);\n return;\n }\n\n if (hasChildren) {\n const firstChild = visibleNodes.value.find(\n (item) => item.parentId === id && !item.node.disabled,\n );\n\n if (firstChild) {\n setFocusedId(firstChild.node.id, true);\n }\n }\n\n break;\n case 'ArrowLeft':\n event.preventDefault();\n\n if (hasChildren && isExpanded(id)) {\n toggleExpanded(id);\n return;\n }\n\n if (record.parentId) {\n setFocusedId(record.parentId, true);\n }\n\n break;\n case 'Home':\n event.preventDefault();\n focusBoundary('first');\n break;\n case 'End':\n event.preventDefault();\n focusBoundary('last');\n break;\n default:\n if (isActivationKey(event)) {\n event.preventDefault();\n toggleSelected(id);\n }\n break;\n }\n};\n\nwatch(\n () => [visibleNodes.value, props.modelValue] as const,\n () => {\n const focusedRecord = visibleNodes.value.find(\n (record) => record.node.id === focusedId.value && !record.node.disabled,\n );\n\n if (!focusedRecord) {\n focusedId.value = getInitialFocusedId();\n }\n },\n { deep: true, immediate: true },\n);\n\nprovide(treeTreeViewInjectionKey, {\n baseId,\n disabled: computed(() => props.disabled),\n selectionMode: computed(() => props.selectionMode),\n focusedId,\n isExpanded,\n toggleExpanded,\n isSelected,\n toggleSelected,\n setFocusedId,\n onItemKeydown,\n registerItem,\n unregisterItem,\n});\n</script>\n\n<template>\n <div\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"nodes.length > 0\"\n v-bind=\"treeAttrs\"\n class=\"tree-tree-view__root\"\n role=\"tree\"\n :aria-multiselectable=\"selectionMode === 'multiple' || undefined\"\n >\n <TreeTreeViewItem\n v-for=\"node in nodes\"\n :key=\"node.id\"\n :node=\"node\"\n :level=\"1\"\n />\n </ul>\n\n <div\n v-else\n class=\"tree-tree-view__empty\"\n >\n {{ emptyText }}\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, provide, ref, useAttrs, watch } from 'vue';\nimport TreeTreeViewItem from './TreeTreeViewItem.vue';\nimport {\n treeTreeViewInjectionKey,\n type TreeTreeViewNode,\n type TreeTreeViewRecord,\n type TreeTreeViewSelectionMode,\n} from './tree-view';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | string[];\n defaultValue?: string | string[];\n nodes?: TreeTreeViewNode[];\n selectionMode?: TreeTreeViewSelectionMode;\n expanded?: string[];\n defaultExpanded?: string[];\n disabled?: boolean;\n emptyText?: string;\n }>(),\n {\n modelValue: undefined,\n defaultValue: undefined,\n nodes: () => [],\n selectionMode: 'single',\n expanded: undefined,\n defaultExpanded: () => [],\n disabled: false,\n emptyText: 'No items available.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined];\n 'update:expanded': [value: string[]];\n 'selection-change': [value: string | string[] | undefined];\n 'expanded-change': [value: string[]];\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('tree-tree-view');\nconst internalValue = ref<string | string[] | undefined>(props.defaultValue);\nconst internalExpanded = ref<string[]>(props.defaultExpanded);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\n\nconst rootClasses = computed(() => [\n 'tree-tree-view',\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst treeAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst selectedValues = computed(() => {\n const value = props.modelValue ?? internalValue.value;\n\n if (value === undefined || value === null || value === '') {\n return [] as string[];\n }\n\n return Array.isArray(value) ? value : [value];\n});\n\nconst expandedValues = computed(() => props.expanded ?? internalExpanded.value);\n\nconst updateSelection = (nextValues: string[]) => {\n if (props.selectionMode === 'multiple') {\n if (props.modelValue === undefined) {\n internalValue.value = nextValues;\n }\n\n emit('update:modelValue', nextValues);\n emit('selection-change', nextValues);\n return;\n }\n\n const nextValue = nextValues[0];\n\n if (props.modelValue === undefined) {\n internalValue.value = nextValue;\n }\n\n emit('update:modelValue', nextValue);\n emit('selection-change', nextValue);\n};\n\nconst updateExpanded = (nextValues: string[]) => {\n if (props.expanded === undefined) {\n internalExpanded.value = nextValues;\n }\n\n emit('update:expanded', nextValues);\n emit('expanded-change', nextValues);\n};\n\nconst isSelected = (id: string) => selectedValues.value.includes(id);\nconst isExpanded = (id: string) => expandedValues.value.includes(id);\n\nconst flattenNodes = (\n nodes: TreeTreeViewNode[],\n level = 1,\n parentId?: string,\n): TreeTreeViewRecord[] =>\n nodes.reduce<TreeTreeViewRecord[]>((records, node) => {\n records.push({\n node,\n level,\n parentId,\n });\n\n if (node.children?.length && isExpanded(node.id)) {\n records.push(...flattenNodes(node.children, level + 1, node.id));\n }\n\n return records;\n }, []);\n\nconst visibleNodes = computed(() => flattenNodes(props.nodes));\nconst enabledNodes = computed(() => visibleNodes.value.filter((record) => !record.node.disabled));\n\nconst getInitialFocusedId = () => {\n const selectedId = selectedValues.value.find((value) =>\n visibleNodes.value.some((record) => record.node.id === value && !record.node.disabled),\n );\n\n if (selectedId) {\n return selectedId;\n }\n\n return enabledNodes.value[0]?.node.id ?? '';\n};\n\nconst focusedId = ref(getInitialFocusedId());\n\nconst registerItem = (id: string, element: HTMLElement) => {\n itemRefs.value.set(id, element);\n};\n\nconst unregisterItem = (id: string) => {\n itemRefs.value.delete(id);\n};\n\nconst focusItem = (id: string) => {\n nextTick(() => itemRefs.value.get(id)?.focus());\n};\n\nconst setFocusedId = (id: string, shouldFocus = false) => {\n focusedId.value = id;\n\n if (shouldFocus) {\n focusItem(id);\n }\n};\n\nconst getVisibleRecord = (id: string) =>\n visibleNodes.value.find((record) => record.node.id === id);\n\nconst focusBoundary = (position: 'first' | 'last') => {\n const target =\n position === 'first' ? enabledNodes.value[0] : enabledNodes.value[enabledNodes.value.length - 1];\n\n if (target) {\n setFocusedId(target.node.id, true);\n }\n};\n\nconst focusAdjacent = (direction: 1 | -1) => {\n const currentIndex = enabledNodes.value.findIndex((record) => record.node.id === focusedId.value);\n\n if (currentIndex === -1) {\n focusBoundary(direction === 1 ? 'first' : 'last');\n return;\n }\n\n const nextIndex = currentIndex + direction;\n\n if (nextIndex < 0 || nextIndex >= enabledNodes.value.length) {\n return;\n }\n\n setFocusedId(enabledNodes.value[nextIndex].node.id, true);\n};\n\nconst toggleExpanded = (id: string) => {\n const nextValues = isExpanded(id)\n ? expandedValues.value.filter((value) => value !== id)\n : [...expandedValues.value, id];\n\n updateExpanded(nextValues);\n};\n\nconst toggleSelected = (id: string) => {\n const record = getVisibleRecord(id);\n\n if (!record || record.node.disabled || props.disabled) {\n return;\n }\n\n if (props.selectionMode === 'multiple') {\n const nextValues = isSelected(id)\n ? selectedValues.value.filter((value) => value !== id)\n : [...selectedValues.value, id];\n\n updateSelection(nextValues);\n return;\n }\n\n updateSelection([id]);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, id: string) => {\n const record = getVisibleRecord(id);\n\n if (!record || record.node.disabled || props.disabled) {\n return;\n }\n\n const hasChildren = Boolean(record.node.children?.length);\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusAdjacent(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusAdjacent(-1);\n break;\n case 'ArrowRight':\n event.preventDefault();\n\n if (hasChildren && !isExpanded(id)) {\n toggleExpanded(id);\n return;\n }\n\n if (hasChildren) {\n const firstChild = visibleNodes.value.find(\n (item) => item.parentId === id && !item.node.disabled,\n );\n\n if (firstChild) {\n setFocusedId(firstChild.node.id, true);\n }\n }\n\n break;\n case 'ArrowLeft':\n event.preventDefault();\n\n if (hasChildren && isExpanded(id)) {\n toggleExpanded(id);\n return;\n }\n\n if (record.parentId) {\n setFocusedId(record.parentId, true);\n }\n\n break;\n case 'Home':\n event.preventDefault();\n focusBoundary('first');\n break;\n case 'End':\n event.preventDefault();\n focusBoundary('last');\n break;\n default:\n if (isActivationKey(event)) {\n event.preventDefault();\n toggleSelected(id);\n }\n break;\n }\n};\n\nwatch(\n () => [visibleNodes.value, props.modelValue] as const,\n () => {\n const focusedRecord = visibleNodes.value.find(\n (record) => record.node.id === focusedId.value && !record.node.disabled,\n );\n\n if (!focusedRecord) {\n focusedId.value = getInitialFocusedId();\n }\n },\n { deep: true, immediate: true },\n);\n\nprovide(treeTreeViewInjectionKey, {\n baseId,\n disabled: computed(() => props.disabled),\n selectionMode: computed(() => props.selectionMode),\n focusedId,\n isExpanded,\n toggleExpanded,\n isSelected,\n toggleSelected,\n setFocusedId,\n onItemKeydown,\n registerItem,\n unregisterItem,\n});\n</script>\n\n<template>\n <div\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"nodes.length > 0\"\n v-bind=\"treeAttrs\"\n class=\"tree-tree-view__root\"\n role=\"tree\"\n :aria-multiselectable=\"selectionMode === 'multiple' || undefined\"\n >\n <TreeTreeViewItem\n v-for=\"node in nodes\"\n :key=\"node.id\"\n :node=\"node\"\n :level=\"1\"\n />\n </ul>\n\n <div\n v-else\n class=\"tree-tree-view__empty\"\n >\n {{ emptyText }}\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeStepItem {\n label: string;\n value: string;\n description?: string;\n meta?: string;\n status?: TreeStepStatus;\n disabled?: boolean;\n}\n\nconst _treeStepStatuses = ['complete', 'current', 'upcoming', 'error'] as const;\nconst _treeStepOrientations = ['horizontal', 'vertical'] as const;\n\nexport type TreeStepStatus = (typeof _treeStepStatuses)[number];\nexport type TreeStepOrientation = (typeof _treeStepOrientations)[number];\n\nconst CheckIcon = getTreeIcon('check');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TreeStepItem[];\n size?: TreeSize;\n orientation?: TreeStepOrientation;\n interactive?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n orientation: 'horizontal',\n interactive: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TreeStepItem;\n index: number;\n status: TreeStepStatus;\n current: boolean;\n }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst internalValue = ref(props.defaultValue || props.items[0]?.value || '');\n\nconst activeValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst currentIndex = computed(() => {\n const activeIndex = props.items.findIndex((item) => item.value === activeValue.value);\n return activeIndex >= 0 ? activeIndex : 0;\n});\n\nconst rootClasses = computed(() => [\n 'tree-steps',\n `tree-steps--${props.size}`,\n `tree-steps--${props.orientation}`,\n {\n 'is-interactive': props.interactive,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst resolveStatus = (item: TreeStepItem, index: number): TreeStepStatus => {\n if (item.status) {\n return item.status;\n }\n\n if (index < currentIndex.value) {\n return 'complete';\n }\n\n if (index === currentIndex.value) {\n return 'current';\n }\n\n return 'upcoming';\n};\n\nconst selectStep = (item: TreeStepItem) => {\n if (!props.interactive || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n};\n\nwatch(\n () => props.items,\n (items) => {\n const hasCurrentItem = items.some((item) => item.value === activeValue.value);\n\n if (!hasCurrentItem && items[0] && props.modelValue === undefined) {\n internalValue.value = items[0].value;\n }\n },\n { deep: true },\n);\n</script>\n\n<template>\n <ol\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"tree-steps__item\"\n :class=\"`is-${resolveStatus(item, index)}`\"\n >\n <button\n type=\"button\"\n class=\"tree-steps__button\"\n :class=\"{\n 'is-current': resolveStatus(item, index) === 'current',\n 'is-disabled': item.disabled,\n }\"\n :disabled=\"!interactive || item.disabled\"\n :aria-current=\"resolveStatus(item, index) === 'current' ? 'step' : undefined\"\n @click=\"selectStep(item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n :status=\"resolveStatus(item, index)\"\n :current=\"resolveStatus(item, index) === 'current'\"\n >\n <span\n class=\"tree-steps__indicator\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"resolveStatus(item, index) === 'complete'\"\n v-bind=\"treeIconDefaults\"\n />\n <span v-else-if=\"resolveStatus(item, index) === 'error'\">!</span>\n <span v-else>{{ index + 1 }}</span>\n </span>\n\n <span class=\"tree-steps__copy\">\n <span class=\"tree-steps__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"tree-steps__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.meta\"\n class=\"tree-steps__meta\"\n >\n {{ item.meta }}\n </span>\n </slot>\n </button>\n </li>\n </ol>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeStepItem {\n label: string;\n value: string;\n description?: string;\n meta?: string;\n status?: TreeStepStatus;\n disabled?: boolean;\n}\n\nconst _treeStepStatuses = ['complete', 'current', 'upcoming', 'error'] as const;\nconst _treeStepOrientations = ['horizontal', 'vertical'] as const;\n\nexport type TreeStepStatus = (typeof _treeStepStatuses)[number];\nexport type TreeStepOrientation = (typeof _treeStepOrientations)[number];\n\nconst CheckIcon = getTreeIcon('check');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TreeStepItem[];\n size?: TreeSize;\n orientation?: TreeStepOrientation;\n interactive?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n orientation: 'horizontal',\n interactive: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TreeStepItem;\n index: number;\n status: TreeStepStatus;\n current: boolean;\n }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst internalValue = ref(props.defaultValue || props.items[0]?.value || '');\n\nconst activeValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst currentIndex = computed(() => {\n const activeIndex = props.items.findIndex((item) => item.value === activeValue.value);\n return activeIndex >= 0 ? activeIndex : 0;\n});\n\nconst rootClasses = computed(() => [\n 'tree-steps',\n `tree-steps--${props.size}`,\n `tree-steps--${props.orientation}`,\n {\n 'is-interactive': props.interactive,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst resolveStatus = (item: TreeStepItem, index: number): TreeStepStatus => {\n if (item.status) {\n return item.status;\n }\n\n if (index < currentIndex.value) {\n return 'complete';\n }\n\n if (index === currentIndex.value) {\n return 'current';\n }\n\n return 'upcoming';\n};\n\nconst selectStep = (item: TreeStepItem) => {\n if (!props.interactive || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n};\n\nwatch(\n () => props.items,\n (items) => {\n const hasCurrentItem = items.some((item) => item.value === activeValue.value);\n\n if (!hasCurrentItem && items[0] && props.modelValue === undefined) {\n internalValue.value = items[0].value;\n }\n },\n { deep: true },\n);\n</script>\n\n<template>\n <ol\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"tree-steps__item\"\n :class=\"`is-${resolveStatus(item, index)}`\"\n >\n <button\n type=\"button\"\n class=\"tree-steps__button\"\n :class=\"{\n 'is-current': resolveStatus(item, index) === 'current',\n 'is-disabled': item.disabled,\n }\"\n :disabled=\"!interactive || item.disabled\"\n :aria-current=\"resolveStatus(item, index) === 'current' ? 'step' : undefined\"\n @click=\"selectStep(item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n :status=\"resolveStatus(item, index)\"\n :current=\"resolveStatus(item, index) === 'current'\"\n >\n <span\n class=\"tree-steps__indicator\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"resolveStatus(item, index) === 'complete'\"\n v-bind=\"treeIconDefaults\"\n />\n <span v-else-if=\"resolveStatus(item, index) === 'error'\">!</span>\n <span v-else>{{ index + 1 }}</span>\n </span>\n\n <span class=\"tree-steps__copy\">\n <span class=\"tree-steps__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"tree-steps__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.meta\"\n class=\"tree-steps__meta\"\n >\n {{ item.meta }}\n </span>\n </slot>\n </button>\n </li>\n </ol>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, ref, useAttrs, watch, type ComponentPublicInstance } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeToggleGroupOption {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst _treeToggleGroupSelectionModes = ['single', 'multiple'] as const;\nconst _treeToggleGroupVariants = ['outline', 'soft', 'solid'] as const;\n\nexport type TreeToggleGroupSelectionMode = (typeof _treeToggleGroupSelectionModes)[number];\nexport type TreeToggleGroupVariant = (typeof _treeToggleGroupVariants)[number];\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | string[];\n options?: TreeToggleGroupOption[];\n selectionMode?: TreeToggleGroupSelectionMode;\n size?: TreeSize;\n variant?: TreeToggleGroupVariant;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n options: () => [],\n selectionMode: 'single',\n size: 'md',\n variant: 'outline',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined];\n}>();\n\ndefineSlots<{\n option?: (props: { option: TreeToggleGroupOption; selected: boolean }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('tree-toggle-group');\nconst buttonRefs = ref<Map<string, HTMLButtonElement>>(new Map());\n\nconst normalizedValues = computed(() =>\n props.selectionMode === 'multiple'\n ? Array.isArray(props.modelValue)\n ? props.modelValue\n : []\n : typeof props.modelValue === 'string' && props.modelValue\n ? [props.modelValue]\n : [],\n);\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.options.findIndex((option) =>\n normalizedValues.value.includes(option.value) && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.options.findIndex((option) => !option.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 'tree-toggle-group',\n `tree-toggle-group--${props.size}`,\n `tree-toggle-group--${props.variant}`,\n `tree-toggle-group--${props.selectionMode}`,\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => normalizedValues.value.includes(value);\n\nconst setButtonRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLButtonElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLButtonElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLButtonElement) {\n buttonRefs.value.set(value, resolvedElement);\n } else {\n buttonRefs.value.delete(value);\n }\n};\n\nconst focusOption = (index: number) => {\n const option = props.options[index];\n\n if (!option) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => buttonRefs.value.get(option.value)?.focus());\n};\n\nconst selectValue = (value: string) => {\n const option = props.options.find((item) => item.value === value);\n\n if (!option || option.disabled || props.disabled) {\n return;\n }\n\n if (props.selectionMode === 'multiple') {\n const nextValues = isSelected(value)\n ? normalizedValues.value.filter((item) => item !== value)\n : [...normalizedValues.value, value];\n\n emit('update:modelValue', nextValues);\n return;\n }\n\n emit('update:modelValue', value);\n};\n\nconst onOptionKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.options.findIndex((option) => !option.disabled);\n\n if (firstIndex >= 0) {\n focusOption(firstIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[firstIndex].value);\n }\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.options].reverse().findIndex((option) => !option.disabled);\n\n if (lastIndex >= 0) {\n const resolvedIndex = props.options.length - 1 - lastIndex;\n focusOption(resolvedIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[resolvedIndex].value);\n }\n }\n\n return;\n }\n\n if (\n event.key === 'ArrowRight' ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowLeft' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n const direction = event.key === 'ArrowRight' || event.key === 'ArrowDown' ? 1 : -1;\n const nextIndex = getNextEnabledIndex(index, props.options, direction as 1 | -1);\n\n if (nextIndex >= 0) {\n focusOption(nextIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[nextIndex].value);\n }\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectValue(props.options[index].value);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.modelValue, props.options] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <div\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :role=\"selectionMode === 'single' ? 'radiogroup' : 'group'\"\n >\n <button\n v-for=\"(option, index) in options\"\n :id=\"`${baseId}-${option.value}`\"\n :ref=\"(element) => setButtonRef(element, option.value)\"\n :key=\"option.value\"\n type=\"button\"\n class=\"tree-toggle-group__item\"\n :class=\"{\n 'is-selected': isSelected(option.value),\n 'is-disabled': disabled || option.disabled,\n }\"\n :role=\"selectionMode === 'single' ? 'radio' : undefined\"\n :aria-checked=\"selectionMode === 'single' ? isSelected(option.value) : undefined\"\n :aria-pressed=\"selectionMode === 'multiple' ? isSelected(option.value) : undefined\"\n :tabindex=\"option.disabled || disabled ? -1 : getTabIndex(index)\"\n :disabled=\"disabled || option.disabled\"\n @click=\"selectValue(option.value)\"\n @keydown=\"onOptionKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"isSelected(option.value)\"\n >\n {{ option.label }}\n </slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, ref, useAttrs, watch, type ComponentPublicInstance } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TreeToggleGroupOption {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst _treeToggleGroupSelectionModes = ['single', 'multiple'] as const;\nconst _treeToggleGroupVariants = ['outline', 'soft', 'solid'] as const;\n\nexport type TreeToggleGroupSelectionMode = (typeof _treeToggleGroupSelectionModes)[number];\nexport type TreeToggleGroupVariant = (typeof _treeToggleGroupVariants)[number];\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | string[];\n options?: TreeToggleGroupOption[];\n selectionMode?: TreeToggleGroupSelectionMode;\n size?: TreeSize;\n variant?: TreeToggleGroupVariant;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n options: () => [],\n selectionMode: 'single',\n size: 'md',\n variant: 'outline',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined];\n}>();\n\ndefineSlots<{\n option?: (props: { option: TreeToggleGroupOption; selected: boolean }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('tree-toggle-group');\nconst buttonRefs = ref<Map<string, HTMLButtonElement>>(new Map());\n\nconst normalizedValues = computed(() =>\n props.selectionMode === 'multiple'\n ? Array.isArray(props.modelValue)\n ? props.modelValue\n : []\n : typeof props.modelValue === 'string' && props.modelValue\n ? [props.modelValue]\n : [],\n);\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.options.findIndex((option) =>\n normalizedValues.value.includes(option.value) && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.options.findIndex((option) => !option.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 'tree-toggle-group',\n `tree-toggle-group--${props.size}`,\n `tree-toggle-group--${props.variant}`,\n `tree-toggle-group--${props.selectionMode}`,\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => normalizedValues.value.includes(value);\n\nconst setButtonRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLButtonElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLButtonElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLButtonElement) {\n buttonRefs.value.set(value, resolvedElement);\n } else {\n buttonRefs.value.delete(value);\n }\n};\n\nconst focusOption = (index: number) => {\n const option = props.options[index];\n\n if (!option) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => buttonRefs.value.get(option.value)?.focus());\n};\n\nconst selectValue = (value: string) => {\n const option = props.options.find((item) => item.value === value);\n\n if (!option || option.disabled || props.disabled) {\n return;\n }\n\n if (props.selectionMode === 'multiple') {\n const nextValues = isSelected(value)\n ? normalizedValues.value.filter((item) => item !== value)\n : [...normalizedValues.value, value];\n\n emit('update:modelValue', nextValues);\n return;\n }\n\n emit('update:modelValue', value);\n};\n\nconst onOptionKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.options.findIndex((option) => !option.disabled);\n\n if (firstIndex >= 0) {\n focusOption(firstIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[firstIndex].value);\n }\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.options].reverse().findIndex((option) => !option.disabled);\n\n if (lastIndex >= 0) {\n const resolvedIndex = props.options.length - 1 - lastIndex;\n focusOption(resolvedIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[resolvedIndex].value);\n }\n }\n\n return;\n }\n\n if (\n event.key === 'ArrowRight' ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowLeft' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n const direction = event.key === 'ArrowRight' || event.key === 'ArrowDown' ? 1 : -1;\n const nextIndex = getNextEnabledIndex(index, props.options, direction as 1 | -1);\n\n if (nextIndex >= 0) {\n focusOption(nextIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[nextIndex].value);\n }\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectValue(props.options[index].value);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.modelValue, props.options] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <div\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :role=\"selectionMode === 'single' ? 'radiogroup' : 'group'\"\n >\n <button\n v-for=\"(option, index) in options\"\n :id=\"`${baseId}-${option.value}`\"\n :ref=\"(element) => setButtonRef(element, option.value)\"\n :key=\"option.value\"\n type=\"button\"\n class=\"tree-toggle-group__item\"\n :class=\"{\n 'is-selected': isSelected(option.value),\n 'is-disabled': disabled || option.disabled,\n }\"\n :role=\"selectionMode === 'single' ? 'radio' : undefined\"\n :aria-checked=\"selectionMode === 'single' ? isSelected(option.value) : undefined\"\n :aria-pressed=\"selectionMode === 'multiple' ? isSelected(option.value) : undefined\"\n :tabindex=\"option.disabled || disabled ? -1 : getTabIndex(index)\"\n :disabled=\"disabled || option.disabled\"\n @click=\"selectValue(option.value)\"\n @keydown=\"onOptionKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"isSelected(option.value)\"\n >\n {{ option.label }}\n </slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs, ref, watch, nextTick } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n rows?: number;\n autoGrow?: boolean;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n rows: 3,\n autoGrow: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\nconst textareaRef = ref<HTMLTextAreaElement | null>(null);\n\nconst rootClasses = computed(() => [\n 'tree-textarea',\n `tree-textarea--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst textareaAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value);\n};\n\nconst adjustHeight = () => {\n const el = textareaRef.value;\n if (!el || !props.autoGrow) return;\n el.style.height = 'auto';\n el.style.height = `${el.scrollHeight}px`;\n};\n\nwatch(\n () => props.modelValue,\n async () => {\n if (!props.autoGrow) return;\n await nextTick();\n adjustHeight();\n },\n);\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <textarea\n ref=\"textareaRef\"\n v-bind=\"textareaAttrs\"\n class=\"tree-textarea__field\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n />\n <TreeSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs, ref, watch, nextTick } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport TreeSpinner from './TreeSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n size?: TreeSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n rows?: number;\n autoGrow?: boolean;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n rows: 3,\n autoGrow: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\nconst textareaRef = ref<HTMLTextAreaElement | null>(null);\n\nconst rootClasses = computed(() => [\n 'tree-textarea',\n `tree-textarea--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst textareaAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value);\n};\n\nconst adjustHeight = () => {\n const el = textareaRef.value;\n if (!el || !props.autoGrow) return;\n el.style.height = 'auto';\n el.style.height = `${el.scrollHeight}px`;\n};\n\nwatch(\n () => props.modelValue,\n async () => {\n if (!props.autoGrow) return;\n await nextTick();\n adjustHeight();\n },\n);\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <textarea\n ref=\"textareaRef\"\n v-bind=\"textareaAttrs\"\n class=\"tree-textarea__field\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n />\n <TreeSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n width?: string;\n height?: string;\n animation?: 'pulse' | 'wave' | 'none';\n }>(),\n {\n width: '100%',\n height: undefined,\n animation: 'pulse',\n },\n);\n\nconst classes = computed(() => [\n 'tree-skeleton',\n props.animation !== 'none' ? `tree-skeleton--${props.animation}` : '',\n]);\n\nconst style = computed(() => ({\n width: props.width,\n height: props.height,\n}));\n</script>\n\n<template>\n <span\n :class=\"classes\"\n :style=\"style\"\n aria-hidden=\"true\"\n >\n <slot />\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n width?: string;\n height?: string;\n animation?: 'pulse' | 'wave' | 'none';\n }>(),\n {\n width: '100%',\n height: undefined,\n animation: 'pulse',\n },\n);\n\nconst classes = computed(() => [\n 'tree-skeleton',\n props.animation !== 'none' ? `tree-skeleton--${props.animation}` : '',\n]);\n\nconst style = computed(() => ({\n width: props.width,\n height: props.height,\n}));\n</script>\n\n<template>\n <span\n :class=\"classes\"\n :style=\"style\"\n aria-hidden=\"true\"\n >\n <slot />\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs, useSlots } from 'vue';\nimport TreeSkeleton from './TreeSkeleton.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeStatTones = ['neutral', 'success', 'warning', 'danger', 'info'] as const;\nconst _treeStatTrendDirections = ['up', 'down', 'neutral'] as const;\n\nexport type TreeStatTone = (typeof _treeStatTones)[number];\nexport type TreeStatTrendDirection = (typeof _treeStatTrendDirections)[number];\n\nconst props = withDefaults(\n defineProps<{\n label?: string;\n value?: string | number;\n trend?: string;\n meta?: string;\n tone?: TreeStatTone;\n trendDirection?: TreeStatTrendDirection;\n loading?: boolean;\n }>(),\n {\n label: '',\n value: '',\n trend: '',\n meta: '',\n tone: 'neutral',\n trendDirection: 'neutral',\n loading: false,\n },\n);\n\ndefineSlots<{\n icon?: () => unknown;\n label?: () => unknown;\n value?: () => unknown;\n trend?: () => unknown;\n meta?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst slots = useSlots();\n\nconst rootClasses = computed(() => [\n 'tree-stat',\n `tree-stat--${props.tone}`,\n {\n 'has-icon': Boolean(slots.icon) && !props.loading,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst loadingAttrs = computed(() => ({\n ...rootAttrs.value,\n 'aria-busy': props.loading || undefined,\n}));\n\nconst hasValue = computed(() => props.value !== '' && props.value !== null && props.value !== undefined);\nconst hasTrend = computed(() => Boolean(slots.trend || props.trend));\nconst hasMeta = computed(() => Boolean(slots.meta || props.meta));\nconst hasLabel = computed(() => Boolean(slots.label || props.label));\n\nconst trendSymbol = computed(() => {\n if (props.trendDirection === 'up') {\n return '+';\n }\n\n if (props.trendDirection === 'down') {\n return '-';\n }\n\n return '•';\n});\n</script>\n\n<template>\n <div\n v-bind=\"loadingAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <template v-if=\"loading\">\n <div class=\"tree-stat__loading\">\n <TreeSkeleton class=\"tree-stat__loading-label\" />\n <TreeSkeleton class=\"tree-stat__loading-value\" />\n <TreeSkeleton class=\"tree-stat__loading-trend\" />\n </div>\n </template>\n <template v-else>\n <div\n v-if=\"$slots.icon\"\n class=\"tree-stat__icon\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div class=\"tree-stat__body\">\n <div\n v-if=\"hasLabel || hasMeta\"\n class=\"tree-stat__topline\"\n >\n <p\n v-if=\"hasLabel\"\n class=\"tree-stat__label\"\n >\n <slot name=\"label\">\n {{ label }}\n </slot>\n </p>\n\n <p\n v-if=\"hasMeta\"\n class=\"tree-stat__meta\"\n >\n <slot name=\"meta\">\n {{ meta }}\n </slot>\n </p>\n </div>\n\n <div class=\"tree-stat__content\">\n <p\n v-if=\"hasValue || $slots.value\"\n class=\"tree-stat__value\"\n >\n <slot name=\"value\">\n {{ value }}\n </slot>\n </p>\n\n <p\n v-if=\"hasTrend\"\n class=\"tree-stat__trend\"\n >\n <slot name=\"trend\">\n <span\n class=\"tree-stat__trend-indicator\"\n aria-hidden=\"true\"\n >\n {{ trendSymbol }}\n </span>\n <span>{{ trend }}</span>\n </slot>\n </p>\n </div>\n </div>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs, useSlots } from 'vue';\nimport TreeSkeleton from './TreeSkeleton.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeStatTones = ['neutral', 'success', 'warning', 'danger', 'info'] as const;\nconst _treeStatTrendDirections = ['up', 'down', 'neutral'] as const;\n\nexport type TreeStatTone = (typeof _treeStatTones)[number];\nexport type TreeStatTrendDirection = (typeof _treeStatTrendDirections)[number];\n\nconst props = withDefaults(\n defineProps<{\n label?: string;\n value?: string | number;\n trend?: string;\n meta?: string;\n tone?: TreeStatTone;\n trendDirection?: TreeStatTrendDirection;\n loading?: boolean;\n }>(),\n {\n label: '',\n value: '',\n trend: '',\n meta: '',\n tone: 'neutral',\n trendDirection: 'neutral',\n loading: false,\n },\n);\n\ndefineSlots<{\n icon?: () => unknown;\n label?: () => unknown;\n value?: () => unknown;\n trend?: () => unknown;\n meta?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst slots = useSlots();\n\nconst rootClasses = computed(() => [\n 'tree-stat',\n `tree-stat--${props.tone}`,\n {\n 'has-icon': Boolean(slots.icon) && !props.loading,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst loadingAttrs = computed(() => ({\n ...rootAttrs.value,\n 'aria-busy': props.loading || undefined,\n}));\n\nconst hasValue = computed(() => props.value !== '' && props.value !== null && props.value !== undefined);\nconst hasTrend = computed(() => Boolean(slots.trend || props.trend));\nconst hasMeta = computed(() => Boolean(slots.meta || props.meta));\nconst hasLabel = computed(() => Boolean(slots.label || props.label));\n\nconst trendSymbol = computed(() => {\n if (props.trendDirection === 'up') {\n return '+';\n }\n\n if (props.trendDirection === 'down') {\n return '-';\n }\n\n return '•';\n});\n</script>\n\n<template>\n <div\n v-bind=\"loadingAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <template v-if=\"loading\">\n <div class=\"tree-stat__loading\">\n <TreeSkeleton class=\"tree-stat__loading-label\" />\n <TreeSkeleton class=\"tree-stat__loading-value\" />\n <TreeSkeleton class=\"tree-stat__loading-trend\" />\n </div>\n </template>\n <template v-else>\n <div\n v-if=\"$slots.icon\"\n class=\"tree-stat__icon\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div class=\"tree-stat__body\">\n <div\n v-if=\"hasLabel || hasMeta\"\n class=\"tree-stat__topline\"\n >\n <p\n v-if=\"hasLabel\"\n class=\"tree-stat__label\"\n >\n <slot name=\"label\">\n {{ label }}\n </slot>\n </p>\n\n <p\n v-if=\"hasMeta\"\n class=\"tree-stat__meta\"\n >\n <slot name=\"meta\">\n {{ meta }}\n </slot>\n </p>\n </div>\n\n <div class=\"tree-stat__content\">\n <p\n v-if=\"hasValue || $slots.value\"\n class=\"tree-stat__value\"\n >\n <slot name=\"value\">\n {{ value }}\n </slot>\n </p>\n\n <p\n v-if=\"hasTrend\"\n class=\"tree-stat__trend\"\n >\n <slot name=\"trend\">\n <span\n class=\"tree-stat__trend-indicator\"\n aria-hidden=\"true\"\n >\n {{ trendSymbol }}\n </span>\n <span>{{ trend }}</span>\n </slot>\n </p>\n </div>\n </div>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n invalid?: boolean;\n }>(),\n {\n modelValue: false,\n size: 'md',\n disabled: false,\n invalid: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-switch',\n `tree-switch--${props.size}`,\n {\n 'is-checked': props.modelValue,\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n emit('update:modelValue', !props.modelValue);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n v-bind=\"inputAttrs\"\n type=\"checkbox\"\n role=\"switch\"\n class=\"tree-switch__input\"\n :checked=\"modelValue\"\n :disabled=\"disabled\"\n :aria-checked=\"modelValue\"\n :aria-invalid=\"invalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"tree-switch__track\"\n aria-hidden=\"true\"\n >\n <span class=\"tree-switch__thumb\" />\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"tree-switch__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean;\n size?: TreeSize;\n disabled?: boolean;\n invalid?: boolean;\n }>(),\n {\n modelValue: false,\n size: 'md',\n disabled: false,\n invalid: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 'tree-switch',\n `tree-switch--${props.size}`,\n {\n 'is-checked': props.modelValue,\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n emit('update:modelValue', !props.modelValue);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n v-bind=\"inputAttrs\"\n type=\"checkbox\"\n role=\"switch\"\n class=\"tree-switch__input\"\n :checked=\"modelValue\"\n :disabled=\"disabled\"\n :aria-checked=\"modelValue\"\n :aria-invalid=\"invalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"tree-switch__track\"\n aria-hidden=\"true\"\n >\n <span class=\"tree-switch__thumb\" />\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"tree-switch__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, toRef, useAttrs } from 'vue';\nimport { createId } from '@treeui/utils';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeTooltipSide } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n content?: string;\n side?: TreeTooltipSide;\n delay?: number;\n id?: string;\n }>(),\n {\n defaultOpen: false,\n disabled: false,\n content: '',\n side: 'top',\n delay: 80,\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst contentId = props.id ?? createId('tree-tooltip');\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst rootClasses = computed(() => ['tree-tooltip', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nlet openTimer: ReturnType<typeof setTimeout> | undefined;\n\nconst clearOpenTimer = () => {\n if (openTimer) {\n clearTimeout(openTimer);\n openTimer = undefined;\n }\n};\n\nconst show = (immediate = false) => {\n if (props.disabled) {\n return;\n }\n\n clearOpenTimer();\n\n if (immediate) {\n setValue(true);\n return;\n }\n\n openTimer = setTimeout(() => {\n setValue(true);\n }, props.delay);\n};\n\nconst showOnFocus = () => {\n show(true);\n};\n\nconst showOnPointer = () => {\n show();\n};\n\nconst hide = () => {\n clearOpenTimer();\n setValue(false);\n};\n\nconst tooltipClasses = computed(() => [\n 'tree-tooltip__content',\n `tree-tooltip__content--${props.side}`,\n]);\n\nonBeforeUnmount(clearOpenTimer);\n</script>\n\n<template>\n <span\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n @mouseenter=\"showOnPointer\"\n @mouseleave=\"hide\"\n @focus.capture=\"showOnFocus\"\n @blur.capture=\"hide\"\n >\n <span\n class=\"tree-tooltip__trigger\"\n :aria-describedby=\"isOpen ? contentId : undefined\"\n v-bind=\"triggerAttrs\"\n >\n <slot name=\"trigger\">\n <slot />\n </slot>\n </span>\n <transition name=\"tree-fade\">\n <span\n v-if=\"isOpen && !disabled\"\n :id=\"contentId\"\n role=\"tooltip\"\n :class=\"tooltipClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <slot name=\"content\">\n {{ content }}\n </slot>\n </span>\n </transition>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, toRef, useAttrs } from 'vue';\nimport { createId } from '@treeui/utils';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeTooltipSide } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n content?: string;\n side?: TreeTooltipSide;\n delay?: number;\n id?: string;\n }>(),\n {\n defaultOpen: false,\n disabled: false,\n content: '',\n side: 'top',\n delay: 80,\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst contentId = props.id ?? createId('tree-tooltip');\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst rootClasses = computed(() => ['tree-tooltip', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nlet openTimer: ReturnType<typeof setTimeout> | undefined;\n\nconst clearOpenTimer = () => {\n if (openTimer) {\n clearTimeout(openTimer);\n openTimer = undefined;\n }\n};\n\nconst show = (immediate = false) => {\n if (props.disabled) {\n return;\n }\n\n clearOpenTimer();\n\n if (immediate) {\n setValue(true);\n return;\n }\n\n openTimer = setTimeout(() => {\n setValue(true);\n }, props.delay);\n};\n\nconst showOnFocus = () => {\n show(true);\n};\n\nconst showOnPointer = () => {\n show();\n};\n\nconst hide = () => {\n clearOpenTimer();\n setValue(false);\n};\n\nconst tooltipClasses = computed(() => [\n 'tree-tooltip__content',\n `tree-tooltip__content--${props.side}`,\n]);\n\nonBeforeUnmount(clearOpenTimer);\n</script>\n\n<template>\n <span\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n @mouseenter=\"showOnPointer\"\n @mouseleave=\"hide\"\n @focus.capture=\"showOnFocus\"\n @blur.capture=\"hide\"\n >\n <span\n class=\"tree-tooltip__trigger\"\n :aria-describedby=\"isOpen ? contentId : undefined\"\n v-bind=\"triggerAttrs\"\n >\n <slot name=\"trigger\">\n <slot />\n </slot>\n </span>\n <transition name=\"tree-fade\">\n <span\n v-if=\"isOpen && !disabled\"\n :id=\"contentId\"\n role=\"tooltip\"\n :class=\"tooltipClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <slot name=\"content\">\n {{ content }}\n </slot>\n </span>\n </transition>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n label?: string;\n htmlFor?: string;\n error?: string;\n hint?: string;\n required?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n }>(),\n {\n label: undefined,\n htmlFor: undefined,\n error: undefined,\n hint: undefined,\n required: false,\n disabled: false,\n size: 'md',\n },\n);\n\nconst attrs = useAttrs();\n\nconst hasError = computed(() => !!props.error || !!slots.error);\n\nconst slots = defineSlots<{\n default?: (props: Record<string, never>) => unknown;\n label?: (props: Record<string, never>) => unknown;\n error?: (props: Record<string, never>) => unknown;\n hint?: (props: Record<string, never>) => unknown;\n}>();\n\nconst rootClasses = computed(() => [\n 'tree-form-field',\n `tree-form-field--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': hasError.value,\n 'is-required': props.required,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst fieldAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <div\n v-bind=\"fieldAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <label\n v-if=\"label || $slots.label\"\n class=\"tree-form-field__label\"\n :for=\"htmlFor\"\n >\n <slot name=\"label\">{{ label }}</slot>\n <span\n v-if=\"required\"\n class=\"tree-form-field__required\"\n aria-hidden=\"true\"\n >*</span>\n </label>\n\n <div class=\"tree-form-field__control\">\n <slot />\n </div>\n\n <p\n v-if=\"hasError\"\n class=\"tree-form-field__error\"\n role=\"alert\"\n >\n <slot name=\"error\">\n {{ error }}\n </slot>\n </p>\n\n <p\n v-else-if=\"hint || $slots.hint\"\n class=\"tree-form-field__hint\"\n >\n <slot name=\"hint\">\n {{ hint }}\n </slot>\n </p>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n label?: string;\n htmlFor?: string;\n error?: string;\n hint?: string;\n required?: boolean;\n disabled?: boolean;\n size?: TreeSize;\n }>(),\n {\n label: undefined,\n htmlFor: undefined,\n error: undefined,\n hint: undefined,\n required: false,\n disabled: false,\n size: 'md',\n },\n);\n\nconst attrs = useAttrs();\n\nconst hasError = computed(() => !!props.error || !!slots.error);\n\nconst slots = defineSlots<{\n default?: (props: Record<string, never>) => unknown;\n label?: (props: Record<string, never>) => unknown;\n error?: (props: Record<string, never>) => unknown;\n hint?: (props: Record<string, never>) => unknown;\n}>();\n\nconst rootClasses = computed(() => [\n 'tree-form-field',\n `tree-form-field--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': hasError.value,\n 'is-required': props.required,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst fieldAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <div\n v-bind=\"fieldAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <label\n v-if=\"label || $slots.label\"\n class=\"tree-form-field__label\"\n :for=\"htmlFor\"\n >\n <slot name=\"label\">{{ label }}</slot>\n <span\n v-if=\"required\"\n class=\"tree-form-field__required\"\n aria-hidden=\"true\"\n >*</span>\n </label>\n\n <div class=\"tree-form-field__control\">\n <slot />\n </div>\n\n <p\n v-if=\"hasError\"\n class=\"tree-form-field__error\"\n role=\"alert\"\n >\n <slot name=\"error\">\n {{ error }}\n </slot>\n </p>\n\n <p\n v-else-if=\"hint || $slots.hint\"\n class=\"tree-form-field__hint\"\n >\n <slot name=\"hint\">\n {{ hint }}\n </slot>\n </p>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n /** Current active page (1-based) */\n modelValue?: number;\n /** Total number of pages */\n totalPages: number;\n /** Number of sibling pages shown around the current page */\n siblings?: number;\n /** Size variant */\n size?: TreeSize;\n /** Disable all controls */\n disabled?: boolean;\n /** Accessible label for the nav element */\n label?: string;\n }>(),\n {\n modelValue: 1,\n siblings: 1,\n size: 'md',\n disabled: false,\n label: 'Pagination',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [page: number];\n}>();\n\ndefineSlots<{\n previous?: (props: Record<string, never>) => unknown;\n next?: (props: Record<string, never>) => unknown;\n}>();\n\nconst currentPage = computed(() =>\n Math.min(Math.max(1, props.modelValue), props.totalPages),\n);\n\nconst pages = computed(() => {\n const total = props.totalPages;\n const current = currentPage.value;\n const siblings = props.siblings;\n const items: (number | 'ellipsis')[] = [];\n\n const rangeStart = Math.max(2, current - siblings);\n const rangeEnd = Math.min(total - 1, current + siblings);\n\n // Always show page 1\n items.push(1);\n\n // Leading ellipsis\n if (rangeStart > 2) {\n items.push('ellipsis');\n }\n\n // Sibling pages\n for (let i = rangeStart; i <= rangeEnd; i++) {\n items.push(i);\n }\n\n // Trailing ellipsis\n if (rangeEnd < total - 1) {\n items.push('ellipsis');\n }\n\n // Always show last page (if more than 1 page)\n if (total > 1) {\n items.push(total);\n }\n\n return items;\n});\n\nconst classes = computed(() => [\n 'tree-pagination',\n `tree-pagination--${props.size}`,\n { 'is-disabled': props.disabled },\n]);\n\nfunction goToPage(page: number) {\n if (props.disabled) return;\n const clamped = Math.min(Math.max(1, page), props.totalPages);\n if (clamped !== currentPage.value) {\n emit('update:modelValue', clamped);\n }\n}\n\nfunction onKeydown(event: KeyboardEvent, page: number) {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n goToPage(page);\n }\n}\n</script>\n\n<template>\n <nav\n :class=\"classes\"\n :aria-label=\"label\"\n >\n <ul class=\"tree-pagination__list\">\n <!-- Previous button -->\n <li class=\"tree-pagination__item\">\n <button\n class=\"tree-pagination__button tree-pagination__button--prev\"\n type=\"button\"\n :disabled=\"disabled || currentPage <= 1\"\n :aria-label=\"'Go to previous page'\"\n @click=\"goToPage(currentPage - 1)\"\n >\n <slot name=\"previous\">\n <svg\n class=\"tree-pagination__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M10 12L6 8l4-4\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>\n </button>\n </li>\n\n <!-- Page items -->\n <li\n v-for=\"(page, index) in pages\"\n :key=\"page === 'ellipsis' ? `ellipsis-${index}` : page\"\n class=\"tree-pagination__item\"\n >\n <span\n v-if=\"page === 'ellipsis'\"\n class=\"tree-pagination__ellipsis\"\n aria-hidden=\"true\"\n >\n &hellip;\n </span>\n <button\n v-else\n class=\"tree-pagination__button\"\n :class=\"{ 'is-active': page === currentPage }\"\n type=\"button\"\n :disabled=\"disabled\"\n :aria-label=\"`Go to page ${page}`\"\n :aria-current=\"page === currentPage ? 'page' : undefined\"\n @click=\"goToPage(page)\"\n @keydown=\"onKeydown($event, page)\"\n >\n {{ page }}\n </button>\n </li>\n\n <!-- Next button -->\n <li class=\"tree-pagination__item\">\n <button\n class=\"tree-pagination__button tree-pagination__button--next\"\n type=\"button\"\n :disabled=\"disabled || currentPage >= totalPages\"\n :aria-label=\"'Go to next page'\"\n @click=\"goToPage(currentPage + 1)\"\n >\n <slot name=\"next\">\n <svg\n class=\"tree-pagination__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>\n </button>\n </li>\n </ul>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n /** Current active page (1-based) */\n modelValue?: number;\n /** Total number of pages */\n totalPages: number;\n /** Number of sibling pages shown around the current page */\n siblings?: number;\n /** Size variant */\n size?: TreeSize;\n /** Disable all controls */\n disabled?: boolean;\n /** Accessible label for the nav element */\n label?: string;\n }>(),\n {\n modelValue: 1,\n siblings: 1,\n size: 'md',\n disabled: false,\n label: 'Pagination',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [page: number];\n}>();\n\ndefineSlots<{\n previous?: (props: Record<string, never>) => unknown;\n next?: (props: Record<string, never>) => unknown;\n}>();\n\nconst currentPage = computed(() =>\n Math.min(Math.max(1, props.modelValue), props.totalPages),\n);\n\nconst pages = computed(() => {\n const total = props.totalPages;\n const current = currentPage.value;\n const siblings = props.siblings;\n const items: (number | 'ellipsis')[] = [];\n\n const rangeStart = Math.max(2, current - siblings);\n const rangeEnd = Math.min(total - 1, current + siblings);\n\n // Always show page 1\n items.push(1);\n\n // Leading ellipsis\n if (rangeStart > 2) {\n items.push('ellipsis');\n }\n\n // Sibling pages\n for (let i = rangeStart; i <= rangeEnd; i++) {\n items.push(i);\n }\n\n // Trailing ellipsis\n if (rangeEnd < total - 1) {\n items.push('ellipsis');\n }\n\n // Always show last page (if more than 1 page)\n if (total > 1) {\n items.push(total);\n }\n\n return items;\n});\n\nconst classes = computed(() => [\n 'tree-pagination',\n `tree-pagination--${props.size}`,\n { 'is-disabled': props.disabled },\n]);\n\nfunction goToPage(page: number) {\n if (props.disabled) return;\n const clamped = Math.min(Math.max(1, page), props.totalPages);\n if (clamped !== currentPage.value) {\n emit('update:modelValue', clamped);\n }\n}\n\nfunction onKeydown(event: KeyboardEvent, page: number) {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n goToPage(page);\n }\n}\n</script>\n\n<template>\n <nav\n :class=\"classes\"\n :aria-label=\"label\"\n >\n <ul class=\"tree-pagination__list\">\n <!-- Previous button -->\n <li class=\"tree-pagination__item\">\n <button\n class=\"tree-pagination__button tree-pagination__button--prev\"\n type=\"button\"\n :disabled=\"disabled || currentPage <= 1\"\n :aria-label=\"'Go to previous page'\"\n @click=\"goToPage(currentPage - 1)\"\n >\n <slot name=\"previous\">\n <svg\n class=\"tree-pagination__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M10 12L6 8l4-4\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>\n </button>\n </li>\n\n <!-- Page items -->\n <li\n v-for=\"(page, index) in pages\"\n :key=\"page === 'ellipsis' ? `ellipsis-${index}` : page\"\n class=\"tree-pagination__item\"\n >\n <span\n v-if=\"page === 'ellipsis'\"\n class=\"tree-pagination__ellipsis\"\n aria-hidden=\"true\"\n >\n &hellip;\n </span>\n <button\n v-else\n class=\"tree-pagination__button\"\n :class=\"{ 'is-active': page === currentPage }\"\n type=\"button\"\n :disabled=\"disabled\"\n :aria-label=\"`Go to page ${page}`\"\n :aria-current=\"page === currentPage ? 'page' : undefined\"\n @click=\"goToPage(page)\"\n @keydown=\"onKeydown($event, page)\"\n >\n {{ page }}\n </button>\n </li>\n\n <!-- Next button -->\n <li class=\"tree-pagination__item\">\n <button\n class=\"tree-pagination__button tree-pagination__button--next\"\n type=\"button\"\n :disabled=\"disabled || currentPage >= totalPages\"\n :aria-label=\"'Go to next page'\"\n @click=\"goToPage(currentPage + 1)\"\n >\n <slot name=\"next\">\n <svg\n class=\"tree-pagination__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>\n </button>\n </li>\n </ul>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { createId, focusFirst, isEscapeKey } from '@treeui/utils';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeTooltipSide } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n side?: TreeTooltipSide;\n align?: 'start' | 'center' | 'end';\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n side: 'bottom',\n align: 'center',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n trigger(props: { isOpen: boolean }): unknown;\n default(): unknown;\n}>();\n\nconst attrs = useAttrs();\nconst contentId = props.id ?? createId('tree-popover');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst contentRef = ref<HTMLElement | null>(null);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-popover',\n {\n 'is-open': isOpen.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst contentClasses = computed(() => [\n 'tree-popover__content',\n `tree-popover__content--${props.side}`,\n `tree-popover__content--align-${props.align}`,\n]);\n\nconst openPopover = () => {\n if (props.disabled) return;\n setValue(true);\n nextTick(() => {\n if (contentRef.value) {\n if (!focusFirst(contentRef.value)) {\n contentRef.value.focus();\n }\n }\n });\n};\n\nconst closePopover = (restoreFocus = false) => {\n setValue(false);\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst togglePopover = () => {\n if (isOpen.value) {\n closePopover();\n } else {\n openPopover();\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closePopover();\n }\n};\n\nconst onContentKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closePopover(true);\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closePopover();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"tree-popover__anchor\"\n @click=\"togglePopover\"\n @keydown=\"onTriggerKeydown\"\n >\n <slot\n name=\"trigger\"\n :is-open=\"isOpen\"\n >\n <button\n ref=\"triggerRef\"\n type=\"button\"\n class=\"tree-popover__trigger\"\n :disabled=\"disabled\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"isOpen ? contentId : undefined\"\n aria-haspopup=\"dialog\"\n v-bind=\"triggerAttrs\"\n />\n </slot>\n </div>\n <transition name=\"tree-popover-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"contentId\"\n ref=\"contentRef\"\n role=\"dialog\"\n :class=\"contentClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n tabindex=\"-1\"\n @keydown=\"onContentKeydown\"\n >\n <slot />\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { createId, focusFirst, isEscapeKey } from '@treeui/utils';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TreeTooltipSide } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n side?: TreeTooltipSide;\n align?: 'start' | 'center' | 'end';\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n side: 'bottom',\n align: 'center',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n trigger(props: { isOpen: boolean }): unknown;\n default(): unknown;\n}>();\n\nconst attrs = useAttrs();\nconst contentId = props.id ?? createId('tree-popover');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst contentRef = ref<HTMLElement | null>(null);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 'tree-popover',\n {\n 'is-open': isOpen.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst contentClasses = computed(() => [\n 'tree-popover__content',\n `tree-popover__content--${props.side}`,\n `tree-popover__content--align-${props.align}`,\n]);\n\nconst openPopover = () => {\n if (props.disabled) return;\n setValue(true);\n nextTick(() => {\n if (contentRef.value) {\n if (!focusFirst(contentRef.value)) {\n contentRef.value.focus();\n }\n }\n });\n};\n\nconst closePopover = (restoreFocus = false) => {\n setValue(false);\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst togglePopover = () => {\n if (isOpen.value) {\n closePopover();\n } else {\n openPopover();\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closePopover();\n }\n};\n\nconst onContentKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closePopover(true);\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closePopover();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"tree-popover__anchor\"\n @click=\"togglePopover\"\n @keydown=\"onTriggerKeydown\"\n >\n <slot\n name=\"trigger\"\n :is-open=\"isOpen\"\n >\n <button\n ref=\"triggerRef\"\n type=\"button\"\n class=\"tree-popover__trigger\"\n :disabled=\"disabled\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"isOpen ? contentId : undefined\"\n aria-haspopup=\"dialog\"\n v-bind=\"triggerAttrs\"\n />\n </slot>\n </div>\n <transition name=\"tree-popover-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"contentId\"\n ref=\"contentRef\"\n role=\"dialog\"\n :class=\"contentClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n tabindex=\"-1\"\n @keydown=\"onContentKeydown\"\n >\n <slot />\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n /** Current progress value (0–100). Omit for indeterminate. */\n value?: number;\n /** Maximum value. Defaults to 100. */\n max?: number;\n /** Size variant */\n size?: TreeSize;\n /** Accessible label */\n label?: string;\n }>(),\n {\n value: undefined,\n max: 100,\n size: 'md',\n label: 'Progress',\n },\n);\n\nconst isIndeterminate = computed(() => props.value === undefined || props.value === null);\n\nconst percentage = computed(() => {\n if (isIndeterminate.value) return 0;\n return Math.min(100, Math.max(0, (props.value! / props.max) * 100));\n});\n\nconst classes = computed(() => [\n 'tree-progress',\n `tree-progress--${props.size}`,\n { 'tree-progress--indeterminate': isIndeterminate.value },\n]);\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"progressbar\"\n :aria-valuenow=\"isIndeterminate ? undefined : percentage\"\n :aria-valuemin=\"0\"\n :aria-valuemax=\"100\"\n :aria-label=\"label\"\n >\n <div class=\"tree-progress__track\">\n <div\n class=\"tree-progress__fill\"\n :style=\"isIndeterminate ? undefined : { width: `${percentage}%` }\"\n />\n </div>\n\n <span class=\"tree-visually-hidden\">{{ label }}</span>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n /** Current progress value (0–100). Omit for indeterminate. */\n value?: number;\n /** Maximum value. Defaults to 100. */\n max?: number;\n /** Size variant */\n size?: TreeSize;\n /** Accessible label */\n label?: string;\n }>(),\n {\n value: undefined,\n max: 100,\n size: 'md',\n label: 'Progress',\n },\n);\n\nconst isIndeterminate = computed(() => props.value === undefined || props.value === null);\n\nconst percentage = computed(() => {\n if (isIndeterminate.value) return 0;\n return Math.min(100, Math.max(0, (props.value! / props.max) * 100));\n});\n\nconst classes = computed(() => [\n 'tree-progress',\n `tree-progress--${props.size}`,\n { 'tree-progress--indeterminate': isIndeterminate.value },\n]);\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"progressbar\"\n :aria-valuenow=\"isIndeterminate ? undefined : percentage\"\n :aria-valuemin=\"0\"\n :aria-valuemax=\"100\"\n :aria-label=\"label\"\n >\n <div class=\"tree-progress__track\">\n <div\n class=\"tree-progress__fill\"\n :style=\"isIndeterminate ? undefined : { width: `${percentage}%` }\"\n />\n </div>\n\n <span class=\"tree-visually-hidden\">{{ label }}</span>\n </div>\n</template>\n","import type { InjectionKey, Ref } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nexport type TabsActivationMode = 'automatic' | 'manual';\n\nexport interface TabsContext {\n activeValue: Ref<string>;\n setActiveValue: (value: string) => void;\n size: Ref<TreeSize>;\n activationMode: Ref<TabsActivationMode>;\n disabled: Ref<boolean>;\n baseId: string;\n registerTab: (value: string) => void;\n unregisterTab: (value: string) => void;\n getTabValues: () => string[];\n isTabDisabled: (value: string) => boolean;\n setTabDisabled: (value: string, disabled: boolean) => void;\n}\n\nexport const TABS_INJECTION_KEY: InjectionKey<TabsContext> = Symbol('TreeTabs');\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { computed, provide, reactive, ref, toRef, watch } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport type { TabsActivationMode } from './tabs-context';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n size?: TreeSize;\n activationMode?: TabsActivationMode;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n size: 'md',\n activationMode: 'automatic',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst baseId = createId('tree-tabs');\nconst internalValue = ref(props.defaultValue);\nconst tabOrder = ref<string[]>([]);\nconst disabledTabs: Record<string, boolean> = reactive({});\n\nconst activeValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst setActiveValue = (value: string) => {\n if (value === activeValue.value) return;\n if (props.modelValue === undefined) {\n internalValue.value = value;\n }\n emit('update:modelValue', value);\n};\n\nconst registerTab = (value: string) => {\n if (!tabOrder.value.includes(value)) {\n tabOrder.value.push(value);\n }\n};\n\nconst unregisterTab = (value: string) => {\n const idx = tabOrder.value.indexOf(value);\n if (idx >= 0) tabOrder.value.splice(idx, 1);\n delete disabledTabs[value];\n};\n\nconst getTabValues = () => tabOrder.value;\n\nconst isTabDisabled = (value: string) => props.disabled || !!disabledTabs[value];\n\nconst setTabDisabled = (value: string, disabled: boolean) => {\n if (disabled) {\n disabledTabs[value] = true;\n } else {\n delete disabledTabs[value];\n }\n};\n\nwatch(\n () => props.modelValue,\n (val) => {\n if (val !== undefined) {\n internalValue.value = val;\n }\n },\n);\n\nprovide(TABS_INJECTION_KEY, {\n activeValue,\n setActiveValue,\n size: toRef(props, 'size'),\n activationMode: toRef(props, 'activationMode'),\n disabled: toRef(props, 'disabled'),\n baseId,\n registerTab,\n unregisterTab,\n getTabValues,\n isTabDisabled,\n setTabDisabled,\n});\n\nconst rootClasses = computed(() => [\n 'tree-tabs',\n `tree-tabs--${props.size}`,\n]);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { computed, provide, reactive, ref, toRef, watch } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport type { TabsActivationMode } from './tabs-context';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n size?: TreeSize;\n activationMode?: TabsActivationMode;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n size: 'md',\n activationMode: 'automatic',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst baseId = createId('tree-tabs');\nconst internalValue = ref(props.defaultValue);\nconst tabOrder = ref<string[]>([]);\nconst disabledTabs: Record<string, boolean> = reactive({});\n\nconst activeValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst setActiveValue = (value: string) => {\n if (value === activeValue.value) return;\n if (props.modelValue === undefined) {\n internalValue.value = value;\n }\n emit('update:modelValue', value);\n};\n\nconst registerTab = (value: string) => {\n if (!tabOrder.value.includes(value)) {\n tabOrder.value.push(value);\n }\n};\n\nconst unregisterTab = (value: string) => {\n const idx = tabOrder.value.indexOf(value);\n if (idx >= 0) tabOrder.value.splice(idx, 1);\n delete disabledTabs[value];\n};\n\nconst getTabValues = () => tabOrder.value;\n\nconst isTabDisabled = (value: string) => props.disabled || !!disabledTabs[value];\n\nconst setTabDisabled = (value: string, disabled: boolean) => {\n if (disabled) {\n disabledTabs[value] = true;\n } else {\n delete disabledTabs[value];\n }\n};\n\nwatch(\n () => props.modelValue,\n (val) => {\n if (val !== undefined) {\n internalValue.value = val;\n }\n },\n);\n\nprovide(TABS_INJECTION_KEY, {\n activeValue,\n setActiveValue,\n size: toRef(props, 'size'),\n activationMode: toRef(props, 'activationMode'),\n disabled: toRef(props, 'disabled'),\n baseId,\n registerTab,\n unregisterTab,\n getTabValues,\n isTabDisabled,\n setTabDisabled,\n});\n\nconst rootClasses = computed(() => [\n 'tree-tabs',\n `tree-tabs--${props.size}`,\n]);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { isActivationKey } from '@treeui/utils';\nimport { computed, inject, ref } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTabList must be used inside TTabs');\n}\n\nconst listRef = ref<HTMLElement | null>(null);\n\nconst getAllTabElements = (): HTMLElement[] => {\n if (!listRef.value) return [];\n return Array.from(\n listRef.value.querySelectorAll<HTMLElement>('[role=\"tab\"]'),\n );\n};\n\nconst getEnabledTabElements = (): HTMLElement[] => {\n return getAllTabElements().filter((el) => {\n const value = el.dataset.tabValue;\n return value ? !ctx.isTabDisabled(value) : false;\n });\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n\n const current = document.activeElement as HTMLElement;\n const currentIndex = tabs.indexOf(current);\n let nextIndex = currentIndex + direction;\n\n if (nextIndex < 0) nextIndex = tabs.length - 1;\n if (nextIndex >= tabs.length) nextIndex = 0;\n\n const nextTab = tabs[nextIndex];\n nextTab.focus();\n\n if (ctx.activationMode.value === 'automatic') {\n const value = nextTab.dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst focusFirst = () => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n tabs[0].focus();\n if (ctx.activationMode.value === 'automatic') {\n const value = tabs[0].dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst focusLast = () => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n const last = tabs[tabs.length - 1];\n last.focus();\n if (ctx.activationMode.value === 'automatic') {\n const value = last.dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n switch (event.key) {\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusFirst();\n break;\n case 'End':\n event.preventDefault();\n focusLast();\n break;\n default:\n if (ctx.activationMode.value === 'manual' && isActivationKey(event)) {\n event.preventDefault();\n const target = event.target as HTMLElement;\n const value = target.dataset?.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n break;\n }\n};\n\nconst classes = computed(() => [\n 'tree-tabs__list',\n]);\n</script>\n\n<template>\n <div\n ref=\"listRef\"\n role=\"tablist\"\n aria-orientation=\"horizontal\"\n :class=\"classes\"\n @keydown=\"onKeydown\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { isActivationKey } from '@treeui/utils';\nimport { computed, inject, ref } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTabList must be used inside TTabs');\n}\n\nconst listRef = ref<HTMLElement | null>(null);\n\nconst getAllTabElements = (): HTMLElement[] => {\n if (!listRef.value) return [];\n return Array.from(\n listRef.value.querySelectorAll<HTMLElement>('[role=\"tab\"]'),\n );\n};\n\nconst getEnabledTabElements = (): HTMLElement[] => {\n return getAllTabElements().filter((el) => {\n const value = el.dataset.tabValue;\n return value ? !ctx.isTabDisabled(value) : false;\n });\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n\n const current = document.activeElement as HTMLElement;\n const currentIndex = tabs.indexOf(current);\n let nextIndex = currentIndex + direction;\n\n if (nextIndex < 0) nextIndex = tabs.length - 1;\n if (nextIndex >= tabs.length) nextIndex = 0;\n\n const nextTab = tabs[nextIndex];\n nextTab.focus();\n\n if (ctx.activationMode.value === 'automatic') {\n const value = nextTab.dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst focusFirst = () => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n tabs[0].focus();\n if (ctx.activationMode.value === 'automatic') {\n const value = tabs[0].dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst focusLast = () => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n const last = tabs[tabs.length - 1];\n last.focus();\n if (ctx.activationMode.value === 'automatic') {\n const value = last.dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n switch (event.key) {\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusFirst();\n break;\n case 'End':\n event.preventDefault();\n focusLast();\n break;\n default:\n if (ctx.activationMode.value === 'manual' && isActivationKey(event)) {\n event.preventDefault();\n const target = event.target as HTMLElement;\n const value = target.dataset?.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n break;\n }\n};\n\nconst classes = computed(() => [\n 'tree-tabs__list',\n]);\n</script>\n\n<template>\n <div\n ref=\"listRef\"\n role=\"tablist\"\n aria-orientation=\"horizontal\"\n :class=\"classes\"\n @keydown=\"onKeydown\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onBeforeUnmount, onMounted, watch } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n }>(),\n {\n disabled: false,\n },\n);\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTab must be used inside TTabs');\n}\n\nonMounted(() => {\n ctx.registerTab(props.value);\n ctx.setTabDisabled(props.value, props.disabled);\n});\n\nwatch(\n () => props.disabled,\n (val) => ctx.setTabDisabled(props.value, val),\n);\n\nonBeforeUnmount(() => {\n ctx.unregisterTab(props.value);\n});\n\nconst isActive = computed(() => ctx.activeValue.value === props.value);\nconst isDisabled = computed(() => ctx.isTabDisabled(props.value));\nconst tabId = computed(() => `${ctx.baseId}-tab-${props.value}`);\nconst panelId = computed(() => `${ctx.baseId}-panel-${props.value}`);\n\nconst onClick = () => {\n if (isDisabled.value) return;\n ctx.setActiveValue(props.value);\n};\n\nconst classes = computed(() => [\n 'tree-tabs__tab',\n `tree-tabs__tab--${ctx.size.value}`,\n {\n 'is-active': isActive.value,\n 'is-disabled': isDisabled.value,\n },\n]);\n</script>\n\n<template>\n <button\n :id=\"tabId\"\n role=\"tab\"\n type=\"button\"\n :class=\"classes\"\n :aria-selected=\"isActive\"\n :aria-controls=\"panelId\"\n :tabindex=\"isActive ? 0 : -1\"\n :disabled=\"isDisabled || undefined\"\n :data-tab-value=\"value\"\n @click=\"onClick\"\n >\n <slot />\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onBeforeUnmount, onMounted, watch } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n }>(),\n {\n disabled: false,\n },\n);\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTab must be used inside TTabs');\n}\n\nonMounted(() => {\n ctx.registerTab(props.value);\n ctx.setTabDisabled(props.value, props.disabled);\n});\n\nwatch(\n () => props.disabled,\n (val) => ctx.setTabDisabled(props.value, val),\n);\n\nonBeforeUnmount(() => {\n ctx.unregisterTab(props.value);\n});\n\nconst isActive = computed(() => ctx.activeValue.value === props.value);\nconst isDisabled = computed(() => ctx.isTabDisabled(props.value));\nconst tabId = computed(() => `${ctx.baseId}-tab-${props.value}`);\nconst panelId = computed(() => `${ctx.baseId}-panel-${props.value}`);\n\nconst onClick = () => {\n if (isDisabled.value) return;\n ctx.setActiveValue(props.value);\n};\n\nconst classes = computed(() => [\n 'tree-tabs__tab',\n `tree-tabs__tab--${ctx.size.value}`,\n {\n 'is-active': isActive.value,\n 'is-disabled': isDisabled.value,\n },\n]);\n</script>\n\n<template>\n <button\n :id=\"tabId\"\n role=\"tab\"\n type=\"button\"\n :class=\"classes\"\n :aria-selected=\"isActive\"\n :aria-controls=\"panelId\"\n :tabindex=\"isActive ? 0 : -1\"\n :disabled=\"isDisabled || undefined\"\n :data-tab-value=\"value\"\n @click=\"onClick\"\n >\n <slot />\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = defineProps<{\n value: string;\n}>();\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTabPanel must be used inside TTabs');\n}\n\nconst isActive = computed(() => ctx.activeValue.value === props.value);\nconst panelId = computed(() => `${ctx.baseId}-panel-${props.value}`);\nconst tabId = computed(() => `${ctx.baseId}-tab-${props.value}`);\n</script>\n\n<template>\n <div\n v-if=\"isActive\"\n :id=\"panelId\"\n role=\"tabpanel\"\n :aria-labelledby=\"tabId\"\n tabindex=\"0\"\n class=\"tree-tabs__panel\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = defineProps<{\n value: string;\n}>();\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTabPanel must be used inside TTabs');\n}\n\nconst isActive = computed(() => ctx.activeValue.value === props.value);\nconst panelId = computed(() => `${ctx.baseId}-panel-${props.value}`);\nconst tabId = computed(() => `${ctx.baseId}-tab-${props.value}`);\n</script>\n\n<template>\n <div\n v-if=\"isActive\"\n :id=\"panelId\"\n role=\"tabpanel\"\n :aria-labelledby=\"tabId\"\n tabindex=\"0\"\n class=\"tree-tabs__panel\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport { computed } from 'vue';\nimport type { ToastItem } from '../composables/useToast';\n\nconst XIcon = getTreeIcon('x');\n\nconst iconMap = {\n info: getTreeIcon('info'),\n success: getTreeIcon('check'),\n warning: getTreeIcon('alert-circle'),\n danger: getTreeIcon('alert-circle'),\n} as const;\n\nconst props = withDefaults(\n defineProps<{\n toast: ToastItem;\n }>(),\n {},\n);\n\nconst emit = defineEmits<{\n close: [id: string];\n}>();\n\nconst toastId = createId('tree-toast-item');\nconst titleId = `${toastId}-title`;\nconst descriptionId = `${toastId}-description`;\n\nconst classes = computed(() => [\n 'tree-toast',\n `tree-toast--${props.toast.variant}`,\n]);\n\nconst StatusIcon = computed(() => iconMap[props.toast.variant]);\n\nfunction handleClose() {\n emit('close', props.toast.id);\n}\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"status\"\n :aria-labelledby=\"titleId\"\n :aria-describedby=\"toast.description ? descriptionId : undefined\"\n >\n <span\n class=\"tree-toast__icon\"\n aria-hidden=\"true\"\n >\n <StatusIcon\n v-bind=\"treeIconDefaults\"\n :size=\"18\"\n />\n </span>\n <div class=\"tree-toast__content\">\n <p\n :id=\"titleId\"\n class=\"tree-toast__title\"\n >\n {{ toast.title }}\n </p>\n <p\n v-if=\"toast.description\"\n :id=\"descriptionId\"\n class=\"tree-toast__description\"\n >\n {{ toast.description }}\n </p>\n </div>\n <button\n v-if=\"toast.closable\"\n type=\"button\"\n class=\"tree-toast__close\"\n aria-label=\"Dismiss notification\"\n @click=\"handleClose\"\n >\n <XIcon\n v-bind=\"treeIconDefaults\"\n :size=\"16\"\n />\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport { computed } from 'vue';\nimport type { ToastItem } from '../composables/useToast';\n\nconst XIcon = getTreeIcon('x');\n\nconst iconMap = {\n info: getTreeIcon('info'),\n success: getTreeIcon('check'),\n warning: getTreeIcon('alert-circle'),\n danger: getTreeIcon('alert-circle'),\n} as const;\n\nconst props = withDefaults(\n defineProps<{\n toast: ToastItem;\n }>(),\n {},\n);\n\nconst emit = defineEmits<{\n close: [id: string];\n}>();\n\nconst toastId = createId('tree-toast-item');\nconst titleId = `${toastId}-title`;\nconst descriptionId = `${toastId}-description`;\n\nconst classes = computed(() => [\n 'tree-toast',\n `tree-toast--${props.toast.variant}`,\n]);\n\nconst StatusIcon = computed(() => iconMap[props.toast.variant]);\n\nfunction handleClose() {\n emit('close', props.toast.id);\n}\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"status\"\n :aria-labelledby=\"titleId\"\n :aria-describedby=\"toast.description ? descriptionId : undefined\"\n >\n <span\n class=\"tree-toast__icon\"\n aria-hidden=\"true\"\n >\n <StatusIcon\n v-bind=\"treeIconDefaults\"\n :size=\"18\"\n />\n </span>\n <div class=\"tree-toast__content\">\n <p\n :id=\"titleId\"\n class=\"tree-toast__title\"\n >\n {{ toast.title }}\n </p>\n <p\n v-if=\"toast.description\"\n :id=\"descriptionId\"\n class=\"tree-toast__description\"\n >\n {{ toast.description }}\n </p>\n </div>\n <button\n v-if=\"toast.closable\"\n type=\"button\"\n class=\"tree-toast__close\"\n aria-label=\"Dismiss notification\"\n @click=\"handleClose\"\n >\n <XIcon\n v-bind=\"treeIconDefaults\"\n :size=\"16\"\n />\n </button>\n </div>\n</template>\n","import { readonly, ref } from 'vue';\nimport { createId } from '@treeui/utils';\n\nexport type ToastVariant = 'info' | 'success' | 'warning' | 'danger';\n\nexport type ToastPosition =\n | 'top-right'\n | 'top-left'\n | 'bottom-right'\n | 'bottom-left'\n | 'top-center'\n | 'bottom-center';\n\nexport interface ToastOptions {\n title: string;\n description?: string;\n variant?: ToastVariant;\n duration?: number;\n closable?: boolean;\n}\n\nexport interface ToastItem extends Required<Pick<ToastOptions, 'title' | 'variant' | 'duration' | 'closable'>> {\n id: string;\n description?: string;\n}\n\nconst toasts = ref<ToastItem[]>([]);\nconst timers = new Map<string, ReturnType<typeof setTimeout>>();\n\nfunction add(options: ToastOptions): string {\n const id = createId('tree-toast');\n\n const item: ToastItem = {\n id,\n title: options.title,\n description: options.description,\n variant: options.variant ?? 'info',\n duration: options.duration ?? 5000,\n closable: options.closable ?? true,\n };\n\n toasts.value = [...toasts.value, item];\n\n if (item.duration > 0) {\n const timer = setTimeout(() => {\n remove(id);\n }, item.duration);\n timers.set(id, timer);\n }\n\n return id;\n}\n\nfunction remove(id: string) {\n const timer = timers.get(id);\n\n if (timer) {\n clearTimeout(timer);\n timers.delete(id);\n }\n\n toasts.value = toasts.value.filter((t) => t.id !== id);\n}\n\nfunction clear() {\n for (const timer of timers.values()) {\n clearTimeout(timer);\n }\n\n timers.clear();\n toasts.value = [];\n}\n\nexport function useToast() {\n return {\n toasts: readonly(toasts),\n add,\n remove,\n clear,\n };\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { useToast, type ToastPosition } from '../composables/useToast';\nimport TreeToast from './TreeToast.vue';\n\nconst props = withDefaults(\n defineProps<{\n position?: ToastPosition;\n max?: number;\n }>(),\n {\n position: 'bottom-right',\n max: 5,\n },\n);\n\nconst { toasts, remove } = useToast();\n\nconst visibleToasts = computed(() =>\n toasts.value.slice(-props.max),\n);\n\nconst classes = computed(() => [\n 'tree-toast-provider',\n `tree-toast-provider--${props.position}`,\n]);\n\nfunction handleClose(id: string) {\n remove(id);\n}\n</script>\n\n<template>\n <slot />\n\n <Teleport to=\"body\">\n <div\n :class=\"classes\"\n aria-live=\"polite\"\n aria-relevant=\"additions removals\"\n >\n <TransitionGroup name=\"tree-toast\">\n <TreeToast\n v-for=\"toast in visibleToasts\"\n :key=\"toast.id\"\n :toast=\"toast\"\n @close=\"handleClose\"\n />\n </TransitionGroup>\n </div>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { useToast, type ToastPosition } from '../composables/useToast';\nimport TreeToast from './TreeToast.vue';\n\nconst props = withDefaults(\n defineProps<{\n position?: ToastPosition;\n max?: number;\n }>(),\n {\n position: 'bottom-right',\n max: 5,\n },\n);\n\nconst { toasts, remove } = useToast();\n\nconst visibleToasts = computed(() =>\n toasts.value.slice(-props.max),\n);\n\nconst classes = computed(() => [\n 'tree-toast-provider',\n `tree-toast-provider--${props.position}`,\n]);\n\nfunction handleClose(id: string) {\n remove(id);\n}\n</script>\n\n<template>\n <slot />\n\n <Teleport to=\"body\">\n <div\n :class=\"classes\"\n aria-live=\"polite\"\n aria-relevant=\"additions removals\"\n >\n <TransitionGroup name=\"tree-toast\">\n <TreeToast\n v-for=\"toast in visibleToasts\"\n :key=\"toast.id\"\n :toast=\"toast\"\n @close=\"handleClose\"\n />\n </TransitionGroup>\n </div>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nexport type TreeAvatarStatus = 'online' | 'offline' | 'busy' | 'away';\n\nconst props = withDefaults(\n defineProps<{\n src?: string;\n alt?: string;\n initials?: string;\n size?: TreeSize;\n status?: TreeAvatarStatus;\n }>(),\n {\n src: undefined,\n alt: '',\n initials: undefined,\n size: 'md',\n status: undefined,\n },\n);\n\nconst classes = computed(() => [\n 'tree-avatar',\n `tree-avatar--${props.size}`,\n]);\n\nconst computedInitials = computed(() => {\n if (props.initials) return props.initials;\n if (props.alt) {\n return props.alt\n .split(' ')\n .filter(Boolean)\n .map((w) => w[0])\n .slice(0, 2)\n .join('')\n .toUpperCase();\n }\n return '';\n});\n\nfunction onImgError(event: Event) {\n const target = event.target as HTMLImageElement;\n target.style.display = 'none';\n}\n</script>\n\n<template>\n <span\n :class=\"classes\"\n role=\"img\"\n :aria-label=\"alt || undefined\"\n >\n <img\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt\"\n class=\"tree-avatar__image\"\n @error=\"onImgError\"\n >\n <span\n v-else\n class=\"tree-avatar__initials\"\n aria-hidden=\"true\"\n >\n {{ computedInitials }}\n </span>\n <slot />\n <span\n v-if=\"status\"\n class=\"tree-avatar__status\"\n :class=\"`tree-avatar__status--${status}`\"\n :aria-label=\"status\"\n />\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nexport type TreeAvatarStatus = 'online' | 'offline' | 'busy' | 'away';\n\nconst props = withDefaults(\n defineProps<{\n src?: string;\n alt?: string;\n initials?: string;\n size?: TreeSize;\n status?: TreeAvatarStatus;\n }>(),\n {\n src: undefined,\n alt: '',\n initials: undefined,\n size: 'md',\n status: undefined,\n },\n);\n\nconst classes = computed(() => [\n 'tree-avatar',\n `tree-avatar--${props.size}`,\n]);\n\nconst computedInitials = computed(() => {\n if (props.initials) return props.initials;\n if (props.alt) {\n return props.alt\n .split(' ')\n .filter(Boolean)\n .map((w) => w[0])\n .slice(0, 2)\n .join('')\n .toUpperCase();\n }\n return '';\n});\n\nfunction onImgError(event: Event) {\n const target = event.target as HTMLImageElement;\n target.style.display = 'none';\n}\n</script>\n\n<template>\n <span\n :class=\"classes\"\n role=\"img\"\n :aria-label=\"alt || undefined\"\n >\n <img\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt\"\n class=\"tree-avatar__image\"\n @error=\"onImgError\"\n >\n <span\n v-else\n class=\"tree-avatar__initials\"\n aria-hidden=\"true\"\n >\n {{ computedInitials }}\n </span>\n <slot />\n <span\n v-if=\"status\"\n class=\"tree-avatar__status\"\n :class=\"`tree-avatar__status--${status}`\"\n :aria-label=\"status\"\n />\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n orientation?: 'horizontal' | 'vertical';\n decorative?: boolean;\n label?: string;\n }>(),\n {\n orientation: 'horizontal',\n decorative: true,\n label: undefined,\n },\n);\n\nconst classes = computed(() => [\n 'tree-divider',\n `tree-divider--${props.orientation}`,\n]);\n</script>\n\n<template>\n <hr\n :class=\"classes\"\n :role=\"decorative ? 'none' : 'separator'\"\n :aria-orientation=\"!decorative ? orientation : undefined\"\n :aria-label=\"!decorative ? label : undefined\"\n >\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n orientation?: 'horizontal' | 'vertical';\n decorative?: boolean;\n label?: string;\n }>(),\n {\n orientation: 'horizontal',\n decorative: true,\n label: undefined,\n },\n);\n\nconst classes = computed(() => [\n 'tree-divider',\n `tree-divider--${props.orientation}`,\n]);\n</script>\n\n<template>\n <hr\n :class=\"classes\"\n :role=\"decorative ? 'none' : 'separator'\"\n :aria-orientation=\"!decorative ? orientation : undefined\"\n :aria-label=\"!decorative ? label : undefined\"\n >\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nexport type TreeTableColumn = {\n key: string;\n label: string;\n sortable?: boolean;\n align?: 'left' | 'center' | 'right';\n width?: string;\n};\n\nexport type TreeTableSortDirection = 'asc' | 'desc' | 'none';\n\nexport type TreeTableSortState = {\n key: string;\n direction: TreeTableSortDirection;\n};\n\nconst props = withDefaults(\n defineProps<{\n columns: TreeTableColumn[];\n rows: Record<string, unknown>[];\n size?: TreeSize;\n sortBy?: TreeTableSortState;\n }>(),\n {\n size: 'md',\n sortBy: undefined,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'sort', state: TreeTableSortState): void;\n}>();\n\ndefineSlots<{\n [key: `cell-${string}`]: (props: { row: Record<string, unknown>; value: unknown }) => void;\n [key: `header-${string}`]: (props: { column: TreeTableColumn }) => void;\n empty: () => void;\n}>();\n\nconst internalSort = ref<TreeTableSortState | undefined>(undefined);\n\nconst currentSort = computed(() => props.sortBy ?? internalSort.value);\n\nconst classes = computed(() => [\n 'tree-table',\n `tree-table--${props.size}`,\n]);\n\nconst sortedRows = computed(() => {\n const sort = currentSort.value;\n if (!sort || sort.direction === 'none') return props.rows;\n\n return [...props.rows].sort((a, b) => {\n const aVal = a[sort.key];\n const bVal = b[sort.key];\n\n if (aVal == null && bVal == null) return 0;\n if (aVal == null) return 1;\n if (bVal == null) return -1;\n\n const cmp =\n typeof aVal === 'number' && typeof bVal === 'number'\n ? aVal - bVal\n : String(aVal).localeCompare(String(bVal));\n\n return sort.direction === 'desc' ? -cmp : cmp;\n });\n});\n\nfunction handleSort(column: TreeTableColumn) {\n if (!column.sortable) return;\n\n const cur = currentSort.value;\n let direction: TreeTableSortDirection = 'asc';\n\n if (cur?.key === column.key) {\n if (cur.direction === 'asc') direction = 'desc';\n else if (cur.direction === 'desc') direction = 'none';\n else direction = 'asc';\n }\n\n const state: TreeTableSortState = { key: column.key, direction };\n internalSort.value = state;\n emit('sort', state);\n}\n\nfunction sortAriaSort(column: TreeTableColumn): 'none' | 'ascending' | 'descending' | undefined {\n if (!column.sortable) return undefined;\n const cur = currentSort.value;\n if (cur?.key !== column.key || cur.direction === 'none') return 'none';\n return cur.direction === 'asc' ? 'ascending' : 'descending';\n}\n\nfunction handleHeaderKeydown(event: KeyboardEvent, column: TreeTableColumn) {\n if (column.sortable && (event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n handleSort(column);\n }\n}\n</script>\n\n<template>\n <div class=\"tree-table-wrapper\">\n <table\n :class=\"classes\"\n role=\"grid\"\n >\n <thead class=\"tree-table__head\">\n <tr class=\"tree-table__row\">\n <th\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"tree-table__header\"\n :class=\"[\n column.sortable ? 'tree-table__header--sortable' : '',\n column.align ? `tree-table__header--${column.align}` : '',\n ]\"\n :style=\"column.width ? { width: column.width } : undefined\"\n :aria-sort=\"sortAriaSort(column)\"\n :tabindex=\"column.sortable ? 0 : undefined\"\n scope=\"col\"\n @click=\"handleSort(column)\"\n @keydown=\"handleHeaderKeydown($event, column)\"\n >\n <slot\n :name=\"`header-${column.key}`\"\n :column=\"column\"\n >\n <span class=\"tree-table__header-content\">\n {{ column.label }}\n <span\n v-if=\"column.sortable\"\n class=\"tree-table__sort-icon\"\n aria-hidden=\"true\"\n >\n <svg\n v-if=\"currentSort?.key === column.key && currentSort.direction === 'asc'\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n <svg\n v-else-if=\"currentSort?.key === column.key && currentSort.direction === 'desc'\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n <svg\n v-else\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n style=\"opacity: 0.4\"\n >\n <path d=\"m7 15 5 5 5-5\" />\n <path d=\"m7 9 5-5 5 5\" />\n </svg>\n </span>\n </span>\n </slot>\n </th>\n </tr>\n </thead>\n <tbody class=\"tree-table__body\">\n <tr\n v-if=\"sortedRows.length === 0\"\n class=\"tree-table__row tree-table__row--empty\"\n >\n <td\n :colspan=\"columns.length\"\n class=\"tree-table__cell tree-table__cell--empty\"\n >\n <slot name=\"empty\">\n No data available.\n </slot>\n </td>\n </tr>\n <tr\n v-for=\"(row, index) in sortedRows\"\n :key=\"index\"\n class=\"tree-table__row\"\n >\n <td\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"tree-table__cell\"\n :class=\"column.align ? `tree-table__cell--${column.align}` : ''\"\n >\n <slot\n :name=\"`cell-${column.key}`\"\n :row=\"row\"\n :value=\"row[column.key]\"\n >\n {{ row[column.key] ?? '' }}\n </slot>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nexport type TreeTableColumn = {\n key: string;\n label: string;\n sortable?: boolean;\n align?: 'left' | 'center' | 'right';\n width?: string;\n};\n\nexport type TreeTableSortDirection = 'asc' | 'desc' | 'none';\n\nexport type TreeTableSortState = {\n key: string;\n direction: TreeTableSortDirection;\n};\n\nconst props = withDefaults(\n defineProps<{\n columns: TreeTableColumn[];\n rows: Record<string, unknown>[];\n size?: TreeSize;\n sortBy?: TreeTableSortState;\n }>(),\n {\n size: 'md',\n sortBy: undefined,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'sort', state: TreeTableSortState): void;\n}>();\n\ndefineSlots<{\n [key: `cell-${string}`]: (props: { row: Record<string, unknown>; value: unknown }) => void;\n [key: `header-${string}`]: (props: { column: TreeTableColumn }) => void;\n empty: () => void;\n}>();\n\nconst internalSort = ref<TreeTableSortState | undefined>(undefined);\n\nconst currentSort = computed(() => props.sortBy ?? internalSort.value);\n\nconst classes = computed(() => [\n 'tree-table',\n `tree-table--${props.size}`,\n]);\n\nconst sortedRows = computed(() => {\n const sort = currentSort.value;\n if (!sort || sort.direction === 'none') return props.rows;\n\n return [...props.rows].sort((a, b) => {\n const aVal = a[sort.key];\n const bVal = b[sort.key];\n\n if (aVal == null && bVal == null) return 0;\n if (aVal == null) return 1;\n if (bVal == null) return -1;\n\n const cmp =\n typeof aVal === 'number' && typeof bVal === 'number'\n ? aVal - bVal\n : String(aVal).localeCompare(String(bVal));\n\n return sort.direction === 'desc' ? -cmp : cmp;\n });\n});\n\nfunction handleSort(column: TreeTableColumn) {\n if (!column.sortable) return;\n\n const cur = currentSort.value;\n let direction: TreeTableSortDirection = 'asc';\n\n if (cur?.key === column.key) {\n if (cur.direction === 'asc') direction = 'desc';\n else if (cur.direction === 'desc') direction = 'none';\n else direction = 'asc';\n }\n\n const state: TreeTableSortState = { key: column.key, direction };\n internalSort.value = state;\n emit('sort', state);\n}\n\nfunction sortAriaSort(column: TreeTableColumn): 'none' | 'ascending' | 'descending' | undefined {\n if (!column.sortable) return undefined;\n const cur = currentSort.value;\n if (cur?.key !== column.key || cur.direction === 'none') return 'none';\n return cur.direction === 'asc' ? 'ascending' : 'descending';\n}\n\nfunction handleHeaderKeydown(event: KeyboardEvent, column: TreeTableColumn) {\n if (column.sortable && (event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n handleSort(column);\n }\n}\n</script>\n\n<template>\n <div class=\"tree-table-wrapper\">\n <table\n :class=\"classes\"\n role=\"grid\"\n >\n <thead class=\"tree-table__head\">\n <tr class=\"tree-table__row\">\n <th\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"tree-table__header\"\n :class=\"[\n column.sortable ? 'tree-table__header--sortable' : '',\n column.align ? `tree-table__header--${column.align}` : '',\n ]\"\n :style=\"column.width ? { width: column.width } : undefined\"\n :aria-sort=\"sortAriaSort(column)\"\n :tabindex=\"column.sortable ? 0 : undefined\"\n scope=\"col\"\n @click=\"handleSort(column)\"\n @keydown=\"handleHeaderKeydown($event, column)\"\n >\n <slot\n :name=\"`header-${column.key}`\"\n :column=\"column\"\n >\n <span class=\"tree-table__header-content\">\n {{ column.label }}\n <span\n v-if=\"column.sortable\"\n class=\"tree-table__sort-icon\"\n aria-hidden=\"true\"\n >\n <svg\n v-if=\"currentSort?.key === column.key && currentSort.direction === 'asc'\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n <svg\n v-else-if=\"currentSort?.key === column.key && currentSort.direction === 'desc'\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n <svg\n v-else\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n style=\"opacity: 0.4\"\n >\n <path d=\"m7 15 5 5 5-5\" />\n <path d=\"m7 9 5-5 5 5\" />\n </svg>\n </span>\n </span>\n </slot>\n </th>\n </tr>\n </thead>\n <tbody class=\"tree-table__body\">\n <tr\n v-if=\"sortedRows.length === 0\"\n class=\"tree-table__row tree-table__row--empty\"\n >\n <td\n :colspan=\"columns.length\"\n class=\"tree-table__cell tree-table__cell--empty\"\n >\n <slot name=\"empty\">\n No data available.\n </slot>\n </td>\n </tr>\n <tr\n v-for=\"(row, index) in sortedRows\"\n :key=\"index\"\n class=\"tree-table__row\"\n >\n <td\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"tree-table__cell\"\n :class=\"column.align ? `tree-table__cell--${column.align}` : ''\"\n >\n <slot\n :name=\"`cell-${column.key}`\"\n :row=\"row\"\n :value=\"row[column.key]\"\n >\n {{ row[column.key] ?? '' }}\n </slot>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nexport type TreeTagVariant = 'solid' | 'outline' | 'soft';\n\nconst props = withDefaults(\n defineProps<{\n variant?: TreeTagVariant;\n size?: TreeSize;\n removable?: boolean;\n disabled?: boolean;\n }>(),\n {\n variant: 'soft',\n size: 'md',\n removable: false,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'remove'): void;\n}>();\n\nconst classes = computed(() => [\n 'tree-tag',\n `tree-tag--${props.variant}`,\n `tree-tag--${props.size}`,\n props.disabled ? 'is-disabled' : '',\n]);\n\nfunction handleRemove() {\n if (props.disabled) return;\n emit('remove');\n}\n</script>\n\n<template>\n <span :class=\"classes\">\n <span\n v-if=\"$slots.icon\"\n class=\"tree-tag__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span class=\"tree-tag__label\">\n <slot />\n </span>\n <button\n v-if=\"removable\"\n type=\"button\"\n class=\"tree-tag__remove\"\n :disabled=\"disabled\"\n aria-label=\"Remove\"\n @click=\"handleRemove\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\nexport type TreeTagVariant = 'solid' | 'outline' | 'soft';\n\nconst props = withDefaults(\n defineProps<{\n variant?: TreeTagVariant;\n size?: TreeSize;\n removable?: boolean;\n disabled?: boolean;\n }>(),\n {\n variant: 'soft',\n size: 'md',\n removable: false,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'remove'): void;\n}>();\n\nconst classes = computed(() => [\n 'tree-tag',\n `tree-tag--${props.variant}`,\n `tree-tag--${props.size}`,\n props.disabled ? 'is-disabled' : '',\n]);\n\nfunction handleRemove() {\n if (props.disabled) return;\n emit('remove');\n}\n</script>\n\n<template>\n <span :class=\"classes\">\n <span\n v-if=\"$slots.icon\"\n class=\"tree-tag__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span class=\"tree-tag__label\">\n <slot />\n </span>\n <button\n v-if=\"removable\"\n type=\"button\"\n class=\"tree-tag__remove\"\n :disabled=\"disabled\"\n aria-label=\"Remove\"\n @click=\"handleRemove\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport type TreeTimelineTone = 'neutral' | 'brand' | 'success' | 'warning' | 'danger';\n\nexport interface TreeTimelineItem {\n id?: string | number;\n title: string;\n description?: string;\n meta?: string;\n timestamp?: string;\n datetime?: string;\n tone?: TreeTimelineTone;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TreeTimelineItem[];\n size?: TreeSize;\n }>(),\n {\n items: () => [],\n size: 'md',\n },\n);\n\ndefineSlots<{\n marker?: (props: { item: TreeTimelineItem; index: number }) => unknown;\n item?: (props: { item: TreeTimelineItem; index: number }) => unknown;\n}>();\n\nconst attrs = useAttrs();\n\nconst classes = computed(() => [\n 'tree-timeline',\n `tree-timeline--${props.size}`,\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst normalizeTone = (tone?: TreeTimelineTone) => tone ?? 'neutral';\nconst itemKey = (item: TreeTimelineItem, index: number) => item.id ?? `${item.title}-${index}`;\n</script>\n\n<template>\n <ol\n v-bind=\"rootAttrs\"\n :class=\"classes\"\n :style=\"rootStyle\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"itemKey(item, index)\"\n class=\"tree-timeline__item\"\n >\n <div class=\"tree-timeline__rail\">\n <span\n v-if=\"index < items.length - 1\"\n class=\"tree-timeline__line\"\n aria-hidden=\"true\"\n />\n <div\n class=\"tree-timeline__marker\"\n :class=\"`tree-timeline__marker--${normalizeTone(item.tone)}`\"\n aria-hidden=\"true\"\n >\n <slot\n name=\"marker\"\n :item=\"item\"\n :index=\"index\"\n />\n </div>\n </div>\n\n <div class=\"tree-timeline__content\">\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n <div\n v-if=\"item.meta\"\n class=\"tree-timeline__meta\"\n >\n {{ item.meta }}\n </div>\n\n <div class=\"tree-timeline__header\">\n <p class=\"tree-timeline__title\">\n {{ item.title }}\n </p>\n <time\n v-if=\"item.timestamp\"\n class=\"tree-timeline__timestamp\"\n :datetime=\"item.datetime || undefined\"\n >\n {{ item.timestamp }}\n </time>\n </div>\n\n <p\n v-if=\"item.description\"\n class=\"tree-timeline__description\"\n >\n {{ item.description }}\n </p>\n </slot>\n </div>\n </li>\n </ol>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport type TreeTimelineTone = 'neutral' | 'brand' | 'success' | 'warning' | 'danger';\n\nexport interface TreeTimelineItem {\n id?: string | number;\n title: string;\n description?: string;\n meta?: string;\n timestamp?: string;\n datetime?: string;\n tone?: TreeTimelineTone;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TreeTimelineItem[];\n size?: TreeSize;\n }>(),\n {\n items: () => [],\n size: 'md',\n },\n);\n\ndefineSlots<{\n marker?: (props: { item: TreeTimelineItem; index: number }) => unknown;\n item?: (props: { item: TreeTimelineItem; index: number }) => unknown;\n}>();\n\nconst attrs = useAttrs();\n\nconst classes = computed(() => [\n 'tree-timeline',\n `tree-timeline--${props.size}`,\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst normalizeTone = (tone?: TreeTimelineTone) => tone ?? 'neutral';\nconst itemKey = (item: TreeTimelineItem, index: number) => item.id ?? `${item.title}-${index}`;\n</script>\n\n<template>\n <ol\n v-bind=\"rootAttrs\"\n :class=\"classes\"\n :style=\"rootStyle\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"itemKey(item, index)\"\n class=\"tree-timeline__item\"\n >\n <div class=\"tree-timeline__rail\">\n <span\n v-if=\"index < items.length - 1\"\n class=\"tree-timeline__line\"\n aria-hidden=\"true\"\n />\n <div\n class=\"tree-timeline__marker\"\n :class=\"`tree-timeline__marker--${normalizeTone(item.tone)}`\"\n aria-hidden=\"true\"\n >\n <slot\n name=\"marker\"\n :item=\"item\"\n :index=\"index\"\n />\n </div>\n </div>\n\n <div class=\"tree-timeline__content\">\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n <div\n v-if=\"item.meta\"\n class=\"tree-timeline__meta\"\n >\n {{ item.meta }}\n </div>\n\n <div class=\"tree-timeline__header\">\n <p class=\"tree-timeline__title\">\n {{ item.title }}\n </p>\n <time\n v-if=\"item.timestamp\"\n class=\"tree-timeline__timestamp\"\n :datetime=\"item.datetime || undefined\"\n >\n {{ item.timestamp }}\n </time>\n </div>\n\n <p\n v-if=\"item.description\"\n class=\"tree-timeline__description\"\n >\n {{ item.description }}\n </p>\n </slot>\n </div>\n </li>\n </ol>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport TreeButton from './TreeButton.vue';\nimport TreeBadge from './TreeBadge.vue';\n\nexport interface PricingFeature {\n text: string;\n included?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n title: string;\n description?: string;\n price: string | number;\n currency?: string;\n period?: string;\n features?: PricingFeature[];\n highlighted?: boolean;\n badge?: string;\n buttonText?: string;\n size?: TreeSize;\n disabled?: boolean;\n }>(),\n {\n description: undefined,\n currency: '$',\n period: undefined,\n features: () => [],\n highlighted: false,\n badge: undefined,\n buttonText: undefined,\n size: 'md',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n select: [];\n}>();\n\ndefineSlots<{\n header?: () => unknown;\n price?: () => unknown;\n features?: () => unknown;\n action?: () => unknown;\n badge?: () => unknown;\n}>();\n\nconst classes = computed(() => [\n 'tree-pricing-card',\n `tree-pricing-card--${props.size}`,\n {\n 'tree-pricing-card--highlighted': props.highlighted,\n },\n]);\n\nconst onSelect = () => {\n if (!props.disabled) {\n emit('select');\n }\n};\n</script>\n\n<template>\n <article :class=\"classes\">\n <div\n v-if=\"badge || $slots.badge\"\n class=\"tree-pricing-card__badge\"\n >\n <slot name=\"badge\">\n <TreeBadge\n variant=\"solid\"\n size=\"sm\"\n >\n {{ badge }}\n </TreeBadge>\n </slot>\n </div>\n\n <header class=\"tree-pricing-card__header\">\n <slot name=\"header\">\n <h3 class=\"tree-pricing-card__title\">\n {{ title }}\n </h3>\n <p\n v-if=\"description\"\n class=\"tree-pricing-card__description\"\n >\n {{ description }}\n </p>\n </slot>\n </header>\n\n <div class=\"tree-pricing-card__price\">\n <slot name=\"price\">\n <span class=\"tree-pricing-card__currency\">{{ currency }}</span>\n <span class=\"tree-pricing-card__amount\">{{ price }}</span>\n <span\n v-if=\"period\"\n class=\"tree-pricing-card__period\"\n >{{ period }}</span>\n </slot>\n </div>\n\n <div\n v-if=\"features.length > 0 || $slots.features\"\n class=\"tree-pricing-card__features\"\n >\n <slot name=\"features\">\n <ul\n class=\"tree-pricing-card__feature-list\"\n role=\"list\"\n >\n <li\n v-for=\"(feature, index) in features\"\n :key=\"index\"\n class=\"tree-pricing-card__feature-item\"\n :class=\"{ 'tree-pricing-card__feature-item--excluded': feature.included === false }\"\n >\n <span\n class=\"tree-pricing-card__feature-icon\"\n aria-hidden=\"true\"\n >\n {{ feature.included === false ? '✕' : '✓' }}\n </span>\n <span>{{ feature.text }}</span>\n </li>\n </ul>\n </slot>\n </div>\n\n <footer\n v-if=\"buttonText || $slots.action\"\n class=\"tree-pricing-card__action\"\n >\n <slot name=\"action\">\n <TreeButton\n :variant=\"highlighted ? 'solid' : 'outline'\"\n :size=\"size\"\n :disabled=\"disabled\"\n @click=\"onSelect\"\n >\n {{ buttonText }}\n </TreeButton>\n </slot>\n </footer>\n </article>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport TreeButton from './TreeButton.vue';\nimport TreeBadge from './TreeBadge.vue';\n\nexport interface PricingFeature {\n text: string;\n included?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n title: string;\n description?: string;\n price: string | number;\n currency?: string;\n period?: string;\n features?: PricingFeature[];\n highlighted?: boolean;\n badge?: string;\n buttonText?: string;\n size?: TreeSize;\n disabled?: boolean;\n }>(),\n {\n description: undefined,\n currency: '$',\n period: undefined,\n features: () => [],\n highlighted: false,\n badge: undefined,\n buttonText: undefined,\n size: 'md',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n select: [];\n}>();\n\ndefineSlots<{\n header?: () => unknown;\n price?: () => unknown;\n features?: () => unknown;\n action?: () => unknown;\n badge?: () => unknown;\n}>();\n\nconst classes = computed(() => [\n 'tree-pricing-card',\n `tree-pricing-card--${props.size}`,\n {\n 'tree-pricing-card--highlighted': props.highlighted,\n },\n]);\n\nconst onSelect = () => {\n if (!props.disabled) {\n emit('select');\n }\n};\n</script>\n\n<template>\n <article :class=\"classes\">\n <div\n v-if=\"badge || $slots.badge\"\n class=\"tree-pricing-card__badge\"\n >\n <slot name=\"badge\">\n <TreeBadge\n variant=\"solid\"\n size=\"sm\"\n >\n {{ badge }}\n </TreeBadge>\n </slot>\n </div>\n\n <header class=\"tree-pricing-card__header\">\n <slot name=\"header\">\n <h3 class=\"tree-pricing-card__title\">\n {{ title }}\n </h3>\n <p\n v-if=\"description\"\n class=\"tree-pricing-card__description\"\n >\n {{ description }}\n </p>\n </slot>\n </header>\n\n <div class=\"tree-pricing-card__price\">\n <slot name=\"price\">\n <span class=\"tree-pricing-card__currency\">{{ currency }}</span>\n <span class=\"tree-pricing-card__amount\">{{ price }}</span>\n <span\n v-if=\"period\"\n class=\"tree-pricing-card__period\"\n >{{ period }}</span>\n </slot>\n </div>\n\n <div\n v-if=\"features.length > 0 || $slots.features\"\n class=\"tree-pricing-card__features\"\n >\n <slot name=\"features\">\n <ul\n class=\"tree-pricing-card__feature-list\"\n role=\"list\"\n >\n <li\n v-for=\"(feature, index) in features\"\n :key=\"index\"\n class=\"tree-pricing-card__feature-item\"\n :class=\"{ 'tree-pricing-card__feature-item--excluded': feature.included === false }\"\n >\n <span\n class=\"tree-pricing-card__feature-icon\"\n aria-hidden=\"true\"\n >\n {{ feature.included === false ? '✕' : '✓' }}\n </span>\n <span>{{ feature.text }}</span>\n </li>\n </ul>\n </slot>\n </div>\n\n <footer\n v-if=\"buttonText || $slots.action\"\n class=\"tree-pricing-card__action\"\n >\n <slot name=\"action\">\n <TreeButton\n :variant=\"highlighted ? 'solid' : 'outline'\"\n :size=\"size\"\n :disabled=\"disabled\"\n @click=\"onSelect\"\n >\n {{ buttonText }}\n </TreeButton>\n </slot>\n </footer>\n </article>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport TreePricingCard from './TreePricingCard.vue';\nimport type { PricingFeature } from './TreePricingCard.vue';\n\nexport interface PricingPlan {\n title: string;\n description?: string;\n price: string | number;\n currency?: string;\n period?: string;\n features?: PricingFeature[];\n highlighted?: boolean;\n badge?: string;\n buttonText?: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n plans: PricingPlan[];\n size?: TreeSize;\n columns?: number;\n }>(),\n {\n size: 'md',\n columns: undefined,\n },\n);\n\nconst emit = defineEmits<{\n select: [plan: PricingPlan, index: number];\n}>();\n\nconst gridStyle = computed(() => {\n if (props.columns) {\n return { gridTemplateColumns: `repeat(${props.columns}, 1fr)` };\n }\n return { gridTemplateColumns: `repeat(${props.plans.length}, 1fr)` };\n});\n</script>\n\n<template>\n <div\n class=\"tree-pricing\"\n :style=\"gridStyle\"\n role=\"list\"\n >\n <div\n v-for=\"(plan, index) in plans\"\n :key=\"index\"\n role=\"listitem\"\n >\n <slot\n name=\"plan\"\n :plan=\"plan\"\n :index=\"index\"\n >\n <TreePricingCard\n v-bind=\"plan\"\n :size=\"size\"\n @select=\"emit('select', plan, index)\"\n />\n </slot>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TreeSize } from '../types/contracts';\nimport TreePricingCard from './TreePricingCard.vue';\nimport type { PricingFeature } from './TreePricingCard.vue';\n\nexport interface PricingPlan {\n title: string;\n description?: string;\n price: string | number;\n currency?: string;\n period?: string;\n features?: PricingFeature[];\n highlighted?: boolean;\n badge?: string;\n buttonText?: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n plans: PricingPlan[];\n size?: TreeSize;\n columns?: number;\n }>(),\n {\n size: 'md',\n columns: undefined,\n },\n);\n\nconst emit = defineEmits<{\n select: [plan: PricingPlan, index: number];\n}>();\n\nconst gridStyle = computed(() => {\n if (props.columns) {\n return { gridTemplateColumns: `repeat(${props.columns}, 1fr)` };\n }\n return { gridTemplateColumns: `repeat(${props.plans.length}, 1fr)` };\n});\n</script>\n\n<template>\n <div\n class=\"tree-pricing\"\n :style=\"gridStyle\"\n role=\"list\"\n >\n <div\n v-for=\"(plan, index) in plans\"\n :key=\"index\"\n role=\"listitem\"\n >\n <slot\n name=\"plan\"\n :plan=\"plan\"\n :index=\"index\"\n >\n <TreePricingCard\n v-bind=\"plan\"\n :size=\"size\"\n @select=\"emit('select', plan, index)\"\n />\n </slot>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs, nextTick } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n size?: TreeSize;\n disabled?: boolean;\n placeholder?: string;\n uploadImage?: (file: File) => Promise<string>;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n placeholder: 'Write your markdown here...',\n uploadImage: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'image-upload': [file: File, url: string];\n 'image-upload-error': [file: File, error: Error];\n}>();\n\ndefineSlots<{\n toolbar?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst textareaRef = ref<HTMLTextAreaElement | null>(null);\nconst isUploading = ref(false);\n\nconst rootClasses = computed(() => [\n 'tree-md-editor',\n `tree-md-editor--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-uploading': isUploading.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst editorAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value);\n};\n\n/* ──────── Toolbar Actions ──────── */\n\nconst insertAtCursor = (before: string, after = '') => {\n const el = textareaRef.value;\n if (!el) return;\n\n const start = el.selectionStart;\n const end = el.selectionEnd;\n const text = stringValue.value;\n const selected = text.slice(start, end);\n\n const newText = text.slice(0, start) + before + selected + after + text.slice(end);\n emit('update:modelValue', newText);\n\n nextTick(() => {\n el.focus();\n const cursorPos = selected\n ? start + before.length + selected.length + after.length\n : start + before.length;\n el.setSelectionRange(cursorPos, cursorPos);\n });\n};\n\nconst insertHeading = (level: number) => {\n const prefix = '#'.repeat(level) + ' ';\n const el = textareaRef.value;\n if (!el) return;\n\n const start = el.selectionStart;\n const text = stringValue.value;\n\n // Find start of current line\n const lineStart = text.lastIndexOf('\\n', start - 1) + 1;\n const lineEnd = text.indexOf('\\n', start);\n const actualEnd = lineEnd === -1 ? text.length : lineEnd;\n const line = text.slice(lineStart, actualEnd);\n\n // Strip existing heading markers\n const stripped = line.replace(/^#{1,6}\\s*/, '');\n const newLine = prefix + stripped;\n\n const newText = text.slice(0, lineStart) + newLine + text.slice(actualEnd);\n emit('update:modelValue', newText);\n\n nextTick(() => {\n el.focus();\n el.setSelectionRange(lineStart + newLine.length, lineStart + newLine.length);\n });\n};\n\nconst insertBold = () => insertAtCursor('**', '**');\nconst insertItalic = () => insertAtCursor('_', '_');\nconst insertCode = () => insertAtCursor('`', '`');\nconst insertCodeBlock = () => insertAtCursor('\\n```\\n', '\\n```\\n');\nconst insertLink = () => insertAtCursor('[', '](url)');\nconst insertList = () => insertAtCursor('\\n- ');\nconst insertOrderedList = () => insertAtCursor('\\n1. ');\nconst insertQuote = () => insertAtCursor('\\n> ');\nconst insertHr = () => insertAtCursor('\\n---\\n');\n\n/* ──────── Markdown → HTML rendering ──────── */\n\nconst renderedHtml = computed(() => {\n return markdownToHtml(stringValue.value);\n});\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\nfunction markdownToHtml(md: string): string {\n if (!md) return '';\n\n const lines = md.split('\\n');\n const html: string[] = [];\n let inCodeBlock = false;\n let inList = false;\n let inOrderedList = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Code blocks\n if (line.trim().startsWith('```')) {\n if (inCodeBlock) {\n html.push('</code></pre>');\n inCodeBlock = false;\n } else {\n inCodeBlock = true;\n html.push('<pre class=\"tree-md-editor__code-block\"><code>');\n }\n continue;\n }\n\n if (inCodeBlock) {\n html.push(escapeHtml(line));\n html.push('\\n');\n continue;\n }\n\n // Close open lists if needed\n const isUnorderedListItem = /^[-*+]\\s/.test(line.trim());\n const isOrderedListItem = /^\\d+\\.\\s/.test(line.trim());\n\n if (inList && !isUnorderedListItem) {\n html.push('</ul>');\n inList = false;\n }\n if (inOrderedList && !isOrderedListItem) {\n html.push('</ol>');\n inOrderedList = false;\n }\n\n // Horizontal rule\n if (/^(-{3,}|_{3,}|\\*{3,})$/.test(line.trim())) {\n html.push('<hr class=\"tree-md-editor__hr\" />');\n continue;\n }\n\n // Headings\n const headingMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (headingMatch) {\n const level = headingMatch[1].length;\n html.push(`<h${level} class=\"tree-md-editor__heading tree-md-editor__heading--${level}\">${inlineMarkdown(escapeHtml(headingMatch[2]))}</h${level}>`);\n continue;\n }\n\n // Blockquote\n if (line.trim().startsWith('> ')) {\n html.push(`<blockquote class=\"tree-md-editor__blockquote\">${inlineMarkdown(escapeHtml(line.trim().slice(2)))}</blockquote>`);\n continue;\n }\n\n // Unordered list\n if (isUnorderedListItem) {\n if (!inList) {\n html.push('<ul class=\"tree-md-editor__list\">');\n inList = true;\n }\n html.push(`<li>${inlineMarkdown(escapeHtml(line.trim().slice(2)))}</li>`);\n continue;\n }\n\n // Ordered list\n if (isOrderedListItem) {\n if (!inOrderedList) {\n html.push('<ol class=\"tree-md-editor__list tree-md-editor__list--ordered\">');\n inOrderedList = true;\n }\n const content = line.trim().replace(/^\\d+\\.\\s/, '');\n html.push(`<li>${inlineMarkdown(escapeHtml(content))}</li>`);\n continue;\n }\n\n // Empty line\n if (line.trim() === '') {\n html.push('<br />');\n continue;\n }\n\n // Paragraph\n html.push(`<p class=\"tree-md-editor__paragraph\">${inlineMarkdown(escapeHtml(line))}</p>`);\n }\n\n // Close any open blocks\n if (inCodeBlock) html.push('</code></pre>');\n if (inList) html.push('</ul>');\n if (inOrderedList) html.push('</ol>');\n\n return html.join('\\n');\n}\n\nfunction inlineMarkdown(text: string): string {\n // Images: ![alt](url)\n text = text.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, '<img src=\"$2\" alt=\"$1\" class=\"tree-md-editor__image\" loading=\"lazy\" />');\n // Links: [text](url)\n text = text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>');\n // Bold: **text**\n text = text.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');\n // Italic: _text_ or *text*\n text = text.replace(/_(.+?)_/g, '<em>$1</em>');\n text = text.replace(/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, '<em>$1</em>');\n // Inline code: `text`\n text = text.replace(/`(.+?)`/g, '<code class=\"tree-md-editor__inline-code\">$1</code>');\n // Strikethrough: ~~text~~\n text = text.replace(/~~(.+?)~~/g, '<del>$1</del>');\n return text;\n}\n\n/* ──────── Image paste / drop handling ──────── */\n\nconst handlePaste = async (event: ClipboardEvent) => {\n if (props.disabled) return;\n\n const items = event.clipboardData?.items;\n if (!items) return;\n\n for (const item of items) {\n if (item.type.startsWith('image/')) {\n event.preventDefault();\n const file = item.getAsFile();\n if (file) await processImageUpload(file);\n return;\n }\n }\n};\n\nconst handleDrop = async (event: DragEvent) => {\n if (props.disabled) return;\n\n const files = event.dataTransfer?.files;\n if (!files) return;\n\n for (const file of files) {\n if (file.type.startsWith('image/')) {\n event.preventDefault();\n await processImageUpload(file);\n }\n }\n};\n\nconst handleDragOver = (event: DragEvent) => {\n if (props.disabled) return;\n event.preventDefault();\n};\n\nconst processImageUpload = async (file: File) => {\n if (!props.uploadImage) {\n // Fallback: insert a placeholder with the file name\n insertAtCursor(`![${file.name}]()`);\n return;\n }\n\n // Insert uploading placeholder\n const placeholder = `![Uploading ${file.name}...]()`;\n insertAtCursor(placeholder);\n isUploading.value = true;\n\n try {\n const url = props.uploadImage(file);\n const resolvedUrl = url instanceof Promise ? await url : url;\n\n // Replace placeholder with actual URL\n const currentValue = stringValue.value;\n const newValue = currentValue.replace(placeholder, `![${file.name}](${resolvedUrl})`);\n emit('update:modelValue', newValue);\n emit('image-upload', file, resolvedUrl);\n } catch (err) {\n // Remove placeholder on error\n const currentValue = stringValue.value;\n const newValue = currentValue.replace(placeholder, '');\n emit('update:modelValue', newValue);\n emit('image-upload-error', file, err instanceof Error ? err : new Error(String(err)));\n } finally {\n isUploading.value = false;\n }\n};\n\n/* ──────── Keyboard shortcuts ──────── */\n\nconst handleKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n const mod = event.metaKey || event.ctrlKey;\n if (!mod) return;\n\n switch (event.key) {\n case 'b':\n event.preventDefault();\n insertBold();\n break;\n case 'i':\n event.preventDefault();\n insertItalic();\n break;\n case 'k':\n event.preventDefault();\n insertLink();\n break;\n case 'e':\n event.preventDefault();\n insertCode();\n break;\n }\n};\n\n</script>\n\n<template>\n <div\n v-bind=\"editorAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <!-- Toolbar -->\n <div\n class=\"tree-md-editor__toolbar\"\n role=\"toolbar\"\n aria-label=\"Markdown formatting\"\n >\n <div class=\"tree-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Heading 1 (H1)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(1)\"\n >\n H1\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Heading 2 (H2)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(2)\"\n >\n H2\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Heading 3 (H3)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(3)\"\n >\n H3\n </button>\n </div>\n\n <div\n class=\"tree-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"tree-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Bold (Ctrl+B)\"\n :disabled=\"disabled\"\n @click=\"insertBold\"\n >\n <strong>B</strong>\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Italic (Ctrl+I)\"\n :disabled=\"disabled\"\n @click=\"insertItalic\"\n >\n <em>I</em>\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Strikethrough\"\n :disabled=\"disabled\"\n @click=\"insertAtCursor('~~', '~~')\"\n >\n <del>S</del>\n </button>\n </div>\n\n <div\n class=\"tree-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"tree-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Inline code (Ctrl+E)\"\n :disabled=\"disabled\"\n @click=\"insertCode\"\n >\n &lt;/&gt;\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Code block\"\n :disabled=\"disabled\"\n @click=\"insertCodeBlock\"\n >\n { }\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Link (Ctrl+K)\"\n :disabled=\"disabled\"\n @click=\"insertLink\"\n >\n 🔗\n </button>\n </div>\n\n <div\n class=\"tree-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"tree-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Unordered list\"\n :disabled=\"disabled\"\n @click=\"insertList\"\n >\n •&nbsp;List\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Ordered list\"\n :disabled=\"disabled\"\n @click=\"insertOrderedList\"\n >\n 1.&nbsp;List\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Blockquote\"\n :disabled=\"disabled\"\n @click=\"insertQuote\"\n >\n &gt;\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Horizontal rule\"\n :disabled=\"disabled\"\n @click=\"insertHr\"\n >\n ―\n </button>\n </div>\n\n <slot name=\"toolbar\" />\n </div>\n\n <!-- Editor body -->\n <div class=\"tree-md-editor__body\">\n <!-- Write pane -->\n <div\n class=\"tree-md-editor__pane tree-md-editor__pane--write\"\n >\n <textarea\n ref=\"textareaRef\"\n class=\"tree-md-editor__textarea\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-label=\"placeholder\"\n @input=\"onInput\"\n @paste=\"handlePaste\"\n @drop=\"handleDrop\"\n @dragover=\"handleDragOver\"\n @keydown=\"handleKeydown\"\n />\n </div>\n\n <!-- Preview pane -->\n <div\n class=\"tree-md-editor__pane tree-md-editor__pane--preview\"\n aria-label=\"Markdown preview\"\n >\n <!-- eslint-disable vue/no-v-html -->\n <div\n class=\"tree-md-editor__preview\"\n v-html=\"renderedHtml\"\n />\n <!-- eslint-enable vue/no-v-html -->\n </div>\n </div>\n\n <!-- Upload indicator -->\n <div\n v-if=\"isUploading\"\n class=\"tree-md-editor__upload-bar\"\n role=\"status\"\n aria-live=\"polite\"\n >\n Uploading image…\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs, nextTick } from 'vue';\nimport type { TreeSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n size?: TreeSize;\n disabled?: boolean;\n placeholder?: string;\n uploadImage?: (file: File) => Promise<string>;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n placeholder: 'Write your markdown here...',\n uploadImage: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'image-upload': [file: File, url: string];\n 'image-upload-error': [file: File, error: Error];\n}>();\n\ndefineSlots<{\n toolbar?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst textareaRef = ref<HTMLTextAreaElement | null>(null);\nconst isUploading = ref(false);\n\nconst rootClasses = computed(() => [\n 'tree-md-editor',\n `tree-md-editor--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-uploading': isUploading.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst editorAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value);\n};\n\n/* ──────── Toolbar Actions ──────── */\n\nconst insertAtCursor = (before: string, after = '') => {\n const el = textareaRef.value;\n if (!el) return;\n\n const start = el.selectionStart;\n const end = el.selectionEnd;\n const text = stringValue.value;\n const selected = text.slice(start, end);\n\n const newText = text.slice(0, start) + before + selected + after + text.slice(end);\n emit('update:modelValue', newText);\n\n nextTick(() => {\n el.focus();\n const cursorPos = selected\n ? start + before.length + selected.length + after.length\n : start + before.length;\n el.setSelectionRange(cursorPos, cursorPos);\n });\n};\n\nconst insertHeading = (level: number) => {\n const prefix = '#'.repeat(level) + ' ';\n const el = textareaRef.value;\n if (!el) return;\n\n const start = el.selectionStart;\n const text = stringValue.value;\n\n // Find start of current line\n const lineStart = text.lastIndexOf('\\n', start - 1) + 1;\n const lineEnd = text.indexOf('\\n', start);\n const actualEnd = lineEnd === -1 ? text.length : lineEnd;\n const line = text.slice(lineStart, actualEnd);\n\n // Strip existing heading markers\n const stripped = line.replace(/^#{1,6}\\s*/, '');\n const newLine = prefix + stripped;\n\n const newText = text.slice(0, lineStart) + newLine + text.slice(actualEnd);\n emit('update:modelValue', newText);\n\n nextTick(() => {\n el.focus();\n el.setSelectionRange(lineStart + newLine.length, lineStart + newLine.length);\n });\n};\n\nconst insertBold = () => insertAtCursor('**', '**');\nconst insertItalic = () => insertAtCursor('_', '_');\nconst insertCode = () => insertAtCursor('`', '`');\nconst insertCodeBlock = () => insertAtCursor('\\n```\\n', '\\n```\\n');\nconst insertLink = () => insertAtCursor('[', '](url)');\nconst insertList = () => insertAtCursor('\\n- ');\nconst insertOrderedList = () => insertAtCursor('\\n1. ');\nconst insertQuote = () => insertAtCursor('\\n> ');\nconst insertHr = () => insertAtCursor('\\n---\\n');\n\n/* ──────── Markdown → HTML rendering ──────── */\n\nconst renderedHtml = computed(() => {\n return markdownToHtml(stringValue.value);\n});\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\nfunction markdownToHtml(md: string): string {\n if (!md) return '';\n\n const lines = md.split('\\n');\n const html: string[] = [];\n let inCodeBlock = false;\n let inList = false;\n let inOrderedList = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Code blocks\n if (line.trim().startsWith('```')) {\n if (inCodeBlock) {\n html.push('</code></pre>');\n inCodeBlock = false;\n } else {\n inCodeBlock = true;\n html.push('<pre class=\"tree-md-editor__code-block\"><code>');\n }\n continue;\n }\n\n if (inCodeBlock) {\n html.push(escapeHtml(line));\n html.push('\\n');\n continue;\n }\n\n // Close open lists if needed\n const isUnorderedListItem = /^[-*+]\\s/.test(line.trim());\n const isOrderedListItem = /^\\d+\\.\\s/.test(line.trim());\n\n if (inList && !isUnorderedListItem) {\n html.push('</ul>');\n inList = false;\n }\n if (inOrderedList && !isOrderedListItem) {\n html.push('</ol>');\n inOrderedList = false;\n }\n\n // Horizontal rule\n if (/^(-{3,}|_{3,}|\\*{3,})$/.test(line.trim())) {\n html.push('<hr class=\"tree-md-editor__hr\" />');\n continue;\n }\n\n // Headings\n const headingMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (headingMatch) {\n const level = headingMatch[1].length;\n html.push(`<h${level} class=\"tree-md-editor__heading tree-md-editor__heading--${level}\">${inlineMarkdown(escapeHtml(headingMatch[2]))}</h${level}>`);\n continue;\n }\n\n // Blockquote\n if (line.trim().startsWith('> ')) {\n html.push(`<blockquote class=\"tree-md-editor__blockquote\">${inlineMarkdown(escapeHtml(line.trim().slice(2)))}</blockquote>`);\n continue;\n }\n\n // Unordered list\n if (isUnorderedListItem) {\n if (!inList) {\n html.push('<ul class=\"tree-md-editor__list\">');\n inList = true;\n }\n html.push(`<li>${inlineMarkdown(escapeHtml(line.trim().slice(2)))}</li>`);\n continue;\n }\n\n // Ordered list\n if (isOrderedListItem) {\n if (!inOrderedList) {\n html.push('<ol class=\"tree-md-editor__list tree-md-editor__list--ordered\">');\n inOrderedList = true;\n }\n const content = line.trim().replace(/^\\d+\\.\\s/, '');\n html.push(`<li>${inlineMarkdown(escapeHtml(content))}</li>`);\n continue;\n }\n\n // Empty line\n if (line.trim() === '') {\n html.push('<br />');\n continue;\n }\n\n // Paragraph\n html.push(`<p class=\"tree-md-editor__paragraph\">${inlineMarkdown(escapeHtml(line))}</p>`);\n }\n\n // Close any open blocks\n if (inCodeBlock) html.push('</code></pre>');\n if (inList) html.push('</ul>');\n if (inOrderedList) html.push('</ol>');\n\n return html.join('\\n');\n}\n\nfunction inlineMarkdown(text: string): string {\n // Images: ![alt](url)\n text = text.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, '<img src=\"$2\" alt=\"$1\" class=\"tree-md-editor__image\" loading=\"lazy\" />');\n // Links: [text](url)\n text = text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>');\n // Bold: **text**\n text = text.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');\n // Italic: _text_ or *text*\n text = text.replace(/_(.+?)_/g, '<em>$1</em>');\n text = text.replace(/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, '<em>$1</em>');\n // Inline code: `text`\n text = text.replace(/`(.+?)`/g, '<code class=\"tree-md-editor__inline-code\">$1</code>');\n // Strikethrough: ~~text~~\n text = text.replace(/~~(.+?)~~/g, '<del>$1</del>');\n return text;\n}\n\n/* ──────── Image paste / drop handling ──────── */\n\nconst handlePaste = async (event: ClipboardEvent) => {\n if (props.disabled) return;\n\n const items = event.clipboardData?.items;\n if (!items) return;\n\n for (const item of items) {\n if (item.type.startsWith('image/')) {\n event.preventDefault();\n const file = item.getAsFile();\n if (file) await processImageUpload(file);\n return;\n }\n }\n};\n\nconst handleDrop = async (event: DragEvent) => {\n if (props.disabled) return;\n\n const files = event.dataTransfer?.files;\n if (!files) return;\n\n for (const file of files) {\n if (file.type.startsWith('image/')) {\n event.preventDefault();\n await processImageUpload(file);\n }\n }\n};\n\nconst handleDragOver = (event: DragEvent) => {\n if (props.disabled) return;\n event.preventDefault();\n};\n\nconst processImageUpload = async (file: File) => {\n if (!props.uploadImage) {\n // Fallback: insert a placeholder with the file name\n insertAtCursor(`![${file.name}]()`);\n return;\n }\n\n // Insert uploading placeholder\n const placeholder = `![Uploading ${file.name}...]()`;\n insertAtCursor(placeholder);\n isUploading.value = true;\n\n try {\n const url = props.uploadImage(file);\n const resolvedUrl = url instanceof Promise ? await url : url;\n\n // Replace placeholder with actual URL\n const currentValue = stringValue.value;\n const newValue = currentValue.replace(placeholder, `![${file.name}](${resolvedUrl})`);\n emit('update:modelValue', newValue);\n emit('image-upload', file, resolvedUrl);\n } catch (err) {\n // Remove placeholder on error\n const currentValue = stringValue.value;\n const newValue = currentValue.replace(placeholder, '');\n emit('update:modelValue', newValue);\n emit('image-upload-error', file, err instanceof Error ? err : new Error(String(err)));\n } finally {\n isUploading.value = false;\n }\n};\n\n/* ──────── Keyboard shortcuts ──────── */\n\nconst handleKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n const mod = event.metaKey || event.ctrlKey;\n if (!mod) return;\n\n switch (event.key) {\n case 'b':\n event.preventDefault();\n insertBold();\n break;\n case 'i':\n event.preventDefault();\n insertItalic();\n break;\n case 'k':\n event.preventDefault();\n insertLink();\n break;\n case 'e':\n event.preventDefault();\n insertCode();\n break;\n }\n};\n\n</script>\n\n<template>\n <div\n v-bind=\"editorAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <!-- Toolbar -->\n <div\n class=\"tree-md-editor__toolbar\"\n role=\"toolbar\"\n aria-label=\"Markdown formatting\"\n >\n <div class=\"tree-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Heading 1 (H1)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(1)\"\n >\n H1\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Heading 2 (H2)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(2)\"\n >\n H2\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Heading 3 (H3)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(3)\"\n >\n H3\n </button>\n </div>\n\n <div\n class=\"tree-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"tree-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Bold (Ctrl+B)\"\n :disabled=\"disabled\"\n @click=\"insertBold\"\n >\n <strong>B</strong>\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Italic (Ctrl+I)\"\n :disabled=\"disabled\"\n @click=\"insertItalic\"\n >\n <em>I</em>\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Strikethrough\"\n :disabled=\"disabled\"\n @click=\"insertAtCursor('~~', '~~')\"\n >\n <del>S</del>\n </button>\n </div>\n\n <div\n class=\"tree-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"tree-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Inline code (Ctrl+E)\"\n :disabled=\"disabled\"\n @click=\"insertCode\"\n >\n &lt;/&gt;\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Code block\"\n :disabled=\"disabled\"\n @click=\"insertCodeBlock\"\n >\n { }\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Link (Ctrl+K)\"\n :disabled=\"disabled\"\n @click=\"insertLink\"\n >\n 🔗\n </button>\n </div>\n\n <div\n class=\"tree-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"tree-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Unordered list\"\n :disabled=\"disabled\"\n @click=\"insertList\"\n >\n •&nbsp;List\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Ordered list\"\n :disabled=\"disabled\"\n @click=\"insertOrderedList\"\n >\n 1.&nbsp;List\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Blockquote\"\n :disabled=\"disabled\"\n @click=\"insertQuote\"\n >\n &gt;\n </button>\n <button\n type=\"button\"\n class=\"tree-md-editor__toolbar-btn\"\n title=\"Horizontal rule\"\n :disabled=\"disabled\"\n @click=\"insertHr\"\n >\n ―\n </button>\n </div>\n\n <slot name=\"toolbar\" />\n </div>\n\n <!-- Editor body -->\n <div class=\"tree-md-editor__body\">\n <!-- Write pane -->\n <div\n class=\"tree-md-editor__pane tree-md-editor__pane--write\"\n >\n <textarea\n ref=\"textareaRef\"\n class=\"tree-md-editor__textarea\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-label=\"placeholder\"\n @input=\"onInput\"\n @paste=\"handlePaste\"\n @drop=\"handleDrop\"\n @dragover=\"handleDragOver\"\n @keydown=\"handleKeydown\"\n />\n </div>\n\n <!-- Preview pane -->\n <div\n class=\"tree-md-editor__pane tree-md-editor__pane--preview\"\n aria-label=\"Markdown preview\"\n >\n <!-- eslint-disable vue/no-v-html -->\n <div\n class=\"tree-md-editor__preview\"\n v-html=\"renderedHtml\"\n />\n <!-- eslint-enable vue/no-v-html -->\n </div>\n </div>\n\n <!-- Upload indicator -->\n <div\n v-if=\"isUploading\"\n class=\"tree-md-editor__upload-bar\"\n role=\"status\"\n aria-live=\"polite\"\n >\n Uploading image…\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, type Component } from 'vue';\nimport { getTreeIcon, treeIconDefaults, type TreeIconName } from '@treeui/icons';\n\nconst props = withDefaults(\n defineProps<{\n name: TreeIconName;\n size?: number | string;\n strokeWidth?: number | string;\n absoluteStrokeWidth?: boolean;\n label?: string;\n }>(),\n {\n size: treeIconDefaults.size,\n strokeWidth: treeIconDefaults.strokeWidth,\n absoluteStrokeWidth: treeIconDefaults.absoluteStrokeWidth,\n label: undefined,\n },\n);\n\nconst iconComponent = computed(() => getTreeIcon(props.name) as Component);\n</script>\n\n<template>\n <component\n :is=\"iconComponent\"\n class=\"tree-icon\"\n :size=\"size\"\n :stroke-width=\"strokeWidth\"\n :absolute-stroke-width=\"absoluteStrokeWidth\"\n :role=\"label ? 'img' : undefined\"\n :aria-label=\"label || undefined\"\n :aria-hidden=\"label ? undefined : 'true'\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, type Component } from 'vue';\nimport { getTreeIcon, treeIconDefaults, type TreeIconName } from '@treeui/icons';\n\nconst props = withDefaults(\n defineProps<{\n name: TreeIconName;\n size?: number | string;\n strokeWidth?: number | string;\n absoluteStrokeWidth?: boolean;\n label?: string;\n }>(),\n {\n size: treeIconDefaults.size,\n strokeWidth: treeIconDefaults.strokeWidth,\n absoluteStrokeWidth: treeIconDefaults.absoluteStrokeWidth,\n label: undefined,\n },\n);\n\nconst iconComponent = computed(() => getTreeIcon(props.name) as Component);\n</script>\n\n<template>\n <component\n :is=\"iconComponent\"\n class=\"tree-icon\"\n :size=\"size\"\n :stroke-width=\"strokeWidth\"\n :absolute-stroke-width=\"absoluteStrokeWidth\"\n :role=\"label ? 'img' : undefined\"\n :aria-label=\"label || undefined\"\n :aria-hidden=\"label ? undefined : 'true'\"\n />\n</template>\n","import type { App, Plugin } from 'vue';\nimport {\n TAccordion,\n TAccordionItem,\n TAlert,\n TBadge,\n TBreadcrumb,\n TBreadcrumbItem,\n TButton,\n TCard,\n TCheckbox,\n TCombobox,\n TConfirmDialog,\n TContainer,\n TContextMenu,\n TDatePicker,\n TDateTimePicker,\n TDrawer,\n TDropdown,\n TEmptyState,\n TFileUpload,\n TFormField,\n TGrid,\n TAppBar,\n TInput,\n TLink,\n TNavMenu,\n TNavbar,\n TMultiSelect,\n TModal,\n TNumberInput,\n TPagination,\n TPopover,\n TProgress,\n TRadio,\n TRadioGroup,\n TSelectableList,\n TSelect,\n TSidebar,\n TSkeleton,\n TSpinner,\n TStack,\n TStat,\n TStepper,\n TSteps,\n TSwitch,\n TTextarea,\n TTabs,\n TTabList,\n TTab,\n TTabPanel,\n TToggleGroup,\n TToast,\n TToastProvider,\n TTooltip,\n TAvatar,\n TDivider,\n TTable,\n TTag,\n TTreeView,\n TTimeline,\n TPricing,\n TPricingCard,\n TMarkdownEditor,\n TIcon,\n} from './components';\n\nconst components = {\n TAccordion,\n TAccordionItem,\n TAlert,\n TBadge,\n TBreadcrumb,\n TBreadcrumbItem,\n TButton,\n TCard,\n TCheckbox,\n TCombobox,\n TConfirmDialog,\n TContainer,\n TContextMenu,\n TDatePicker,\n TDateTimePicker,\n TDrawer,\n TDropdown,\n TEmptyState,\n TFileUpload,\n TFormField,\n TGrid,\n TAppBar,\n TInput,\n TLink,\n TNavMenu,\n TNavbar,\n TMultiSelect,\n TModal,\n TNumberInput,\n TRadio,\n TRadioGroup,\n TSelectableList,\n TSelect,\n TSidebar,\n TSkeleton,\n TSpinner,\n TStack,\n TStat,\n TStepper,\n TSteps,\n TSwitch,\n TTextarea,\n TTabs,\n TTabList,\n TTab,\n TTabPanel,\n TToggleGroup,\n TToast,\n TToastProvider,\n TPagination,\n TPopover,\n TProgress,\n TTooltip,\n TAvatar,\n TDivider,\n TTable,\n TTag,\n TTreeView,\n TTimeline,\n TPricing,\n TPricingCard,\n TMarkdownEditor,\n TIcon,\n TreeAccordion: TAccordion,\n TreeAccordionItem: TAccordionItem,\n TreeAlert: TAlert,\n TreeBadge: TBadge,\n TreeBreadcrumb: TBreadcrumb,\n TreeBreadcrumbItem: TBreadcrumbItem,\n TreeButton: TButton,\n TreeCard: TCard,\n TreeCheckbox: TCheckbox,\n TreeCombobox: TCombobox,\n TreeConfirmDialog: TConfirmDialog,\n TreeContainer: TContainer,\n TreeContextMenu: TContextMenu,\n TreeDatePicker: TDatePicker,\n TreeDateTimePicker: TDateTimePicker,\n TreeDrawer: TDrawer,\n TreeDropdown: TDropdown,\n TreeEmptyState: TEmptyState,\n TreeFileUpload: TFileUpload,\n TreeGrid: TGrid,\n TreeNavbar: TNavbar,\n TreeAppBar: TNavbar,\n TreeLink: TLink,\n TreeNavMenu: TNavMenu,\n TreeMultiSelect: TMultiSelect,\n TreeRadio: TRadio,\n TreeRadioGroup: TRadioGroup,\n TreeSelect: TSelect,\n TreeSkeleton: TSkeleton,\n TreeSidebar: TSidebar,\n TreeInput: TInput,\n TreeNumberInput: TNumberInput,\n TreeSelectableList: TSelectableList,\n TreeStack: TStack,\n TreeTreeView: TTreeView,\n TreeSteps: TSteps,\n TreeStepper: TStepper,\n TreeToggleGroup: TToggleGroup,\n TreeTextarea: TTextarea,\n TreeModal: TModal,\n TreePagination: TPagination,\n TreePopover: TPopover,\n TreeSpinner: TSpinner,\n TreeFormField: TFormField,\n TreeProgress: TProgress,\n TreeStat: TStat,\n TreeSwitch: TSwitch,\n TreeTabs: TTabs,\n TreeTabList: TTabList,\n TreeTab: TTab,\n TreeTabPanel: TTabPanel,\n TreeToast: TToast,\n TreeToastProvider: TToastProvider,\n TreeTooltip: TTooltip,\n TreeAvatar: TAvatar,\n TreeDivider: TDivider,\n TreeTable: TTable,\n TreeTag: TTag,\n TreeTimeline: TTimeline,\n TreePricing: TPricing,\n TreePricingCard: TPricingCard,\n TreeMarkdownEditor: TMarkdownEditor,\n TreeIcon: TIcon,\n};\n\nexport const TreeUIPlugin: Plugin = {\n install(app: App) {\n Object.entries(components).forEach(([name, component]) => {\n app.component(name, component);\n });\n },\n};\n\nexport const install = TreeUIPlugin.install;\n","export const treeSizes = ['sm', 'md', 'lg'] as const;\nexport const treeVariants = ['solid', 'outline', 'ghost', 'soft', 'danger'] as const;\nexport const treeCardVariants = ['outline', 'soft', 'solid', 'inset'] as const;\nexport const treeTooltipSides = ['top', 'right', 'bottom', 'left'] as const;\nexport const treeDrawerSides = ['top', 'right', 'bottom', 'left'] as const;\n\nexport type TreeSize = (typeof treeSizes)[number];\nexport type TreeVariant = (typeof treeVariants)[number];\nexport type TreeCardVariant = (typeof treeCardVariants)[number];\nexport type TreeTooltipSide = (typeof treeTooltipSides)[number];\nexport type TreeDrawerSide = (typeof treeDrawerSides)[number];\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots","$slots"],"sources":["../src/components/accordion.ts","../src/components/TAccordion.vue","../src/components/TAccordion.vue","../src/components/TAccordionItem.vue","../src/components/TAccordionItem.vue","../src/components/TAlert.vue","../src/components/TAlert.vue","../src/components/TBadge.vue","../src/components/TBadge.vue","../src/components/TBreadcrumb.vue","../src/components/TBreadcrumb.vue","../src/components/TBreadcrumbItem.vue","../src/components/TBreadcrumbItem.vue","../src/components/TSpinner.vue","../src/components/TSpinner.vue","../src/components/TButton.vue","../src/components/TButton.vue","../src/components/TCard.vue","../src/components/TCard.vue","../src/components/TCheckbox.vue","../src/components/TCheckbox.vue","../src/composables/useControllableOpen.ts","../src/components/TCombobox.vue","../src/components/TCombobox.vue","../src/components/TModal.vue","../src/components/TModal.vue","../src/components/TConfirmDialog.vue","../src/components/TConfirmDialog.vue","../src/components/TContainer.vue","../src/components/TContainer.vue","../src/components/TContextMenu.vue","../src/components/TContextMenu.vue","../src/components/TDatePicker.vue","../src/components/TDatePicker.vue","../src/components/TDateTimePicker.vue","../src/components/TDateTimePicker.vue","../src/components/TDrawer.vue","../src/components/TDrawer.vue","../src/components/TDropdown.vue","../src/components/TDropdown.vue","../src/components/TEmptyState.vue","../src/components/TEmptyState.vue","../src/components/TFileUpload.vue","../src/components/TFileUpload.vue","../src/components/TMultiSelect.vue","../src/components/TMultiSelect.vue","../src/components/TGrid.vue","../src/components/TGrid.vue","../src/components/TNavbar.vue","../src/components/TNavbar.vue","../src/components/TLink.vue","../src/components/TLink.vue","../src/components/sidebar.ts","../src/components/TNavMenu.vue","../src/components/TNavMenu.vue","../src/components/TRadio.vue","../src/components/TRadio.vue","../src/components/TRadioGroup.vue","../src/components/TRadioGroup.vue","../src/components/TSelect.vue","../src/components/TSelect.vue","../src/components/TSidebar.vue","../src/components/TSidebar.vue","../src/components/TInput.vue","../src/components/TInput.vue","../src/components/TNumberInput.vue","../src/components/TNumberInput.vue","../src/components/TSelectableList.vue","../src/components/TSelectableList.vue","../src/components/TStack.vue","../src/components/TStack.vue","../src/components/tree-view.ts","../src/components/TTreeViewItem.vue","../src/components/TTreeViewItem.vue","../src/components/TTreeView.vue","../src/components/TTreeView.vue","../src/components/TSteps.vue","../src/components/TSteps.vue","../src/components/TToggleGroup.vue","../src/components/TToggleGroup.vue","../src/components/TTextarea.vue","../src/components/TTextarea.vue","../src/components/TSkeleton.vue","../src/components/TSkeleton.vue","../src/components/TStat.vue","../src/components/TStat.vue","../src/components/TSwitch.vue","../src/components/TSwitch.vue","../src/components/TTooltip.vue","../src/components/TTooltip.vue","../src/components/TFormField.vue","../src/components/TFormField.vue","../src/components/TPagination.vue","../src/components/TPagination.vue","../src/components/TPopover.vue","../src/components/TPopover.vue","../src/components/TProgress.vue","../src/components/TProgress.vue","../src/components/tabs-context.ts","../src/components/TTabs.vue","../src/components/TTabs.vue","../src/components/TTabList.vue","../src/components/TTabList.vue","../src/components/TTab.vue","../src/components/TTab.vue","../src/components/TTabPanel.vue","../src/components/TTabPanel.vue","../src/components/TToast.vue","../src/components/TToast.vue","../src/composables/useToast.ts","../src/components/TToastProvider.vue","../src/components/TToastProvider.vue","../src/components/TAvatar.vue","../src/components/TAvatar.vue","../src/components/TDivider.vue","../src/components/TDivider.vue","../src/components/TTable.vue","../src/components/TTable.vue","../src/components/TTag.vue","../src/components/TTag.vue","../src/components/TTimeline.vue","../src/components/TTimeline.vue","../src/components/TPricingCard.vue","../src/components/TPricingCard.vue","../src/components/TPricing.vue","../src/components/TPricing.vue","../src/components/TMarkdownEditor.vue","../src/components/TMarkdownEditor.vue","../src/components/TIcon.vue","../src/components/TIcon.vue","../src/plugin.ts","../src/types/contracts.ts"],"sourcesContent":["import type { InjectionKey } from 'vue';\n\nexport type AccordionType = 'single' | 'multiple';\n\nexport interface AccordionContext {\n type: AccordionType;\n disabled: boolean;\n collapsible: boolean;\n isItemOpen: (value: string) => boolean;\n toggleItem: (value: string) => void;\n registerTrigger: (value: string, el: HTMLElement) => void;\n unregisterTrigger: (value: string) => void;\n focusPrev: (value: string) => void;\n focusNext: (value: string) => void;\n focusFirst: () => void;\n focusLast: () => void;\n}\n\nexport const accordionInjectionKey: InjectionKey<AccordionContext> = Symbol('tree-accordion');\n","<script setup lang=\"ts\">\nimport { computed, provide, reactive } from 'vue';\nimport { type AccordionType, accordionInjectionKey } from './accordion';\n\nconst props = withDefaults(\n defineProps<{\n type?: AccordionType;\n modelValue?: string | string[];\n defaultValue?: string | string[];\n disabled?: boolean;\n collapsible?: boolean;\n }>(),\n {\n type: 'single',\n modelValue: undefined,\n defaultValue: undefined,\n disabled: false,\n collapsible: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string | string[] | undefined): void;\n}>();\n\n// Internal uncontrolled state\nconst internalValue = computed<string[]>(() => {\n const def = props.defaultValue;\n if (def === undefined) return [];\n return Array.isArray(def) ? def : [def];\n});\n\nconst uncontrolledValue = reactive<Set<string>>(new Set(internalValue.value));\n\nconst isControlled = computed(() => props.modelValue !== undefined);\n\nconst openValues = computed<Set<string>>(() => {\n if (isControlled.value) {\n const mv = props.modelValue!;\n return new Set(Array.isArray(mv) ? mv : [mv]);\n }\n return uncontrolledValue;\n});\n\nfunction isItemOpen(value: string): boolean {\n return openValues.value.has(value);\n}\n\nfunction emitUpdate(values: Set<string>) {\n if (props.type === 'single') {\n const arr = [...values];\n emit('update:modelValue', arr.length > 0 ? arr[0] : undefined);\n } else {\n emit('update:modelValue', [...values]);\n }\n}\n\nfunction toggleItem(value: string) {\n const currentlyOpen = isItemOpen(value);\n\n if (props.type === 'single') {\n if (currentlyOpen) {\n if (props.collapsible) {\n if (!isControlled.value) {\n uncontrolledValue.delete(value);\n }\n emitUpdate(new Set());\n }\n } else {\n if (!isControlled.value) {\n uncontrolledValue.clear();\n uncontrolledValue.add(value);\n }\n emitUpdate(new Set([value]));\n }\n } else {\n // Multiple mode\n const next = new Set(openValues.value);\n if (currentlyOpen) {\n next.delete(value);\n } else {\n next.add(value);\n }\n if (!isControlled.value) {\n if (currentlyOpen) {\n uncontrolledValue.delete(value);\n } else {\n uncontrolledValue.add(value);\n }\n }\n emitUpdate(next);\n }\n}\n\n// Keyboard navigation between triggers\nconst triggerMap = new Map<string, HTMLElement>();\nconst triggerOrder: string[] = reactive([]);\n\nfunction registerTrigger(value: string, el: HTMLElement) {\n if (!triggerMap.has(value)) {\n triggerOrder.push(value);\n }\n triggerMap.set(value, el);\n}\n\nfunction unregisterTrigger(value: string) {\n triggerMap.delete(value);\n const idx = triggerOrder.indexOf(value);\n if (idx !== -1) triggerOrder.splice(idx, 1);\n}\n\nfunction getEnabledTriggers(): string[] {\n return triggerOrder.filter((v) => {\n const el = triggerMap.get(v);\n return el && !el.hasAttribute('disabled');\n });\n}\n\nfunction focusPrev(value: string) {\n const enabled = getEnabledTriggers();\n const idx = enabled.indexOf(value);\n const prev = idx > 0 ? idx - 1 : enabled.length - 1;\n triggerMap.get(enabled[prev])?.focus();\n}\n\nfunction focusNext(value: string) {\n const enabled = getEnabledTriggers();\n const idx = enabled.indexOf(value);\n const next = idx < enabled.length - 1 ? idx + 1 : 0;\n triggerMap.get(enabled[next])?.focus();\n}\n\nfunction focusFirst() {\n const enabled = getEnabledTriggers();\n if (enabled.length) triggerMap.get(enabled[0])?.focus();\n}\n\nfunction focusLast() {\n const enabled = getEnabledTriggers();\n if (enabled.length) triggerMap.get(enabled[enabled.length - 1])?.focus();\n}\n\nprovide(accordionInjectionKey, {\n type: props.type,\n disabled: props.disabled,\n collapsible: props.collapsible,\n isItemOpen,\n toggleItem,\n registerTrigger,\n unregisterTrigger,\n focusPrev,\n focusNext,\n focusFirst,\n focusLast,\n});\n</script>\n\n<template>\n <div class=\"t-accordion\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, provide, reactive } from 'vue';\nimport { type AccordionType, accordionInjectionKey } from './accordion';\n\nconst props = withDefaults(\n defineProps<{\n type?: AccordionType;\n modelValue?: string | string[];\n defaultValue?: string | string[];\n disabled?: boolean;\n collapsible?: boolean;\n }>(),\n {\n type: 'single',\n modelValue: undefined,\n defaultValue: undefined,\n disabled: false,\n collapsible: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string | string[] | undefined): void;\n}>();\n\n// Internal uncontrolled state\nconst internalValue = computed<string[]>(() => {\n const def = props.defaultValue;\n if (def === undefined) return [];\n return Array.isArray(def) ? def : [def];\n});\n\nconst uncontrolledValue = reactive<Set<string>>(new Set(internalValue.value));\n\nconst isControlled = computed(() => props.modelValue !== undefined);\n\nconst openValues = computed<Set<string>>(() => {\n if (isControlled.value) {\n const mv = props.modelValue!;\n return new Set(Array.isArray(mv) ? mv : [mv]);\n }\n return uncontrolledValue;\n});\n\nfunction isItemOpen(value: string): boolean {\n return openValues.value.has(value);\n}\n\nfunction emitUpdate(values: Set<string>) {\n if (props.type === 'single') {\n const arr = [...values];\n emit('update:modelValue', arr.length > 0 ? arr[0] : undefined);\n } else {\n emit('update:modelValue', [...values]);\n }\n}\n\nfunction toggleItem(value: string) {\n const currentlyOpen = isItemOpen(value);\n\n if (props.type === 'single') {\n if (currentlyOpen) {\n if (props.collapsible) {\n if (!isControlled.value) {\n uncontrolledValue.delete(value);\n }\n emitUpdate(new Set());\n }\n } else {\n if (!isControlled.value) {\n uncontrolledValue.clear();\n uncontrolledValue.add(value);\n }\n emitUpdate(new Set([value]));\n }\n } else {\n // Multiple mode\n const next = new Set(openValues.value);\n if (currentlyOpen) {\n next.delete(value);\n } else {\n next.add(value);\n }\n if (!isControlled.value) {\n if (currentlyOpen) {\n uncontrolledValue.delete(value);\n } else {\n uncontrolledValue.add(value);\n }\n }\n emitUpdate(next);\n }\n}\n\n// Keyboard navigation between triggers\nconst triggerMap = new Map<string, HTMLElement>();\nconst triggerOrder: string[] = reactive([]);\n\nfunction registerTrigger(value: string, el: HTMLElement) {\n if (!triggerMap.has(value)) {\n triggerOrder.push(value);\n }\n triggerMap.set(value, el);\n}\n\nfunction unregisterTrigger(value: string) {\n triggerMap.delete(value);\n const idx = triggerOrder.indexOf(value);\n if (idx !== -1) triggerOrder.splice(idx, 1);\n}\n\nfunction getEnabledTriggers(): string[] {\n return triggerOrder.filter((v) => {\n const el = triggerMap.get(v);\n return el && !el.hasAttribute('disabled');\n });\n}\n\nfunction focusPrev(value: string) {\n const enabled = getEnabledTriggers();\n const idx = enabled.indexOf(value);\n const prev = idx > 0 ? idx - 1 : enabled.length - 1;\n triggerMap.get(enabled[prev])?.focus();\n}\n\nfunction focusNext(value: string) {\n const enabled = getEnabledTriggers();\n const idx = enabled.indexOf(value);\n const next = idx < enabled.length - 1 ? idx + 1 : 0;\n triggerMap.get(enabled[next])?.focus();\n}\n\nfunction focusFirst() {\n const enabled = getEnabledTriggers();\n if (enabled.length) triggerMap.get(enabled[0])?.focus();\n}\n\nfunction focusLast() {\n const enabled = getEnabledTriggers();\n if (enabled.length) triggerMap.get(enabled[enabled.length - 1])?.focus();\n}\n\nprovide(accordionInjectionKey, {\n type: props.type,\n disabled: props.disabled,\n collapsible: props.collapsible,\n isItemOpen,\n toggleItem,\n registerTrigger,\n unregisterTrigger,\n focusPrev,\n focusNext,\n focusFirst,\n focusLast,\n});\n</script>\n\n<template>\n <div class=\"t-accordion\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onMounted, onBeforeUnmount, ref, useId } from 'vue';\nimport { accordionInjectionKey } from './accordion';\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n }>(),\n {\n disabled: false,\n },\n);\n\nconst injected = inject(accordionInjectionKey);\n\nif (!injected) {\n throw new Error('[TreeUI] TAccordionItem must be used inside a TAccordion.');\n}\n\nconst ctx = injected;\n\nconst triggerId = useId();\nconst panelId = useId();\nconst triggerRef = ref<HTMLButtonElement | null>(null);\n\nconst isOpen = computed(() => ctx.isItemOpen(props.value));\nconst isDisabled = computed(() => props.disabled || ctx.disabled);\n\nconst itemClasses = computed(() => [\n 't-accordion__item',\n {\n 'is-open': isOpen.value,\n 'is-disabled': isDisabled.value,\n },\n]);\n\nfunction handleToggle() {\n if (isDisabled.value) return;\n ctx.toggleItem(props.value);\n}\n\nfunction handleKeydown(event: KeyboardEvent) {\n if (isDisabled.value) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n ctx.focusNext(props.value);\n break;\n case 'ArrowUp':\n event.preventDefault();\n ctx.focusPrev(props.value);\n break;\n case 'Home':\n event.preventDefault();\n ctx.focusFirst();\n break;\n case 'End':\n event.preventDefault();\n ctx.focusLast();\n break;\n }\n}\n\nonMounted(() => {\n if (triggerRef.value) {\n ctx.registerTrigger(props.value, triggerRef.value);\n }\n});\n\nonBeforeUnmount(() => {\n ctx.unregisterTrigger(props.value);\n});\n</script>\n\n<template>\n <div :class=\"itemClasses\">\n <h3 class=\"t-accordion__heading\">\n <button\n :id=\"triggerId\"\n ref=\"triggerRef\"\n type=\"button\"\n class=\"t-accordion__trigger\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"panelId\"\n :disabled=\"isDisabled || undefined\"\n @click=\"handleToggle\"\n @keydown=\"handleKeydown\"\n >\n <slot\n name=\"trigger\"\n :open=\"isOpen\"\n >\n {{ value }}\n </slot>\n <svg\n class=\"t-accordion__icon\"\n :class=\"{ 'is-open': isOpen }\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n </h3>\n <div\n v-if=\"isOpen\"\n :id=\"panelId\"\n role=\"region\"\n :aria-labelledby=\"triggerId\"\n class=\"t-accordion__content\"\n >\n <div class=\"t-accordion__panel\">\n <slot />\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onMounted, onBeforeUnmount, ref, useId } from 'vue';\nimport { accordionInjectionKey } from './accordion';\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n }>(),\n {\n disabled: false,\n },\n);\n\nconst injected = inject(accordionInjectionKey);\n\nif (!injected) {\n throw new Error('[TreeUI] TAccordionItem must be used inside a TAccordion.');\n}\n\nconst ctx = injected;\n\nconst triggerId = useId();\nconst panelId = useId();\nconst triggerRef = ref<HTMLButtonElement | null>(null);\n\nconst isOpen = computed(() => ctx.isItemOpen(props.value));\nconst isDisabled = computed(() => props.disabled || ctx.disabled);\n\nconst itemClasses = computed(() => [\n 't-accordion__item',\n {\n 'is-open': isOpen.value,\n 'is-disabled': isDisabled.value,\n },\n]);\n\nfunction handleToggle() {\n if (isDisabled.value) return;\n ctx.toggleItem(props.value);\n}\n\nfunction handleKeydown(event: KeyboardEvent) {\n if (isDisabled.value) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n ctx.focusNext(props.value);\n break;\n case 'ArrowUp':\n event.preventDefault();\n ctx.focusPrev(props.value);\n break;\n case 'Home':\n event.preventDefault();\n ctx.focusFirst();\n break;\n case 'End':\n event.preventDefault();\n ctx.focusLast();\n break;\n }\n}\n\nonMounted(() => {\n if (triggerRef.value) {\n ctx.registerTrigger(props.value, triggerRef.value);\n }\n});\n\nonBeforeUnmount(() => {\n ctx.unregisterTrigger(props.value);\n});\n</script>\n\n<template>\n <div :class=\"itemClasses\">\n <h3 class=\"t-accordion__heading\">\n <button\n :id=\"triggerId\"\n ref=\"triggerRef\"\n type=\"button\"\n class=\"t-accordion__trigger\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"panelId\"\n :disabled=\"isDisabled || undefined\"\n @click=\"handleToggle\"\n @keydown=\"handleKeydown\"\n >\n <slot\n name=\"trigger\"\n :open=\"isOpen\"\n >\n {{ value }}\n </slot>\n <svg\n class=\"t-accordion__icon\"\n :class=\"{ 'is-open': isOpen }\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n </h3>\n <div\n v-if=\"isOpen\"\n :id=\"panelId\"\n role=\"region\"\n :aria-labelledby=\"triggerId\"\n class=\"t-accordion__content\"\n >\n <div class=\"t-accordion__panel\">\n <slot />\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nexport type TAlertVariant = 'info' | 'success' | 'warning' | 'danger';\n\nconst props = withDefaults(\n defineProps<{\n variant?: TAlertVariant;\n size?: TSize;\n dismissible?: boolean;\n }>(),\n {\n variant: 'info',\n size: 'md',\n dismissible: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'dismiss'): void;\n}>();\n\nconst classes = computed(() => [\n 't-alert',\n `t-alert--${props.variant}`,\n `t-alert--${props.size}`,\n]);\n\nfunction handleDismiss() {\n emit('dismiss');\n}\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"alert\"\n >\n <span\n v-if=\"$slots.icon\"\n class=\"t-alert__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <div class=\"t-alert__content\">\n <slot />\n </div>\n <button\n v-if=\"dismissible\"\n type=\"button\"\n class=\"t-alert__dismiss\"\n aria-label=\"Dismiss\"\n @click=\"handleDismiss\"\n >\n <slot name=\"dismiss-icon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nexport type TAlertVariant = 'info' | 'success' | 'warning' | 'danger';\n\nconst props = withDefaults(\n defineProps<{\n variant?: TAlertVariant;\n size?: TSize;\n dismissible?: boolean;\n }>(),\n {\n variant: 'info',\n size: 'md',\n dismissible: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'dismiss'): void;\n}>();\n\nconst classes = computed(() => [\n 't-alert',\n `t-alert--${props.variant}`,\n `t-alert--${props.size}`,\n]);\n\nfunction handleDismiss() {\n emit('dismiss');\n}\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"alert\"\n >\n <span\n v-if=\"$slots.icon\"\n class=\"t-alert__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <div class=\"t-alert__content\">\n <slot />\n </div>\n <button\n v-if=\"dismissible\"\n type=\"button\"\n class=\"t-alert__dismiss\"\n aria-label=\"Dismiss\"\n @click=\"handleDismiss\"\n >\n <slot name=\"dismiss-icon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize, TVariant } from '../types/contracts';\n\nconst _treeBadgeTones = ['neutral', 'success', 'warning', 'danger', 'info'] as const;\n\nexport type TBadgeTone = (typeof _treeBadgeTones)[number];\n\nconst props = withDefaults(\n defineProps<{\n variant?: TVariant;\n size?: TSize;\n tone?: TBadgeTone;\n }>(),\n {\n variant: 'soft',\n size: 'md',\n tone: 'neutral',\n },\n);\n\nconst classes = computed(() => [\n 't-badge',\n `t-badge--${props.variant}`,\n `t-badge--${props.size}`,\n `t-badge--tone-${props.tone}`,\n]);\n</script>\n\n<template>\n <span :class=\"classes\">\n <span\n v-if=\"$slots.icon\"\n class=\"t-badge__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <slot />\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize, TVariant } from '../types/contracts';\n\nconst _treeBadgeTones = ['neutral', 'success', 'warning', 'danger', 'info'] as const;\n\nexport type TBadgeTone = (typeof _treeBadgeTones)[number];\n\nconst props = withDefaults(\n defineProps<{\n variant?: TVariant;\n size?: TSize;\n tone?: TBadgeTone;\n }>(),\n {\n variant: 'soft',\n size: 'md',\n tone: 'neutral',\n },\n);\n\nconst classes = computed(() => [\n 't-badge',\n `t-badge--${props.variant}`,\n `t-badge--${props.size}`,\n `t-badge--tone-${props.tone}`,\n]);\n</script>\n\n<template>\n <span :class=\"classes\">\n <span\n v-if=\"$slots.icon\"\n class=\"t-badge__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <slot />\n </span>\n</template>\n","<script setup lang=\"ts\">\nconst props = withDefaults(\n defineProps<{\n /**\n * Character or string used to visually separate breadcrumb items.\n */\n separator?: string;\n }>(),\n {\n separator: '/',\n },\n);\n</script>\n\n<template>\n <nav\n aria-label=\"Breadcrumb\"\n class=\"t-breadcrumb\"\n >\n <ol\n class=\"t-breadcrumb__list\"\n :style=\"{ '--tree-breadcrumb-separator': `'${props.separator}'` }\"\n >\n <slot />\n </ol>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nconst props = withDefaults(\n defineProps<{\n /**\n * Character or string used to visually separate breadcrumb items.\n */\n separator?: string;\n }>(),\n {\n separator: '/',\n },\n);\n</script>\n\n<template>\n <nav\n aria-label=\"Breadcrumb\"\n class=\"t-breadcrumb\"\n >\n <ol\n class=\"t-breadcrumb__list\"\n :style=\"{ '--tree-breadcrumb-separator': `'${props.separator}'` }\"\n >\n <slot />\n </ol>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, type Component } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n /**\n * URL the breadcrumb item links to. Omit for the current/last item.\n */\n href?: string;\n /**\n * Route target. When provided and vue-router is available, renders RouterLink.\n */\n to?: string | Record<string, unknown>;\n /**\n * Marks this item as the current page. Automatically set if it's the last item without href.\n */\n current?: boolean;\n }>(),\n {\n href: undefined,\n to: undefined,\n current: false,\n },\n);\n\nconst instance = getCurrentInstance();\n\nconst routerLinkComponent = computed<Component | null>(() => {\n if (!props.to) return null;\n\n return (instance?.appContext.components.RouterLink as Component | undefined) ?? null;\n});\n\nconst hasRouterLink = computed(() => {\n return Boolean(routerLinkComponent.value);\n});\n\nconst canRenderLink = computed(() => {\n if (props.href) return true;\n if (typeof props.to === 'string') return true;\n return Boolean(props.to && hasRouterLink.value);\n});\n\nconst isCurrent = computed(() => props.current || !canRenderLink.value);\n\nconst tag = computed<string | Component>(() => {\n if (props.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n\n return 'a';\n});\n\nconst linkProps = computed(() => {\n if (props.to && hasRouterLink.value) {\n return { to: props.to };\n }\n\n return {\n href: props.href ?? (typeof props.to === 'string' ? props.to : undefined),\n };\n});\n</script>\n\n<template>\n <li class=\"t-breadcrumb__item\">\n <component\n :is=\"tag\"\n v-if=\"!isCurrent\"\n v-bind=\"linkProps\"\n class=\"t-breadcrumb__link\"\n >\n <slot />\n </component>\n <span\n v-else\n class=\"t-breadcrumb__current\"\n aria-current=\"page\"\n >\n <slot />\n </span>\n </li>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, type Component } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n /**\n * URL the breadcrumb item links to. Omit for the current/last item.\n */\n href?: string;\n /**\n * Route target. When provided and vue-router is available, renders RouterLink.\n */\n to?: string | Record<string, unknown>;\n /**\n * Marks this item as the current page. Automatically set if it's the last item without href.\n */\n current?: boolean;\n }>(),\n {\n href: undefined,\n to: undefined,\n current: false,\n },\n);\n\nconst instance = getCurrentInstance();\n\nconst routerLinkComponent = computed<Component | null>(() => {\n if (!props.to) return null;\n\n return (instance?.appContext.components.RouterLink as Component | undefined) ?? null;\n});\n\nconst hasRouterLink = computed(() => {\n return Boolean(routerLinkComponent.value);\n});\n\nconst canRenderLink = computed(() => {\n if (props.href) return true;\n if (typeof props.to === 'string') return true;\n return Boolean(props.to && hasRouterLink.value);\n});\n\nconst isCurrent = computed(() => props.current || !canRenderLink.value);\n\nconst tag = computed<string | Component>(() => {\n if (props.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n\n return 'a';\n});\n\nconst linkProps = computed(() => {\n if (props.to && hasRouterLink.value) {\n return { to: props.to };\n }\n\n return {\n href: props.href ?? (typeof props.to === 'string' ? props.to : undefined),\n };\n});\n</script>\n\n<template>\n <li class=\"t-breadcrumb__item\">\n <component\n :is=\"tag\"\n v-if=\"!isCurrent\"\n v-bind=\"linkProps\"\n class=\"t-breadcrumb__link\"\n >\n <slot />\n </component>\n <span\n v-else\n class=\"t-breadcrumb__current\"\n aria-current=\"page\"\n >\n <slot />\n </span>\n </li>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n size?: TSize;\n label?: string;\n }>(),\n {\n size: 'md',\n label: 'Loading',\n },\n);\n\nconst classes = computed(() => ['t-spinner', `t-spinner--${props.size}`]);\n</script>\n\n<template>\n <span\n :class=\"classes\"\n role=\"status\"\n :aria-label=\"label\"\n >\n <span\n class=\"t-spinner__ring\"\n aria-hidden=\"true\"\n />\n <span class=\"t-visually-hidden\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n size?: TSize;\n label?: string;\n }>(),\n {\n size: 'md',\n label: 'Loading',\n },\n);\n\nconst classes = computed(() => ['t-spinner', `t-spinner--${props.size}`]);\n</script>\n\n<template>\n <span\n :class=\"classes\"\n role=\"status\"\n :aria-label=\"label\"\n >\n <span\n class=\"t-spinner__ring\"\n aria-hidden=\"true\"\n />\n <span class=\"t-visually-hidden\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { tv } from '@treeui/utils';\nimport type { TSize, TVariant } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TVariant;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n type?: 'button' | 'submit' | 'reset';\n }>(),\n {\n as: 'button',\n variant: 'solid',\n size: 'md',\n disabled: false,\n loading: false,\n type: 'button',\n },\n);\n\nconst emit = defineEmits<{\n click: [event: MouseEvent];\n}>();\n\nconst buttonClass = tv({\n base: 't-button',\n variants: {\n variant: {\n solid: 't-button--solid',\n outline: 't-button--outline',\n ghost: 't-button--ghost',\n soft: 't-button--soft',\n danger: 't-button--danger',\n },\n size: {\n sm: 't-button--sm',\n md: 't-button--md',\n lg: 't-button--lg',\n },\n },\n});\n\nconst isNativeButton = computed(() => props.as === 'button');\nconst isDisabled = computed(() => props.disabled || props.loading);\nconst classes = computed(() =>\n buttonClass({\n variant: props.variant,\n size: props.size,\n class: {\n 'is-loading': props.loading,\n 'is-disabled': isDisabled.value,\n },\n }),\n);\n\nconst onClick = (event: MouseEvent) => {\n if (isDisabled.value) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n emit('click', event);\n};\n</script>\n\n<template>\n <component\n :is=\"as\"\n :type=\"isNativeButton ? type : undefined\"\n :class=\"classes\"\n :disabled=\"isNativeButton ? isDisabled : undefined\"\n :aria-disabled=\"!isNativeButton && isDisabled ? 'true' : undefined\"\n :aria-busy=\"loading || undefined\"\n :tabindex=\"!isNativeButton && isDisabled ? -1 : undefined\"\n @click=\"onClick\"\n >\n <span\n v-if=\"loading\"\n class=\"t-button__spinner\"\n >\n <TSpinner\n size=\"sm\"\n label=\"Loading\"\n />\n </span>\n <span\n v-if=\"$slots.icon\"\n class=\"t-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span class=\"t-button__label\">\n <slot />\n </span>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { tv } from '@treeui/utils';\nimport type { TSize, TVariant } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TVariant;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n type?: 'button' | 'submit' | 'reset';\n }>(),\n {\n as: 'button',\n variant: 'solid',\n size: 'md',\n disabled: false,\n loading: false,\n type: 'button',\n },\n);\n\nconst emit = defineEmits<{\n click: [event: MouseEvent];\n}>();\n\nconst buttonClass = tv({\n base: 't-button',\n variants: {\n variant: {\n solid: 't-button--solid',\n outline: 't-button--outline',\n ghost: 't-button--ghost',\n soft: 't-button--soft',\n danger: 't-button--danger',\n },\n size: {\n sm: 't-button--sm',\n md: 't-button--md',\n lg: 't-button--lg',\n },\n },\n});\n\nconst isNativeButton = computed(() => props.as === 'button');\nconst isDisabled = computed(() => props.disabled || props.loading);\nconst classes = computed(() =>\n buttonClass({\n variant: props.variant,\n size: props.size,\n class: {\n 'is-loading': props.loading,\n 'is-disabled': isDisabled.value,\n },\n }),\n);\n\nconst onClick = (event: MouseEvent) => {\n if (isDisabled.value) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n emit('click', event);\n};\n</script>\n\n<template>\n <component\n :is=\"as\"\n :type=\"isNativeButton ? type : undefined\"\n :class=\"classes\"\n :disabled=\"isNativeButton ? isDisabled : undefined\"\n :aria-disabled=\"!isNativeButton && isDisabled ? 'true' : undefined\"\n :aria-busy=\"loading || undefined\"\n :tabindex=\"!isNativeButton && isDisabled ? -1 : undefined\"\n @click=\"onClick\"\n >\n <span\n v-if=\"loading\"\n class=\"t-button__spinner\"\n >\n <TSpinner\n size=\"sm\"\n label=\"Loading\"\n />\n </span>\n <span\n v-if=\"$slots.icon\"\n class=\"t-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span class=\"t-button__label\">\n <slot />\n </span>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TCardVariant, TSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TCardVariant;\n size?: TSize;\n title?: string;\n }>(),\n {\n as: 'section',\n variant: 'outline',\n size: 'md',\n title: undefined,\n },\n);\n\nconst classes = computed(() => [\n 't-card',\n `t-card--${props.variant}`,\n `t-card--${props.size}`,\n]);\n\nconst hasHeader = computed(() => !!props.title);\n</script>\n\n<template>\n <component\n :is=\"as\"\n :class=\"classes\"\n >\n <header\n v-if=\"$slots.header || hasHeader || $slots.actions\"\n class=\"t-card__header\"\n >\n <slot name=\"header\">\n <span\n v-if=\"title\"\n class=\"t-card__title\"\n >\n {{ title }}\n </span>\n <span\n v-if=\"$slots.actions\"\n class=\"t-card__actions\"\n >\n <slot name=\"actions\" />\n </span>\n </slot>\n </header>\n <div class=\"t-card__body\">\n <slot />\n </div>\n <footer\n v-if=\"$slots.footer\"\n class=\"t-card__footer\"\n >\n <slot name=\"footer\" />\n </footer>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TCardVariant, TSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TCardVariant;\n size?: TSize;\n title?: string;\n }>(),\n {\n as: 'section',\n variant: 'outline',\n size: 'md',\n title: undefined,\n },\n);\n\nconst classes = computed(() => [\n 't-card',\n `t-card--${props.variant}`,\n `t-card--${props.size}`,\n]);\n\nconst hasHeader = computed(() => !!props.title);\n</script>\n\n<template>\n <component\n :is=\"as\"\n :class=\"classes\"\n >\n <header\n v-if=\"$slots.header || hasHeader || $slots.actions\"\n class=\"t-card__header\"\n >\n <slot name=\"header\">\n <span\n v-if=\"title\"\n class=\"t-card__title\"\n >\n {{ title }}\n </span>\n <span\n v-if=\"$slots.actions\"\n class=\"t-card__actions\"\n >\n <slot name=\"actions\" />\n </span>\n </slot>\n </header>\n <div class=\"t-card__body\">\n <slot />\n </div>\n <footer\n v-if=\"$slots.footer\"\n class=\"t-card__footer\"\n >\n <slot name=\"footer\" />\n </footer>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean;\n size?: TSize;\n disabled?: boolean;\n indeterminate?: boolean;\n invalid?: boolean;\n }>(),\n {\n modelValue: false,\n size: 'md',\n disabled: false,\n indeterminate: false,\n invalid: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nwatch(\n () => props.indeterminate,\n (val) => {\n if (inputRef.value) {\n inputRef.value.indeterminate = val;\n }\n },\n);\n\nwatch(inputRef, (el) => {\n if (el) {\n el.indeterminate = props.indeterminate;\n }\n});\n\nconst rootClasses = computed(() => [\n 't-checkbox',\n `t-checkbox--${props.size}`,\n {\n 'is-checked': props.modelValue,\n 'is-indeterminate': props.indeterminate,\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n emit('update:modelValue', !props.modelValue);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n ref=\"inputRef\"\n v-bind=\"inputAttrs\"\n type=\"checkbox\"\n class=\"t-checkbox__input\"\n :checked=\"modelValue\"\n :disabled=\"disabled\"\n :aria-checked=\"indeterminate ? 'mixed' : modelValue\"\n :aria-invalid=\"invalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"t-checkbox__control\"\n aria-hidden=\"true\"\n >\n <svg\n v-if=\"modelValue && !indeterminate\"\n class=\"t-checkbox__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n <svg\n v-else-if=\"indeterminate\"\n class=\"t-checkbox__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n >\n <line\n x1=\"4\"\n y1=\"8\"\n x2=\"12\"\n y2=\"8\"\n />\n </svg>\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"t-checkbox__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean;\n size?: TSize;\n disabled?: boolean;\n indeterminate?: boolean;\n invalid?: boolean;\n }>(),\n {\n modelValue: false,\n size: 'md',\n disabled: false,\n indeterminate: false,\n invalid: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nwatch(\n () => props.indeterminate,\n (val) => {\n if (inputRef.value) {\n inputRef.value.indeterminate = val;\n }\n },\n);\n\nwatch(inputRef, (el) => {\n if (el) {\n el.indeterminate = props.indeterminate;\n }\n});\n\nconst rootClasses = computed(() => [\n 't-checkbox',\n `t-checkbox--${props.size}`,\n {\n 'is-checked': props.modelValue,\n 'is-indeterminate': props.indeterminate,\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n emit('update:modelValue', !props.modelValue);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n ref=\"inputRef\"\n v-bind=\"inputAttrs\"\n type=\"checkbox\"\n class=\"t-checkbox__input\"\n :checked=\"modelValue\"\n :disabled=\"disabled\"\n :aria-checked=\"indeterminate ? 'mixed' : modelValue\"\n :aria-invalid=\"invalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"t-checkbox__control\"\n aria-hidden=\"true\"\n >\n <svg\n v-if=\"modelValue && !indeterminate\"\n class=\"t-checkbox__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n <svg\n v-else-if=\"indeterminate\"\n class=\"t-checkbox__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n >\n <line\n x1=\"4\"\n y1=\"8\"\n x2=\"12\"\n y2=\"8\"\n />\n </svg>\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"t-checkbox__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","import { computed, ref, type Ref } from 'vue';\n\nexport const useControllableOpen = (\n controlledValue: Ref<boolean | undefined>,\n defaultValue: boolean,\n onChange: (value: boolean) => void,\n) => {\n const uncontrolledValue = ref(defaultValue);\n\n const value = computed(() => controlledValue.value ?? uncontrolledValue.value);\n\n const setValue = (nextValue: boolean) => {\n if (nextValue === value.value) {\n return;\n }\n\n if (controlledValue.value === undefined) {\n uncontrolledValue.value = nextValue;\n }\n\n onChange(nextValue);\n };\n\n return {\n value,\n setValue,\n };\n};\n\n","<script setup lang=\"ts\">\nimport { createId, isEscapeKey } from '@treeui/utils';\nimport { computed, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TComboboxOption {\n label: string;\n value: string;\n description?: string;\n keywords?: string[];\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n options?: TComboboxOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n emptyText?: string;\n }>(),\n {\n modelValue: '',\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n emptyText: 'No results found.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n 'input-change': [value: string];\n}>();\n\ndefineSlots<{\n prefix?: () => unknown;\n option?: (props: {\n option: TComboboxOption;\n selected: boolean;\n active: boolean;\n }) => unknown;\n empty?: (props: { query: string }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('t-combobox');\nconst rootRef = ref<HTMLElement | null>(null);\nconst activeIndex = ref(-1);\nconst query = ref('');\n\nconst normalize = (value: string) => value.trim().toLowerCase();\nconst getOptionId = (value: string) => `${listboxId}-option-${value}`;\n\nconst selectedOption = computed(() =>\n props.options.find((option) => option.value === props.modelValue),\n);\n\nconst selectedLabel = computed(() => selectedOption.value?.label ?? '');\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, autocomplete, ...rest } = attrs;\n return {\n autocomplete: typeof autocomplete === 'string' ? autocomplete : 'off',\n ...rest,\n };\n});\n\nconst listboxLabel = computed(() =>\n typeof attrs['aria-label'] === 'string' ? attrs['aria-label'] : undefined,\n);\n\nconst listboxLabelledby = computed(() =>\n typeof attrs['aria-labelledby'] === 'string' ? attrs['aria-labelledby'] : undefined,\n);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-combobox',\n `t-combobox--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst filteredOptions = computed(() => {\n const normalizedQuery = normalize(query.value);\n\n if (!normalizedQuery) {\n return props.options;\n }\n\n return props.options.filter((option) => {\n const fields = [\n option.label,\n option.description ?? '',\n ...(option.keywords ?? []),\n ];\n\n return fields.some((field) => field.toLowerCase().includes(normalizedQuery));\n });\n});\n\nconst enabledFilteredIndexes = computed(() =>\n filteredOptions.value.reduce<number[]>((indexes, option, index) => {\n if (!option.disabled) {\n indexes.push(index);\n }\n\n return indexes;\n }, []),\n);\n\nconst activeOption = computed(() =>\n activeIndex.value >= 0 ? filteredOptions.value[activeIndex.value] : undefined,\n);\n\nconst activeDescendant = computed(() =>\n isOpen.value && activeOption.value ? getOptionId(activeOption.value.value) : undefined,\n);\n\nconst syncQueryFromSelection = () => {\n query.value = selectedLabel.value;\n};\n\nconst setInitialActiveIndex = (fallback: 'first' | 'last' = 'first') => {\n const selectedIndex = filteredOptions.value.findIndex((option) =>\n option.value === props.modelValue && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n activeIndex.value = selectedIndex;\n return;\n }\n\n if (enabledFilteredIndexes.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n activeIndex.value =\n fallback === 'last'\n ? enabledFilteredIndexes.value[enabledFilteredIndexes.value.length - 1]\n : enabledFilteredIndexes.value[0];\n};\n\nconst moveActive = (direction: 1 | -1) => {\n if (enabledFilteredIndexes.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const currentEnabledIndex = enabledFilteredIndexes.value.indexOf(activeIndex.value);\n\n if (currentEnabledIndex === -1) {\n activeIndex.value =\n direction === 1\n ? enabledFilteredIndexes.value[0]\n : enabledFilteredIndexes.value[enabledFilteredIndexes.value.length - 1];\n return;\n }\n\n const nextEnabledIndex = currentEnabledIndex + direction;\n\n if (nextEnabledIndex < 0 || nextEnabledIndex >= enabledFilteredIndexes.value.length) {\n return;\n }\n\n activeIndex.value = enabledFilteredIndexes.value[nextEnabledIndex];\n};\n\nconst openListbox = (fallback: 'first' | 'last' = 'first') => {\n if (props.disabled) {\n return;\n }\n\n setValue(true);\n setInitialActiveIndex(fallback);\n};\n\nconst commitPendingClear = () => {\n if (query.value.trim() !== '' || !props.modelValue) {\n return false;\n }\n\n emit('update:modelValue', '');\n return true;\n};\n\nconst closeListbox = (restoreSelection = false) => {\n setValue(false);\n activeIndex.value = -1;\n\n if (!restoreSelection) {\n return;\n }\n\n if (commitPendingClear()) {\n return;\n }\n\n if (selectedLabel.value && query.value !== selectedLabel.value) {\n query.value = selectedLabel.value;\n }\n};\n\nconst selectOption = (option: TComboboxOption) => {\n if (option.disabled) {\n return;\n }\n\n query.value = option.label;\n emit('update:modelValue', option.value);\n closeListbox(false);\n};\n\nconst onInput = (event: Event) => {\n query.value = (event.target as HTMLInputElement).value;\n emit('input-change', query.value);\n\n if (props.disabled) {\n return;\n }\n\n if (!isOpen.value) {\n openListbox('first');\n return;\n }\n\n setInitialActiveIndex('first');\n};\n\nconst onInputFocus = () => {\n openListbox('first');\n};\n\nconst onInputClick = () => {\n if (!isOpen.value) {\n openListbox('first');\n }\n};\n\nconst onInputKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event)) {\n if (isOpen.value) {\n event.preventDefault();\n closeListbox(true);\n }\n\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('first');\n } else {\n moveActive(1);\n }\n break;\n case 'ArrowUp':\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('last');\n } else {\n moveActive(-1);\n }\n break;\n case 'Enter':\n if (isOpen.value && activeOption.value && !activeOption.value.disabled) {\n event.preventDefault();\n selectOption(activeOption.value);\n }\n break;\n case 'Home':\n if (!isOpen.value) return;\n event.preventDefault();\n setInitialActiveIndex('first');\n break;\n case 'End':\n if (!isOpen.value) return;\n event.preventDefault();\n setInitialActiveIndex('last');\n break;\n case 'Tab':\n closeListbox(true);\n break;\n default:\n break;\n }\n};\n\nconst onOptionPointerEnter = (index: number) => {\n const option = filteredOptions.value[index];\n\n if (option && !option.disabled) {\n activeIndex.value = index;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeListbox(true);\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nwatch(\n () => props.modelValue,\n () => {\n if (!isOpen.value) {\n syncQueryFromSelection();\n }\n },\n { immediate: true },\n);\n\nwatch(\n () => props.options,\n () => {\n if (!isOpen.value) {\n syncQueryFromSelection();\n return;\n }\n\n setInitialActiveIndex('first');\n },\n { deep: true },\n);\n\nwatch(filteredOptions, () => {\n if (!isOpen.value) {\n return;\n }\n\n if (filteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const current = filteredOptions.value[activeIndex.value];\n\n if (!current || current.disabled) {\n setInitialActiveIndex('first');\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div class=\"t-combobox__control\">\n <span\n v-if=\"$slots.prefix\"\n class=\"t-combobox__slot t-combobox__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-combobox__input\"\n role=\"combobox\"\n type=\"text\"\n :value=\"query\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n :aria-expanded=\"isOpen\"\n :aria-activedescendant=\"activeDescendant\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n @input=\"onInput\"\n @focus=\"onInputFocus\"\n @click=\"onInputClick\"\n @keydown=\"onInputKeydown\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <svg\n v-else\n class=\"t-combobox__indicator\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </div>\n\n <transition name=\"t-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"listboxId\"\n role=\"listbox\"\n class=\"t-combobox__listbox\"\n :aria-label=\"listboxLabel\"\n :aria-labelledby=\"listboxLabelledby\"\n >\n <li\n v-if=\"filteredOptions.length === 0\"\n class=\"t-combobox__empty\"\n >\n <slot\n name=\"empty\"\n :query=\"query\"\n >\n {{ emptyText }}\n </slot>\n </li>\n\n <template v-else>\n <li\n v-for=\"(option, index) in filteredOptions\"\n :id=\"getOptionId(option.value)\"\n :key=\"option.value\"\n role=\"option\"\n class=\"t-combobox__option\"\n :class=\"{\n 'is-active': index === activeIndex,\n 'is-disabled': option.disabled,\n 'is-selected': option.value === modelValue,\n }\"\n :aria-selected=\"option.value === modelValue\"\n :aria-disabled=\"option.disabled || undefined\"\n @mouseenter=\"onOptionPointerEnter(index)\"\n @click=\"selectOption(option)\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"option.value === modelValue\"\n :active=\"index === activeIndex\"\n >\n <span class=\"t-combobox__option-copy\">\n <span class=\"t-combobox__option-label\">{{ option.label }}</span>\n <span\n v-if=\"option.description\"\n class=\"t-combobox__option-description\"\n >\n {{ option.description }}\n </span>\n </span>\n <svg\n v-if=\"option.value === modelValue\"\n class=\"t-combobox__check\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n </slot>\n </li>\n </template>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isEscapeKey } from '@treeui/utils';\nimport { computed, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TComboboxOption {\n label: string;\n value: string;\n description?: string;\n keywords?: string[];\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n options?: TComboboxOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n emptyText?: string;\n }>(),\n {\n modelValue: '',\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n emptyText: 'No results found.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n 'input-change': [value: string];\n}>();\n\ndefineSlots<{\n prefix?: () => unknown;\n option?: (props: {\n option: TComboboxOption;\n selected: boolean;\n active: boolean;\n }) => unknown;\n empty?: (props: { query: string }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('t-combobox');\nconst rootRef = ref<HTMLElement | null>(null);\nconst activeIndex = ref(-1);\nconst query = ref('');\n\nconst normalize = (value: string) => value.trim().toLowerCase();\nconst getOptionId = (value: string) => `${listboxId}-option-${value}`;\n\nconst selectedOption = computed(() =>\n props.options.find((option) => option.value === props.modelValue),\n);\n\nconst selectedLabel = computed(() => selectedOption.value?.label ?? '');\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, autocomplete, ...rest } = attrs;\n return {\n autocomplete: typeof autocomplete === 'string' ? autocomplete : 'off',\n ...rest,\n };\n});\n\nconst listboxLabel = computed(() =>\n typeof attrs['aria-label'] === 'string' ? attrs['aria-label'] : undefined,\n);\n\nconst listboxLabelledby = computed(() =>\n typeof attrs['aria-labelledby'] === 'string' ? attrs['aria-labelledby'] : undefined,\n);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-combobox',\n `t-combobox--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst filteredOptions = computed(() => {\n const normalizedQuery = normalize(query.value);\n\n if (!normalizedQuery) {\n return props.options;\n }\n\n return props.options.filter((option) => {\n const fields = [\n option.label,\n option.description ?? '',\n ...(option.keywords ?? []),\n ];\n\n return fields.some((field) => field.toLowerCase().includes(normalizedQuery));\n });\n});\n\nconst enabledFilteredIndexes = computed(() =>\n filteredOptions.value.reduce<number[]>((indexes, option, index) => {\n if (!option.disabled) {\n indexes.push(index);\n }\n\n return indexes;\n }, []),\n);\n\nconst activeOption = computed(() =>\n activeIndex.value >= 0 ? filteredOptions.value[activeIndex.value] : undefined,\n);\n\nconst activeDescendant = computed(() =>\n isOpen.value && activeOption.value ? getOptionId(activeOption.value.value) : undefined,\n);\n\nconst syncQueryFromSelection = () => {\n query.value = selectedLabel.value;\n};\n\nconst setInitialActiveIndex = (fallback: 'first' | 'last' = 'first') => {\n const selectedIndex = filteredOptions.value.findIndex((option) =>\n option.value === props.modelValue && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n activeIndex.value = selectedIndex;\n return;\n }\n\n if (enabledFilteredIndexes.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n activeIndex.value =\n fallback === 'last'\n ? enabledFilteredIndexes.value[enabledFilteredIndexes.value.length - 1]\n : enabledFilteredIndexes.value[0];\n};\n\nconst moveActive = (direction: 1 | -1) => {\n if (enabledFilteredIndexes.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const currentEnabledIndex = enabledFilteredIndexes.value.indexOf(activeIndex.value);\n\n if (currentEnabledIndex === -1) {\n activeIndex.value =\n direction === 1\n ? enabledFilteredIndexes.value[0]\n : enabledFilteredIndexes.value[enabledFilteredIndexes.value.length - 1];\n return;\n }\n\n const nextEnabledIndex = currentEnabledIndex + direction;\n\n if (nextEnabledIndex < 0 || nextEnabledIndex >= enabledFilteredIndexes.value.length) {\n return;\n }\n\n activeIndex.value = enabledFilteredIndexes.value[nextEnabledIndex];\n};\n\nconst openListbox = (fallback: 'first' | 'last' = 'first') => {\n if (props.disabled) {\n return;\n }\n\n setValue(true);\n setInitialActiveIndex(fallback);\n};\n\nconst commitPendingClear = () => {\n if (query.value.trim() !== '' || !props.modelValue) {\n return false;\n }\n\n emit('update:modelValue', '');\n return true;\n};\n\nconst closeListbox = (restoreSelection = false) => {\n setValue(false);\n activeIndex.value = -1;\n\n if (!restoreSelection) {\n return;\n }\n\n if (commitPendingClear()) {\n return;\n }\n\n if (selectedLabel.value && query.value !== selectedLabel.value) {\n query.value = selectedLabel.value;\n }\n};\n\nconst selectOption = (option: TComboboxOption) => {\n if (option.disabled) {\n return;\n }\n\n query.value = option.label;\n emit('update:modelValue', option.value);\n closeListbox(false);\n};\n\nconst onInput = (event: Event) => {\n query.value = (event.target as HTMLInputElement).value;\n emit('input-change', query.value);\n\n if (props.disabled) {\n return;\n }\n\n if (!isOpen.value) {\n openListbox('first');\n return;\n }\n\n setInitialActiveIndex('first');\n};\n\nconst onInputFocus = () => {\n openListbox('first');\n};\n\nconst onInputClick = () => {\n if (!isOpen.value) {\n openListbox('first');\n }\n};\n\nconst onInputKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event)) {\n if (isOpen.value) {\n event.preventDefault();\n closeListbox(true);\n }\n\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('first');\n } else {\n moveActive(1);\n }\n break;\n case 'ArrowUp':\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('last');\n } else {\n moveActive(-1);\n }\n break;\n case 'Enter':\n if (isOpen.value && activeOption.value && !activeOption.value.disabled) {\n event.preventDefault();\n selectOption(activeOption.value);\n }\n break;\n case 'Home':\n if (!isOpen.value) return;\n event.preventDefault();\n setInitialActiveIndex('first');\n break;\n case 'End':\n if (!isOpen.value) return;\n event.preventDefault();\n setInitialActiveIndex('last');\n break;\n case 'Tab':\n closeListbox(true);\n break;\n default:\n break;\n }\n};\n\nconst onOptionPointerEnter = (index: number) => {\n const option = filteredOptions.value[index];\n\n if (option && !option.disabled) {\n activeIndex.value = index;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeListbox(true);\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nwatch(\n () => props.modelValue,\n () => {\n if (!isOpen.value) {\n syncQueryFromSelection();\n }\n },\n { immediate: true },\n);\n\nwatch(\n () => props.options,\n () => {\n if (!isOpen.value) {\n syncQueryFromSelection();\n return;\n }\n\n setInitialActiveIndex('first');\n },\n { deep: true },\n);\n\nwatch(filteredOptions, () => {\n if (!isOpen.value) {\n return;\n }\n\n if (filteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const current = filteredOptions.value[activeIndex.value];\n\n if (!current || current.disabled) {\n setInitialActiveIndex('first');\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div class=\"t-combobox__control\">\n <span\n v-if=\"$slots.prefix\"\n class=\"t-combobox__slot t-combobox__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-combobox__input\"\n role=\"combobox\"\n type=\"text\"\n :value=\"query\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n :aria-expanded=\"isOpen\"\n :aria-activedescendant=\"activeDescendant\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n @input=\"onInput\"\n @focus=\"onInputFocus\"\n @click=\"onInputClick\"\n @keydown=\"onInputKeydown\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <svg\n v-else\n class=\"t-combobox__indicator\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </div>\n\n <transition name=\"t-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"listboxId\"\n role=\"listbox\"\n class=\"t-combobox__listbox\"\n :aria-label=\"listboxLabel\"\n :aria-labelledby=\"listboxLabelledby\"\n >\n <li\n v-if=\"filteredOptions.length === 0\"\n class=\"t-combobox__empty\"\n >\n <slot\n name=\"empty\"\n :query=\"query\"\n >\n {{ emptyText }}\n </slot>\n </li>\n\n <template v-else>\n <li\n v-for=\"(option, index) in filteredOptions\"\n :id=\"getOptionId(option.value)\"\n :key=\"option.value\"\n role=\"option\"\n class=\"t-combobox__option\"\n :class=\"{\n 'is-active': index === activeIndex,\n 'is-disabled': option.disabled,\n 'is-selected': option.value === modelValue,\n }\"\n :aria-selected=\"option.value === modelValue\"\n :aria-disabled=\"option.disabled || undefined\"\n @mouseenter=\"onOptionPointerEnter(index)\"\n @click=\"selectOption(option)\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"option.value === modelValue\"\n :active=\"index === activeIndex\"\n >\n <span class=\"t-combobox__option-copy\">\n <span class=\"t-combobox__option-label\">{{ option.label }}</span>\n <span\n v-if=\"option.description\"\n class=\"t-combobox__option-description\"\n >\n {{ option.description }}\n </span>\n </span>\n <svg\n v-if=\"option.value === modelValue\"\n class=\"t-combobox__check\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n </slot>\n </li>\n </template>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n createId,\n focusFirst,\n focusLast,\n getFocusableElements,\n isEscapeKey,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('t-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-modal__surface',\n `t-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\n};\n\nconst focusSurface = () => {\n nextTick(() => {\n if (!surfaceRef.value) {\n return;\n }\n\n const focused = focusFirst(surfaceRef.value);\n if (!focused) {\n surfaceRef.value.focus();\n }\n });\n};\n\nconst openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\n return;\n }\n\n if (event.key !== 'Tab' || !surfaceRef.value) {\n return;\n }\n\n const focusable = getFocusableElements(surfaceRef.value);\n\n if (!focusable.length) {\n event.preventDefault();\n surfaceRef.value.focus();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n focusLast(surfaceRef.value);\n }\n\n if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n focusFirst(surfaceRef.value);\n }\n};\n\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"t-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n createId,\n focusFirst,\n focusLast,\n getFocusableElements,\n isEscapeKey,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('t-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-modal__surface',\n `t-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\n};\n\nconst focusSurface = () => {\n nextTick(() => {\n if (!surfaceRef.value) {\n return;\n }\n\n const focused = focusFirst(surfaceRef.value);\n if (!focused) {\n surfaceRef.value.focus();\n }\n });\n};\n\nconst openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\n return;\n }\n\n if (event.key !== 'Tab' || !surfaceRef.value) {\n return;\n }\n\n const focusable = getFocusableElements(surfaceRef.value);\n\n if (!focusable.length) {\n event.preventDefault();\n surfaceRef.value.focus();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n focusLast(surfaceRef.value);\n }\n\n if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n focusFirst(surfaceRef.value);\n }\n};\n\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"t-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, toRef, useAttrs } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize, TVariant } from '../types/contracts';\nimport TButton from './TButton.vue';\nimport TModal from './TModal.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst slots = defineSlots<{\n trigger?: () => unknown;\n icon?: () => unknown;\n default?: () => unknown;\n actions?: (props: {\n confirm: () => void;\n cancel: () => void;\n loading: boolean;\n }) => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n confirmVariant?: TVariant;\n confirmDisabled?: boolean;\n cancelDisabled?: boolean;\n loading?: boolean;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n closeOnConfirm?: boolean;\n closeOnCancel?: boolean;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'sm',\n title: '',\n description: '',\n confirmLabel: 'Confirm',\n cancelLabel: 'Cancel',\n confirmVariant: 'danger',\n confirmDisabled: false,\n cancelDisabled: false,\n loading: false,\n closeOnEscape: true,\n closeOnOverlay: false,\n showCloseButton: false,\n closeLabel: 'Close dialog',\n closeOnConfirm: true,\n closeOnCancel: true,\n },\n);\n\nconst emit = defineEmits<{\n confirm: [];\n cancel: [];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst dialogClasses = computed(() => [\n 't-confirm-dialog',\n {\n 't-confirm-dialog--with-icon': Boolean(slots.icon),\n },\n]);\n\nconst hasBodyContent = computed(() => Boolean(slots.default));\n\nconst closeDialog = () => {\n setValue(false);\n};\n\nconst syncOpen = (value: boolean) => {\n setValue(value);\n};\n\nconst handleCancel = () => {\n if (props.cancelDisabled) {\n return;\n }\n\n emit('cancel');\n\n if (props.closeOnCancel) {\n closeDialog();\n }\n};\n\nconst handleConfirm = () => {\n if (props.confirmDisabled || props.loading) {\n return;\n }\n\n emit('confirm');\n\n if (props.closeOnConfirm) {\n closeDialog();\n }\n};\n</script>\n\n<template>\n <TModal\n v-bind=\"attrs\"\n :open=\"isOpen\"\n :disabled=\"disabled\"\n :size=\"size\"\n :title=\"title\"\n :description=\"description\"\n :close-on-escape=\"closeOnEscape\"\n :close-on-overlay=\"closeOnOverlay\"\n :show-close-button=\"showCloseButton\"\n :close-label=\"closeLabel\"\n @update:open=\"syncOpen\"\n >\n <template\n v-if=\"$slots.trigger\"\n #trigger\n >\n <slot name=\"trigger\" />\n </template>\n\n <template #content>\n <div :class=\"dialogClasses\">\n <div\n v-if=\"$slots.icon\"\n class=\"t-confirm-dialog__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div\n v-if=\"hasBodyContent\"\n class=\"t-confirm-dialog__body\"\n >\n <slot />\n </div>\n </div>\n </template>\n\n <template #footer>\n <slot\n name=\"actions\"\n :confirm=\"handleConfirm\"\n :cancel=\"handleCancel\"\n :loading=\"loading\"\n >\n <TButton\n variant=\"ghost\"\n :disabled=\"cancelDisabled\"\n @click=\"handleCancel\"\n >\n {{ cancelLabel }}\n </TButton>\n <TButton\n :variant=\"confirmVariant\"\n :loading=\"loading\"\n :disabled=\"confirmDisabled\"\n @click=\"handleConfirm\"\n >\n {{ confirmLabel }}\n </TButton>\n </slot>\n </template>\n </TModal>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, toRef, useAttrs } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize, TVariant } from '../types/contracts';\nimport TButton from './TButton.vue';\nimport TModal from './TModal.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst slots = defineSlots<{\n trigger?: () => unknown;\n icon?: () => unknown;\n default?: () => unknown;\n actions?: (props: {\n confirm: () => void;\n cancel: () => void;\n loading: boolean;\n }) => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n confirmVariant?: TVariant;\n confirmDisabled?: boolean;\n cancelDisabled?: boolean;\n loading?: boolean;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n closeOnConfirm?: boolean;\n closeOnCancel?: boolean;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'sm',\n title: '',\n description: '',\n confirmLabel: 'Confirm',\n cancelLabel: 'Cancel',\n confirmVariant: 'danger',\n confirmDisabled: false,\n cancelDisabled: false,\n loading: false,\n closeOnEscape: true,\n closeOnOverlay: false,\n showCloseButton: false,\n closeLabel: 'Close dialog',\n closeOnConfirm: true,\n closeOnCancel: true,\n },\n);\n\nconst emit = defineEmits<{\n confirm: [];\n cancel: [];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst dialogClasses = computed(() => [\n 't-confirm-dialog',\n {\n 't-confirm-dialog--with-icon': Boolean(slots.icon),\n },\n]);\n\nconst hasBodyContent = computed(() => Boolean(slots.default));\n\nconst closeDialog = () => {\n setValue(false);\n};\n\nconst syncOpen = (value: boolean) => {\n setValue(value);\n};\n\nconst handleCancel = () => {\n if (props.cancelDisabled) {\n return;\n }\n\n emit('cancel');\n\n if (props.closeOnCancel) {\n closeDialog();\n }\n};\n\nconst handleConfirm = () => {\n if (props.confirmDisabled || props.loading) {\n return;\n }\n\n emit('confirm');\n\n if (props.closeOnConfirm) {\n closeDialog();\n }\n};\n</script>\n\n<template>\n <TModal\n v-bind=\"attrs\"\n :open=\"isOpen\"\n :disabled=\"disabled\"\n :size=\"size\"\n :title=\"title\"\n :description=\"description\"\n :close-on-escape=\"closeOnEscape\"\n :close-on-overlay=\"closeOnOverlay\"\n :show-close-button=\"showCloseButton\"\n :close-label=\"closeLabel\"\n @update:open=\"syncOpen\"\n >\n <template\n v-if=\"$slots.trigger\"\n #trigger\n >\n <slot name=\"trigger\" />\n </template>\n\n <template #content>\n <div :class=\"dialogClasses\">\n <div\n v-if=\"$slots.icon\"\n class=\"t-confirm-dialog__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div\n v-if=\"hasBodyContent\"\n class=\"t-confirm-dialog__body\"\n >\n <slot />\n </div>\n </div>\n </template>\n\n <template #footer>\n <slot\n name=\"actions\"\n :confirm=\"handleConfirm\"\n :cancel=\"handleCancel\"\n :loading=\"loading\"\n >\n <TButton\n variant=\"ghost\"\n :disabled=\"cancelDisabled\"\n @click=\"handleCancel\"\n >\n {{ cancelLabel }}\n </TButton>\n <TButton\n :variant=\"confirmVariant\"\n :loading=\"loading\"\n :disabled=\"confirmDisabled\"\n @click=\"handleConfirm\"\n >\n {{ confirmLabel }}\n </TButton>\n </slot>\n </template>\n </TModal>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeContainerSizes = ['sm', 'md', 'lg', 'xl', 'full'] as const;\n\nexport type TContainerSize = (typeof _treeContainerSizes)[number];\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TContainerSize;\n padded?: boolean;\n centered?: boolean;\n }>(),\n {\n as: 'div',\n size: 'lg',\n padded: true,\n centered: true,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-container',\n `t-container--${props.size}`,\n {\n 'is-padded': props.padded,\n 'is-centered': props.centered,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeContainerSizes = ['sm', 'md', 'lg', 'xl', 'full'] as const;\n\nexport type TContainerSize = (typeof _treeContainerSizes)[number];\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TContainerSize;\n padded?: boolean;\n centered?: boolean;\n }>(),\n {\n as: 'div',\n size: 'lg',\n padded: true,\n centered: true,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-container',\n `t-container--${props.size}`,\n {\n 'is-padded': props.padded,\n 'is-centered': props.centered,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\nexport interface TContextMenuItem {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TContextMenuItem[];\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n }>(),\n {\n items: () => [],\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n },\n);\n\nconst emit = defineEmits<{\n select: [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n default(): unknown;\n item(props: { item: TContextMenuItem; index: number }): unknown;\n}>();\n\nconst menuId = createId('t-context-menu');\nconst rootRef = ref<HTMLElement | null>(null);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\nconst menuPosition = ref({ x: 0, y: 0 });\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-context-menu',\n `t-context-menu--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-open': isOpen.value,\n },\n]);\n\nconst enabledItems = computed(() => props.items.filter((i) => !i.disabled));\n\nconst openMenu = (x: number, y: number) => {\n if (props.disabled) return;\n menuPosition.value = { x, y };\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n setValue(true);\n nextTick(() => focusItem(focusedIndex.value));\n};\n\nconst closeMenu = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => rootRef.value?.focus());\n }\n};\n\nconst selectItem = (item: TContextMenuItem) => {\n if (item.disabled) return;\n emit('select', item.value);\n closeMenu(true);\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n if (!item) return;\n const el = itemRefs.value.get(item.value);\n el?.focus();\n};\n\nconst setItemRef = (el: Element | null, value: string) => {\n if (el instanceof HTMLElement) {\n itemRefs.value.set(value, el);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.items.length) {\n if (!props.items[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusItem(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onContextMenu = (event: MouseEvent) => {\n if (props.disabled) return;\n event.preventDefault();\n openMenu(event.clientX, event.clientY);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, item: TContextMenuItem) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeMenu(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(item);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n focusItem(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[enabledItems.value.length - 1])\n : props.items.length - 1;\n focusItem(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n const menuEl = document.getElementById(menuId);\n if (menuEl?.contains(target)) return;\n closeMenu();\n};\n\nconst onDocumentContextMenu = (event: MouseEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeMenu();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n document.addEventListener('contextmenu', onDocumentContextMenu);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n document.removeEventListener('contextmenu', onDocumentContextMenu);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n document.removeEventListener('contextmenu', onDocumentContextMenu);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n @contextmenu=\"onContextMenu\"\n >\n <slot />\n <Teleport to=\"body\">\n <transition name=\"t-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"menuId\"\n role=\"menu\"\n class=\"t-context-menu__menu\"\n :class=\"`t-context-menu--${size}`\"\n :style=\"{ top: `${menuPosition.y}px`, left: `${menuPosition.x}px` }\"\n aria-label=\"Context menu\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n :ref=\"(el) => setItemRef(el as Element | null, item.value)\"\n role=\"menuitem\"\n class=\"t-context-menu__item\"\n :class=\"{\n 'is-disabled': item.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-disabled=\"item.disabled || undefined\"\n :tabindex=\"item.disabled ? -1 : 0\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n {{ item.label }}\n </slot>\n </li>\n </ul>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\nexport interface TContextMenuItem {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TContextMenuItem[];\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n }>(),\n {\n items: () => [],\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n },\n);\n\nconst emit = defineEmits<{\n select: [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n default(): unknown;\n item(props: { item: TContextMenuItem; index: number }): unknown;\n}>();\n\nconst menuId = createId('t-context-menu');\nconst rootRef = ref<HTMLElement | null>(null);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\nconst menuPosition = ref({ x: 0, y: 0 });\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-context-menu',\n `t-context-menu--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-open': isOpen.value,\n },\n]);\n\nconst enabledItems = computed(() => props.items.filter((i) => !i.disabled));\n\nconst openMenu = (x: number, y: number) => {\n if (props.disabled) return;\n menuPosition.value = { x, y };\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n setValue(true);\n nextTick(() => focusItem(focusedIndex.value));\n};\n\nconst closeMenu = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => rootRef.value?.focus());\n }\n};\n\nconst selectItem = (item: TContextMenuItem) => {\n if (item.disabled) return;\n emit('select', item.value);\n closeMenu(true);\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n if (!item) return;\n const el = itemRefs.value.get(item.value);\n el?.focus();\n};\n\nconst setItemRef = (el: Element | null, value: string) => {\n if (el instanceof HTMLElement) {\n itemRefs.value.set(value, el);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.items.length) {\n if (!props.items[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusItem(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onContextMenu = (event: MouseEvent) => {\n if (props.disabled) return;\n event.preventDefault();\n openMenu(event.clientX, event.clientY);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, item: TContextMenuItem) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeMenu(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(item);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n focusItem(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[enabledItems.value.length - 1])\n : props.items.length - 1;\n focusItem(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n const menuEl = document.getElementById(menuId);\n if (menuEl?.contains(target)) return;\n closeMenu();\n};\n\nconst onDocumentContextMenu = (event: MouseEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeMenu();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n document.addEventListener('contextmenu', onDocumentContextMenu);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n document.removeEventListener('contextmenu', onDocumentContextMenu);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n document.removeEventListener('contextmenu', onDocumentContextMenu);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n @contextmenu=\"onContextMenu\"\n >\n <slot />\n <Teleport to=\"body\">\n <transition name=\"t-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"menuId\"\n role=\"menu\"\n class=\"t-context-menu__menu\"\n :class=\"`t-context-menu--${size}`\"\n :style=\"{ top: `${menuPosition.y}px`, left: `${menuPosition.x}px` }\"\n aria-label=\"Context menu\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n :ref=\"(el) => setItemRef(el as Element | null, item.value)\"\n role=\"menuitem\"\n class=\"t-context-menu__item\"\n :class=\"{\n 'is-disabled': item.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-disabled=\"item.disabled || undefined\"\n :tabindex=\"item.disabled ? -1 : 0\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n {{ item.label }}\n </slot>\n </li>\n </ul>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n addDays,\n addMonths,\n createId,\n isActivationKey,\n isEscapeKey,\n isSameDay,\n parseDateValue,\n startOfDay,\n startOfMonth,\n startOfWeek,\n toDateValue,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n type ComponentPublicInstance,\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\ninterface CalendarCell {\n date: Date;\n dayLabel: number;\n disabled: boolean;\n inMonth: boolean;\n isFocused: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n}\n\nconst CalendarIcon = getTreeIcon('calendar');\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n open?: boolean;\n defaultOpen?: boolean;\n size?: TSize;\n disabled?: boolean;\n invalid?: boolean;\n placeholder?: string;\n locale?: string;\n min?: string;\n max?: string;\n weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n id?: string;\n }>(),\n {\n modelValue: '',\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n invalid: false,\n placeholder: 'Select date',\n locale: 'en-US',\n min: '',\n max: '',\n weekStartsOn: 0,\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n select: [value: string];\n}>();\n\nconst attrs = useAttrs();\nconst today = startOfDay(new Date());\nconst selectedDate = computed(() => parseDateValue(props.modelValue));\nconst minDate = computed(() => parseDateValue(props.min));\nconst maxDate = computed(() => parseDateValue(props.max));\nconst calendarId = props.id ?? createId('t-date-picker');\nconst captionId = `${calendarId}-caption`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst dayRefs = new Map<string, HTMLButtonElement>();\nconst viewMonth = ref(startOfMonth(selectedDate.value ?? today));\nconst focusedDate = ref<Date>(selectedDate.value ?? today);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, name: _name, ...rest } = attrs;\n return rest;\n});\n\nconst hiddenInputName = computed(() =>\n typeof attrs.name === 'string' ? attrs.name : undefined,\n);\n\nconst rootClasses = computed(() => [\n 't-date-picker',\n `t-date-picker--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst triggerText = computed(() => {\n if (!selectedDate.value) {\n return props.placeholder;\n }\n\n return new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n }).format(selectedDate.value);\n});\n\nconst monthLabel = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n month: 'long',\n year: 'numeric',\n }).format(viewMonth.value),\n);\n\nconst weekdayLabels = computed(() => {\n const formatter = new Intl.DateTimeFormat(props.locale, { weekday: 'short' });\n const weekBase = startOfWeek(new Date(2024, 0, 7), props.weekStartsOn);\n\n return Array.from({ length: 7 }, (_, index) =>\n formatter.format(addDays(weekBase, index)),\n );\n});\n\nconst isDateDisabled = (date: Date) => {\n if (props.disabled) {\n return true;\n }\n\n if (minDate.value && date < minDate.value) {\n return true;\n }\n\n if (maxDate.value && date > maxDate.value) {\n return true;\n }\n\n return false;\n};\n\nconst syncCalendarView = (date: Date) => {\n focusedDate.value = startOfDay(date);\n viewMonth.value = startOfMonth(date);\n};\n\nwatch(\n selectedDate,\n (value) => {\n if (value) {\n syncCalendarView(value);\n return;\n }\n\n if (!isOpen.value) {\n syncCalendarView(today);\n }\n },\n { immediate: true },\n);\n\nconst cells = computed(() => {\n const startDate = startOfWeek(startOfMonth(viewMonth.value), props.weekStartsOn);\n\n return Array.from({ length: 6 }, (_, weekIndex) =>\n Array.from({ length: 7 }, (_, dayIndex) => {\n const date = addDays(startDate, weekIndex * 7 + dayIndex);\n const key = toDateValue(date);\n\n return {\n date,\n dayLabel: date.getDate(),\n disabled: isDateDisabled(date),\n inMonth: date.getMonth() === viewMonth.value.getMonth(),\n isFocused: isSameDay(date, focusedDate.value),\n isSelected: isSameDay(date, selectedDate.value),\n isToday: isSameDay(date, today),\n key,\n } satisfies CalendarCell;\n }),\n );\n});\n\nconst canMovePrev = computed(() => {\n if (!minDate.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) > startOfMonth(minDate.value);\n});\n\nconst canMoveNext = computed(() => {\n if (!maxDate.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) < startOfMonth(maxDate.value);\n});\n\nconst focusCurrentDay = () => {\n const key = toDateValue(focusedDate.value);\n nextTick(() => {\n dayRefs.get(key)?.focus();\n });\n};\n\nconst setDayRef = (\n element: Element | ComponentPublicInstance | null,\n key: string,\n) => {\n if (element instanceof HTMLButtonElement) {\n dayRefs.set(key, element);\n return;\n }\n\n dayRefs.delete(key);\n};\n\nconst openCalendar = () => {\n if (props.disabled) {\n return;\n }\n\n syncCalendarView(selectedDate.value ?? focusedDate.value ?? today);\n setValue(true);\n focusCurrentDay();\n};\n\nconst closeCalendar = (restoreFocus = false) => {\n setValue(false);\n\n if (restoreFocus) {\n nextTick(() => {\n triggerRef.value?.focus();\n });\n }\n};\n\nconst toggleCalendar = () => {\n if (isOpen.value) {\n closeCalendar();\n return;\n }\n\n openCalendar();\n};\n\nconst moveCalendar = (direction: 1 | -1) => {\n const nextMonth = addMonths(viewMonth.value, direction);\n syncCalendarView(nextMonth);\n focusCurrentDay();\n};\n\nconst moveFocus = (nextDate: Date) => {\n if (isDateDisabled(nextDate)) {\n return;\n }\n\n syncCalendarView(nextDate);\n focusCurrentDay();\n};\n\nconst selectDate = (date: Date) => {\n if (isDateDisabled(date)) {\n return;\n }\n\n const normalizedDate = startOfDay(date);\n const value = toDateValue(normalizedDate);\n\n syncCalendarView(normalizedDate);\n emit('update:modelValue', value);\n emit('select', value);\n closeCalendar(true);\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeCalendar();\n return;\n }\n\n if (\n isActivationKey(event) ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n openCalendar();\n }\n};\n\nconst onDayKeydown = (event: KeyboardEvent, date: Date) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeCalendar(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectDate(date);\n return;\n }\n\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(addDays(date, -1));\n break;\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(addDays(date, 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(addDays(date, -7));\n break;\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(addDays(date, 7));\n break;\n case 'Home':\n event.preventDefault();\n moveFocus(startOfWeek(date, props.weekStartsOn));\n break;\n case 'End':\n event.preventDefault();\n moveFocus(addDays(startOfWeek(date, props.weekStartsOn), 6));\n break;\n case 'PageUp':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? -12 : -1));\n break;\n case 'PageDown':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? 12 : 1));\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeCalendar();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n return;\n }\n\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <input\n v-if=\"hiddenInputName\"\n type=\"hidden\"\n :name=\"hiddenInputName\"\n :value=\"modelValue\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"t-date-picker__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? calendarId : undefined\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n @click=\"toggleCalendar\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-date-picker__slot t-date-picker__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <span\n class=\"t-date-picker__value\"\n :data-placeholder=\"selectedDate ? undefined : true\"\n >\n {{ triggerText }}\n </span>\n <span class=\"t-date-picker__slot t-date-picker__slot--suffix\">\n <slot name=\"suffix\">\n <CalendarIcon v-bind=\"treeIconDefaults\" />\n </slot>\n </span>\n </button>\n\n <transition name=\"t-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"calendarId\"\n class=\"t-date-picker__content\"\n role=\"dialog\"\n aria-modal=\"false\"\n :aria-labelledby=\"captionId\"\n >\n <div class=\"t-date-picker__header\">\n <button\n type=\"button\"\n class=\"t-date-picker__nav\"\n :disabled=\"!canMovePrev\"\n aria-label=\"Previous month\"\n @click=\"moveCalendar(-1)\"\n >\n <ChevronLeftIcon v-bind=\"treeIconDefaults\" />\n </button>\n <p\n :id=\"captionId\"\n class=\"t-date-picker__month\"\n >\n {{ monthLabel }}\n </p>\n <button\n type=\"button\"\n class=\"t-date-picker__nav\"\n :disabled=\"!canMoveNext\"\n aria-label=\"Next month\"\n @click=\"moveCalendar(1)\"\n >\n <ChevronRightIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <div\n class=\"t-date-picker__weekdays\"\n aria-hidden=\"true\"\n >\n <span\n v-for=\"label in weekdayLabels\"\n :key=\"label\"\n class=\"t-date-picker__weekday\"\n >\n {{ label }}\n </span>\n </div>\n\n <div\n class=\"t-date-picker__grid\"\n role=\"grid\"\n :aria-labelledby=\"captionId\"\n >\n <div\n v-for=\"(week, weekIndex) in cells\"\n :key=\"weekIndex\"\n class=\"t-date-picker__row\"\n role=\"row\"\n >\n <div\n v-for=\"cell in week\"\n :key=\"cell.key\"\n class=\"t-date-picker__cell\"\n role=\"gridcell\"\n :aria-selected=\"cell.isSelected\"\n >\n <button\n :ref=\"(element) => setDayRef(element, cell.key)\"\n type=\"button\"\n class=\"t-date-picker__day\"\n :class=\"{\n 'is-muted': !cell.inMonth,\n 'is-selected': cell.isSelected,\n 'is-today': cell.isToday,\n }\"\n :data-date=\"cell.key\"\n :disabled=\"cell.disabled\"\n :tabindex=\"cell.isFocused ? 0 : -1\"\n :aria-current=\"cell.isToday ? 'date' : undefined\"\n :aria-label=\"cell.key\"\n @click=\"selectDate(cell.date)\"\n @keydown=\"onDayKeydown($event, cell.date)\"\n >\n {{ cell.dayLabel }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n addDays,\n addMonths,\n createId,\n isActivationKey,\n isEscapeKey,\n isSameDay,\n parseDateValue,\n startOfDay,\n startOfMonth,\n startOfWeek,\n toDateValue,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n type ComponentPublicInstance,\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\ninterface CalendarCell {\n date: Date;\n dayLabel: number;\n disabled: boolean;\n inMonth: boolean;\n isFocused: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n}\n\nconst CalendarIcon = getTreeIcon('calendar');\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n open?: boolean;\n defaultOpen?: boolean;\n size?: TSize;\n disabled?: boolean;\n invalid?: boolean;\n placeholder?: string;\n locale?: string;\n min?: string;\n max?: string;\n weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n id?: string;\n }>(),\n {\n modelValue: '',\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n invalid: false,\n placeholder: 'Select date',\n locale: 'en-US',\n min: '',\n max: '',\n weekStartsOn: 0,\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n select: [value: string];\n}>();\n\nconst attrs = useAttrs();\nconst today = startOfDay(new Date());\nconst selectedDate = computed(() => parseDateValue(props.modelValue));\nconst minDate = computed(() => parseDateValue(props.min));\nconst maxDate = computed(() => parseDateValue(props.max));\nconst calendarId = props.id ?? createId('t-date-picker');\nconst captionId = `${calendarId}-caption`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst dayRefs = new Map<string, HTMLButtonElement>();\nconst viewMonth = ref(startOfMonth(selectedDate.value ?? today));\nconst focusedDate = ref<Date>(selectedDate.value ?? today);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, name: _name, ...rest } = attrs;\n return rest;\n});\n\nconst hiddenInputName = computed(() =>\n typeof attrs.name === 'string' ? attrs.name : undefined,\n);\n\nconst rootClasses = computed(() => [\n 't-date-picker',\n `t-date-picker--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst triggerText = computed(() => {\n if (!selectedDate.value) {\n return props.placeholder;\n }\n\n return new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n }).format(selectedDate.value);\n});\n\nconst monthLabel = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n month: 'long',\n year: 'numeric',\n }).format(viewMonth.value),\n);\n\nconst weekdayLabels = computed(() => {\n const formatter = new Intl.DateTimeFormat(props.locale, { weekday: 'short' });\n const weekBase = startOfWeek(new Date(2024, 0, 7), props.weekStartsOn);\n\n return Array.from({ length: 7 }, (_, index) =>\n formatter.format(addDays(weekBase, index)),\n );\n});\n\nconst isDateDisabled = (date: Date) => {\n if (props.disabled) {\n return true;\n }\n\n if (minDate.value && date < minDate.value) {\n return true;\n }\n\n if (maxDate.value && date > maxDate.value) {\n return true;\n }\n\n return false;\n};\n\nconst syncCalendarView = (date: Date) => {\n focusedDate.value = startOfDay(date);\n viewMonth.value = startOfMonth(date);\n};\n\nwatch(\n selectedDate,\n (value) => {\n if (value) {\n syncCalendarView(value);\n return;\n }\n\n if (!isOpen.value) {\n syncCalendarView(today);\n }\n },\n { immediate: true },\n);\n\nconst cells = computed(() => {\n const startDate = startOfWeek(startOfMonth(viewMonth.value), props.weekStartsOn);\n\n return Array.from({ length: 6 }, (_, weekIndex) =>\n Array.from({ length: 7 }, (_, dayIndex) => {\n const date = addDays(startDate, weekIndex * 7 + dayIndex);\n const key = toDateValue(date);\n\n return {\n date,\n dayLabel: date.getDate(),\n disabled: isDateDisabled(date),\n inMonth: date.getMonth() === viewMonth.value.getMonth(),\n isFocused: isSameDay(date, focusedDate.value),\n isSelected: isSameDay(date, selectedDate.value),\n isToday: isSameDay(date, today),\n key,\n } satisfies CalendarCell;\n }),\n );\n});\n\nconst canMovePrev = computed(() => {\n if (!minDate.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) > startOfMonth(minDate.value);\n});\n\nconst canMoveNext = computed(() => {\n if (!maxDate.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) < startOfMonth(maxDate.value);\n});\n\nconst focusCurrentDay = () => {\n const key = toDateValue(focusedDate.value);\n nextTick(() => {\n dayRefs.get(key)?.focus();\n });\n};\n\nconst setDayRef = (\n element: Element | ComponentPublicInstance | null,\n key: string,\n) => {\n if (element instanceof HTMLButtonElement) {\n dayRefs.set(key, element);\n return;\n }\n\n dayRefs.delete(key);\n};\n\nconst openCalendar = () => {\n if (props.disabled) {\n return;\n }\n\n syncCalendarView(selectedDate.value ?? focusedDate.value ?? today);\n setValue(true);\n focusCurrentDay();\n};\n\nconst closeCalendar = (restoreFocus = false) => {\n setValue(false);\n\n if (restoreFocus) {\n nextTick(() => {\n triggerRef.value?.focus();\n });\n }\n};\n\nconst toggleCalendar = () => {\n if (isOpen.value) {\n closeCalendar();\n return;\n }\n\n openCalendar();\n};\n\nconst moveCalendar = (direction: 1 | -1) => {\n const nextMonth = addMonths(viewMonth.value, direction);\n syncCalendarView(nextMonth);\n focusCurrentDay();\n};\n\nconst moveFocus = (nextDate: Date) => {\n if (isDateDisabled(nextDate)) {\n return;\n }\n\n syncCalendarView(nextDate);\n focusCurrentDay();\n};\n\nconst selectDate = (date: Date) => {\n if (isDateDisabled(date)) {\n return;\n }\n\n const normalizedDate = startOfDay(date);\n const value = toDateValue(normalizedDate);\n\n syncCalendarView(normalizedDate);\n emit('update:modelValue', value);\n emit('select', value);\n closeCalendar(true);\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeCalendar();\n return;\n }\n\n if (\n isActivationKey(event) ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n openCalendar();\n }\n};\n\nconst onDayKeydown = (event: KeyboardEvent, date: Date) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeCalendar(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectDate(date);\n return;\n }\n\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(addDays(date, -1));\n break;\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(addDays(date, 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(addDays(date, -7));\n break;\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(addDays(date, 7));\n break;\n case 'Home':\n event.preventDefault();\n moveFocus(startOfWeek(date, props.weekStartsOn));\n break;\n case 'End':\n event.preventDefault();\n moveFocus(addDays(startOfWeek(date, props.weekStartsOn), 6));\n break;\n case 'PageUp':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? -12 : -1));\n break;\n case 'PageDown':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? 12 : 1));\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeCalendar();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n return;\n }\n\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <input\n v-if=\"hiddenInputName\"\n type=\"hidden\"\n :name=\"hiddenInputName\"\n :value=\"modelValue\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"t-date-picker__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? calendarId : undefined\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n @click=\"toggleCalendar\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-date-picker__slot t-date-picker__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <span\n class=\"t-date-picker__value\"\n :data-placeholder=\"selectedDate ? undefined : true\"\n >\n {{ triggerText }}\n </span>\n <span class=\"t-date-picker__slot t-date-picker__slot--suffix\">\n <slot name=\"suffix\">\n <CalendarIcon v-bind=\"treeIconDefaults\" />\n </slot>\n </span>\n </button>\n\n <transition name=\"t-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"calendarId\"\n class=\"t-date-picker__content\"\n role=\"dialog\"\n aria-modal=\"false\"\n :aria-labelledby=\"captionId\"\n >\n <div class=\"t-date-picker__header\">\n <button\n type=\"button\"\n class=\"t-date-picker__nav\"\n :disabled=\"!canMovePrev\"\n aria-label=\"Previous month\"\n @click=\"moveCalendar(-1)\"\n >\n <ChevronLeftIcon v-bind=\"treeIconDefaults\" />\n </button>\n <p\n :id=\"captionId\"\n class=\"t-date-picker__month\"\n >\n {{ monthLabel }}\n </p>\n <button\n type=\"button\"\n class=\"t-date-picker__nav\"\n :disabled=\"!canMoveNext\"\n aria-label=\"Next month\"\n @click=\"moveCalendar(1)\"\n >\n <ChevronRightIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <div\n class=\"t-date-picker__weekdays\"\n aria-hidden=\"true\"\n >\n <span\n v-for=\"label in weekdayLabels\"\n :key=\"label\"\n class=\"t-date-picker__weekday\"\n >\n {{ label }}\n </span>\n </div>\n\n <div\n class=\"t-date-picker__grid\"\n role=\"grid\"\n :aria-labelledby=\"captionId\"\n >\n <div\n v-for=\"(week, weekIndex) in cells\"\n :key=\"weekIndex\"\n class=\"t-date-picker__row\"\n role=\"row\"\n >\n <div\n v-for=\"cell in week\"\n :key=\"cell.key\"\n class=\"t-date-picker__cell\"\n role=\"gridcell\"\n :aria-selected=\"cell.isSelected\"\n >\n <button\n :ref=\"(element) => setDayRef(element, cell.key)\"\n type=\"button\"\n class=\"t-date-picker__day\"\n :class=\"{\n 'is-muted': !cell.inMonth,\n 'is-selected': cell.isSelected,\n 'is-today': cell.isToday,\n }\"\n :data-date=\"cell.key\"\n :disabled=\"cell.disabled\"\n :tabindex=\"cell.isFocused ? 0 : -1\"\n :aria-current=\"cell.isToday ? 'date' : undefined\"\n :aria-label=\"cell.key\"\n @click=\"selectDate(cell.date)\"\n @keydown=\"onDayKeydown($event, cell.date)\"\n >\n {{ cell.dayLabel }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n addDays,\n addMonths,\n createId,\n isActivationKey,\n isEscapeKey,\n isSameDay,\n startOfDay,\n startOfMonth,\n startOfWeek,\n toDateValue,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n type ComponentPublicInstance,\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\ninterface CalendarCell {\n date: Date;\n dayLabel: number;\n disabled: boolean;\n inMonth: boolean;\n isFocused: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n}\n\ninterface TimeOption {\n disabled: boolean;\n label: string;\n value: number;\n}\n\nconst CalendarIcon = getTreeIcon('calendar');\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst dateOnlyPattern = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nconst dateTimePattern = /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})(?::(\\d{2}))?$/;\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n open?: boolean;\n defaultOpen?: boolean;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n locale?: string;\n min?: string;\n max?: string;\n weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n id?: string;\n step?: number;\n }>(),\n {\n modelValue: '',\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: 'Select date and time',\n locale: 'en-US',\n min: '',\n max: '',\n weekStartsOn: 0,\n id: undefined,\n step: 60,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n change: [value: string];\n select: [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst cloneDate = (value: Date) => new Date(value.getTime());\n\nconst formatPart = (value: number) => `${value}`.padStart(2, '0');\n\nconst endOfDay = (date: Date) =>\n new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);\n\nconst parseBoundaryValue = (\n value: string | null | undefined,\n boundary: 'exact' | 'start' | 'end' = 'exact',\n) => {\n if (!value) {\n return null;\n }\n\n const dateOnlyMatch = value.match(dateOnlyPattern);\n if (dateOnlyMatch) {\n const [, yearToken, monthToken, dayToken] = dateOnlyMatch;\n const year = Number.parseInt(yearToken, 10);\n const month = Number.parseInt(monthToken, 10);\n const day = Number.parseInt(dayToken, 10);\n const hour = boundary === 'end' ? 23 : 0;\n const minute = boundary === 'end' ? 59 : 0;\n const second = boundary === 'end' ? 59 : 0;\n const millisecond = boundary === 'end' ? 999 : 0;\n const date = new Date(year, month - 1, day, hour, minute, second, millisecond);\n\n if (\n Number.isNaN(date.getTime()) ||\n date.getFullYear() !== year ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day\n ) {\n return null;\n }\n\n return date;\n }\n\n const dateTimeMatch = value.match(dateTimePattern);\n if (!dateTimeMatch) {\n return null;\n }\n\n const [, yearToken, monthToken, dayToken, hourToken, minuteToken, secondToken] =\n dateTimeMatch;\n const year = Number.parseInt(yearToken, 10);\n const month = Number.parseInt(monthToken, 10);\n const day = Number.parseInt(dayToken, 10);\n const hour = Number.parseInt(hourToken, 10);\n const minute = Number.parseInt(minuteToken, 10);\n const second = secondToken ? Number.parseInt(secondToken, 10) : 0;\n const date = new Date(year, month - 1, day, hour, minute, second, 0);\n\n if (\n Number.isNaN(date.getTime()) ||\n date.getFullYear() !== year ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day ||\n date.getHours() !== hour ||\n date.getMinutes() !== minute ||\n date.getSeconds() !== second\n ) {\n return null;\n }\n\n return date;\n};\n\nconst toDateTimeValue = (date: Date) =>\n `${toDateValue(date)}T${formatPart(date.getHours())}:${formatPart(date.getMinutes())}`;\n\nconst setDatePart = (source: Date, targetDate: Date) =>\n new Date(\n targetDate.getFullYear(),\n targetDate.getMonth(),\n targetDate.getDate(),\n source.getHours(),\n source.getMinutes(),\n 0,\n 0,\n );\n\nconst setTimePart = (source: Date, hour: number, minute: number) =>\n new Date(\n source.getFullYear(),\n source.getMonth(),\n source.getDate(),\n hour,\n minute,\n 0,\n 0,\n );\n\nconst resolveMinuteStep = (step: number) => {\n if (!Number.isFinite(step) || step <= 0 || step % 60 !== 0) {\n return 1;\n }\n\n const minuteStep = step / 60;\n return minuteStep >= 60 ? 1 : minuteStep;\n};\n\nconst today = startOfDay(new Date());\nconst selectedDateTime = computed(() => parseBoundaryValue(props.modelValue, 'exact'));\nconst minDateTime = computed(() => parseBoundaryValue(props.min, 'start'));\nconst maxDateTime = computed(() => parseBoundaryValue(props.max, 'end'));\nconst pickerId = props.id ?? createId('t-date-time-picker');\nconst captionId = `${pickerId}-caption`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst dayRefs = new Map<string, HTMLButtonElement>();\n\nconst clampToRange = (value: Date) => {\n let nextValue = cloneDate(value);\n\n if (minDateTime.value && nextValue < minDateTime.value) {\n nextValue = cloneDate(minDateTime.value);\n }\n\n if (maxDateTime.value && nextValue > maxDateTime.value) {\n nextValue = cloneDate(maxDateTime.value);\n }\n\n return nextValue;\n};\n\nconst createDefaultDraftDateTime = () => {\n const reference = new Date();\n const stepMilliseconds = Math.max(props.step, 60) * 1000;\n const rounded = new Date(Math.ceil(reference.getTime() / stepMilliseconds) * stepMilliseconds);\n\n rounded.setSeconds(0, 0);\n return clampToRange(rounded);\n};\n\nconst initialDateTime = selectedDateTime.value ?? createDefaultDraftDateTime();\nconst draftDateTime = ref(initialDateTime);\nconst focusedDate = ref(startOfDay(initialDateTime));\nconst viewMonth = ref(startOfMonth(initialDateTime));\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, name: _name, ...rest } = attrs;\n return rest;\n});\n\nconst hiddenInputName = computed(() =>\n typeof attrs.name === 'string' ? attrs.name : undefined,\n);\n\nconst rootClasses = computed(() => [\n 't-date-picker',\n 't-date-time-picker',\n `t-date-picker--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst triggerText = computed(() => {\n if (!selectedDateTime.value) {\n return props.placeholder;\n }\n\n return new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n month: 'long',\n year: 'numeric',\n }).format(selectedDateTime.value);\n});\n\nconst draftPreview = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n month: 'long',\n year: 'numeric',\n }).format(draftDateTime.value),\n);\n\nconst monthLabel = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n month: 'long',\n year: 'numeric',\n }).format(viewMonth.value),\n);\n\nconst weekdayLabels = computed(() => {\n const formatter = new Intl.DateTimeFormat(props.locale, { weekday: 'short' });\n const weekBase = startOfWeek(new Date(2024, 0, 7), props.weekStartsOn);\n\n return Array.from({ length: 7 }, (_, index) =>\n formatter.format(addDays(weekBase, index)),\n );\n});\n\nconst minuteStep = computed(() => resolveMinuteStep(props.step));\n\nconst minuteValues = computed(() => {\n const values = new Set<number>();\n\n for (let minute = 0; minute < 60; minute += minuteStep.value) {\n values.add(minute);\n }\n\n values.add(draftDateTime.value.getMinutes());\n\n return [...values].sort((left, right) => left - right);\n});\n\nconst isDateDisabled = (date: Date) => {\n if (props.disabled) {\n return true;\n }\n\n const dayStart = startOfDay(date);\n const dayEnd = endOfDay(date);\n\n if (minDateTime.value && dayEnd < minDateTime.value) {\n return true;\n }\n\n if (maxDateTime.value && dayStart > maxDateTime.value) {\n return true;\n }\n\n return false;\n};\n\nconst isDateTimeDisabled = (value: Date) => {\n if (props.disabled) {\n return true;\n }\n\n if (minDateTime.value && value < minDateTime.value) {\n return true;\n }\n\n if (maxDateTime.value && value > maxDateTime.value) {\n return true;\n }\n\n return false;\n};\n\nconst syncCalendarView = (date: Date) => {\n focusedDate.value = startOfDay(date);\n viewMonth.value = startOfMonth(date);\n};\n\nconst syncDraftState = (dateTime: Date) => {\n const nextValue = clampToRange(dateTime);\n draftDateTime.value = nextValue;\n syncCalendarView(nextValue);\n};\n\nwatch(\n selectedDateTime,\n (value) => {\n if (isOpen.value) {\n return;\n }\n\n syncDraftState(value ?? createDefaultDraftDateTime());\n },\n { immediate: true },\n);\n\nconst draftDate = computed(() => startOfDay(draftDateTime.value));\n\nconst cells = computed(() => {\n const startDate = startOfWeek(startOfMonth(viewMonth.value), props.weekStartsOn);\n\n return Array.from({ length: 6 }, (_, weekIndex) =>\n Array.from({ length: 7 }, (_, dayIndex) => {\n const date = addDays(startDate, weekIndex * 7 + dayIndex);\n const key = toDateValue(date);\n\n return {\n date,\n dayLabel: date.getDate(),\n disabled: isDateDisabled(date),\n inMonth: date.getMonth() === viewMonth.value.getMonth(),\n isFocused: isSameDay(date, focusedDate.value),\n isSelected: isSameDay(date, draftDate.value),\n isToday: isSameDay(date, today),\n key,\n } satisfies CalendarCell;\n }),\n );\n});\n\nconst canMovePrev = computed(() => {\n if (!minDateTime.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) > startOfMonth(minDateTime.value);\n});\n\nconst canMoveNext = computed(() => {\n if (!maxDateTime.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) < startOfMonth(maxDateTime.value);\n});\n\nconst isTimeOptionEnabled = (hour: number, minute: number) => {\n const candidate = setTimePart(draftDateTime.value, hour, minute);\n return !isDateTimeDisabled(candidate);\n};\n\nconst hourOptions = computed<TimeOption[]>(() =>\n Array.from({ length: 24 }, (_, hour) => ({\n disabled: !minuteValues.value.some((minute) => isTimeOptionEnabled(hour, minute)),\n label: formatPart(hour),\n value: hour,\n })),\n);\n\nconst minuteOptions = computed<TimeOption[]>(() =>\n minuteValues.value.map((minute) => ({\n disabled: !isTimeOptionEnabled(draftDateTime.value.getHours(), minute),\n label: formatPart(minute),\n value: minute,\n })),\n);\n\nconst focusCurrentDay = () => {\n const key = toDateValue(focusedDate.value);\n nextTick(() => {\n dayRefs.get(key)?.focus();\n });\n};\n\nconst setDayRef = (\n element: Element | ComponentPublicInstance | null,\n key: string,\n) => {\n if (element instanceof HTMLButtonElement) {\n dayRefs.set(key, element);\n return;\n }\n\n dayRefs.delete(key);\n};\n\nconst openCalendar = () => {\n if (props.disabled) {\n return;\n }\n\n syncDraftState(selectedDateTime.value ?? createDefaultDraftDateTime());\n setValue(true);\n focusCurrentDay();\n};\n\nconst closeCalendar = (restoreFocus = false) => {\n setValue(false);\n\n if (restoreFocus) {\n nextTick(() => {\n triggerRef.value?.focus();\n });\n }\n};\n\nconst toggleCalendar = () => {\n if (isOpen.value) {\n closeCalendar();\n return;\n }\n\n openCalendar();\n};\n\nconst moveCalendar = (direction: 1 | -1) => {\n const nextMonth = addMonths(viewMonth.value, direction);\n syncCalendarView(nextMonth);\n focusCurrentDay();\n};\n\nconst moveFocus = (nextDate: Date) => {\n if (isDateDisabled(nextDate)) {\n return;\n }\n\n syncCalendarView(nextDate);\n focusCurrentDay();\n};\n\nconst selectDate = (date: Date) => {\n if (isDateDisabled(date)) {\n return;\n }\n\n const candidate = clampToRange(setDatePart(draftDateTime.value, date));\n draftDateTime.value = candidate;\n syncCalendarView(candidate);\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeCalendar();\n return;\n }\n\n if (\n isActivationKey(event) ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n openCalendar();\n }\n};\n\nconst onDayKeydown = (event: KeyboardEvent, date: Date) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeCalendar(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectDate(date);\n return;\n }\n\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(addDays(date, -1));\n break;\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(addDays(date, 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(addDays(date, -7));\n break;\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(addDays(date, 7));\n break;\n case 'Home':\n event.preventDefault();\n moveFocus(startOfWeek(date, props.weekStartsOn));\n break;\n case 'End':\n event.preventDefault();\n moveFocus(addDays(startOfWeek(date, props.weekStartsOn), 6));\n break;\n case 'PageUp':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? -12 : -1));\n break;\n case 'PageDown':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? 12 : 1));\n break;\n default:\n break;\n }\n};\n\nconst updateHour = (event: Event) => {\n const nextHour = Number.parseInt((event.target as HTMLSelectElement).value, 10);\n const currentMinute = draftDateTime.value.getMinutes();\n\n if (Number.isNaN(nextHour)) {\n return;\n }\n\n const availableMinutes = minuteValues.value.filter((minute) =>\n isTimeOptionEnabled(nextHour, minute),\n );\n\n if (!availableMinutes.length) {\n return;\n }\n\n const nextMinute = availableMinutes.includes(currentMinute)\n ? currentMinute\n : availableMinutes[0];\n\n draftDateTime.value = setTimePart(draftDateTime.value, nextHour, nextMinute);\n};\n\nconst updateMinute = (event: Event) => {\n const nextMinute = Number.parseInt((event.target as HTMLSelectElement).value, 10);\n const nextHour = draftDateTime.value.getHours();\n\n if (Number.isNaN(nextMinute) || !isTimeOptionEnabled(nextHour, nextMinute)) {\n return;\n }\n\n draftDateTime.value = setTimePart(draftDateTime.value, nextHour, nextMinute);\n};\n\nconst commitDraft = () => {\n const value = toDateTimeValue(draftDateTime.value);\n\n emit('update:modelValue', value);\n emit('change', value);\n emit('select', value);\n closeCalendar(true);\n};\n\nconst clearSelection = () => {\n emit('update:modelValue', '');\n emit('change', '');\n emit('select', '');\n closeCalendar(true);\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeCalendar();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n return;\n }\n\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <input\n v-if=\"hiddenInputName\"\n type=\"hidden\"\n :name=\"hiddenInputName\"\n :value=\"modelValue\"\n >\n\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"t-date-picker__trigger t-date-time-picker__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? pickerId : undefined\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n @click=\"toggleCalendar\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-date-picker__slot t-date-picker__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n\n <span\n class=\"t-date-picker__value\"\n :data-placeholder=\"selectedDateTime ? undefined : true\"\n >\n {{ triggerText }}\n </span>\n\n <span class=\"t-date-picker__slot t-date-picker__slot--suffix\">\n <slot name=\"suffix\">\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <CalendarIcon\n v-else\n v-bind=\"treeIconDefaults\"\n />\n </slot>\n </span>\n </button>\n\n <transition name=\"t-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"pickerId\"\n class=\"t-date-picker__content t-date-time-picker__content\"\n role=\"dialog\"\n aria-modal=\"false\"\n :aria-labelledby=\"captionId\"\n >\n <div class=\"t-date-time-picker__calendar\">\n <div class=\"t-date-picker__header\">\n <button\n type=\"button\"\n class=\"t-date-picker__nav\"\n :disabled=\"!canMovePrev\"\n aria-label=\"Previous month\"\n @click=\"moveCalendar(-1)\"\n >\n <ChevronLeftIcon v-bind=\"treeIconDefaults\" />\n </button>\n\n <p\n :id=\"captionId\"\n class=\"t-date-picker__month\"\n >\n {{ monthLabel }}\n </p>\n\n <button\n type=\"button\"\n class=\"t-date-picker__nav\"\n :disabled=\"!canMoveNext\"\n aria-label=\"Next month\"\n @click=\"moveCalendar(1)\"\n >\n <ChevronRightIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <div\n class=\"t-date-picker__weekdays\"\n aria-hidden=\"true\"\n >\n <span\n v-for=\"label in weekdayLabels\"\n :key=\"label\"\n class=\"t-date-picker__weekday\"\n >\n {{ label }}\n </span>\n </div>\n\n <div\n class=\"t-date-picker__grid\"\n role=\"grid\"\n :aria-labelledby=\"captionId\"\n >\n <div\n v-for=\"(week, weekIndex) in cells\"\n :key=\"weekIndex\"\n class=\"t-date-picker__row\"\n role=\"row\"\n >\n <div\n v-for=\"cell in week\"\n :key=\"cell.key\"\n class=\"t-date-picker__cell\"\n role=\"gridcell\"\n :aria-selected=\"cell.isSelected\"\n >\n <button\n :ref=\"(element) => setDayRef(element, cell.key)\"\n type=\"button\"\n class=\"t-date-picker__day\"\n :class=\"{\n 'is-muted': !cell.inMonth,\n 'is-selected': cell.isSelected,\n 'is-today': cell.isToday,\n }\"\n :data-date=\"cell.key\"\n :tabindex=\"cell.isFocused ? 0 : -1\"\n :disabled=\"cell.disabled\"\n :aria-pressed=\"cell.isSelected\"\n @click=\"selectDate(cell.date)\"\n @keydown=\"onDayKeydown($event, cell.date)\"\n >\n {{ cell.dayLabel }}\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"t-date-time-picker__summary\">\n <p class=\"t-date-time-picker__eyebrow\">\n Selected slot\n </p>\n <p class=\"t-date-time-picker__summary-value\">\n {{ draftPreview }}\n </p>\n </div>\n\n <div class=\"t-date-time-picker__time\">\n <label class=\"t-date-time-picker__time-field\">\n <span class=\"t-date-time-picker__time-label\">Hour</span>\n <select\n class=\"t-date-time-picker__select\"\n :value=\"draftDateTime.getHours()\"\n aria-label=\"Select hour\"\n @change=\"updateHour\"\n >\n <option\n v-for=\"option in hourOptions\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </option>\n </select>\n </label>\n\n <label class=\"t-date-time-picker__time-field\">\n <span class=\"t-date-time-picker__time-label\">Minute</span>\n <select\n class=\"t-date-time-picker__select\"\n :value=\"draftDateTime.getMinutes()\"\n aria-label=\"Select minute\"\n @change=\"updateMinute\"\n >\n <option\n v-for=\"option in minuteOptions\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </option>\n </select>\n </label>\n </div>\n\n <div class=\"t-date-time-picker__footer\">\n <button\n type=\"button\"\n class=\"t-button t-button--ghost t-button--sm\"\n @click=\"clearSelection\"\n >\n Clear\n </button>\n <button\n type=\"button\"\n class=\"t-button t-button--solid t-button--sm\"\n @click=\"commitDraft\"\n >\n Apply\n </button>\n </div>\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n addDays,\n addMonths,\n createId,\n isActivationKey,\n isEscapeKey,\n isSameDay,\n startOfDay,\n startOfMonth,\n startOfWeek,\n toDateValue,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n type ComponentPublicInstance,\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\ninterface CalendarCell {\n date: Date;\n dayLabel: number;\n disabled: boolean;\n inMonth: boolean;\n isFocused: boolean;\n isSelected: boolean;\n isToday: boolean;\n key: string;\n}\n\ninterface TimeOption {\n disabled: boolean;\n label: string;\n value: number;\n}\n\nconst CalendarIcon = getTreeIcon('calendar');\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst dateOnlyPattern = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nconst dateTimePattern = /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})(?::(\\d{2}))?$/;\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n open?: boolean;\n defaultOpen?: boolean;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n locale?: string;\n min?: string;\n max?: string;\n weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n id?: string;\n step?: number;\n }>(),\n {\n modelValue: '',\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: 'Select date and time',\n locale: 'en-US',\n min: '',\n max: '',\n weekStartsOn: 0,\n id: undefined,\n step: 60,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n change: [value: string];\n select: [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst cloneDate = (value: Date) => new Date(value.getTime());\n\nconst formatPart = (value: number) => `${value}`.padStart(2, '0');\n\nconst endOfDay = (date: Date) =>\n new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);\n\nconst parseBoundaryValue = (\n value: string | null | undefined,\n boundary: 'exact' | 'start' | 'end' = 'exact',\n) => {\n if (!value) {\n return null;\n }\n\n const dateOnlyMatch = value.match(dateOnlyPattern);\n if (dateOnlyMatch) {\n const [, yearToken, monthToken, dayToken] = dateOnlyMatch;\n const year = Number.parseInt(yearToken, 10);\n const month = Number.parseInt(monthToken, 10);\n const day = Number.parseInt(dayToken, 10);\n const hour = boundary === 'end' ? 23 : 0;\n const minute = boundary === 'end' ? 59 : 0;\n const second = boundary === 'end' ? 59 : 0;\n const millisecond = boundary === 'end' ? 999 : 0;\n const date = new Date(year, month - 1, day, hour, minute, second, millisecond);\n\n if (\n Number.isNaN(date.getTime()) ||\n date.getFullYear() !== year ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day\n ) {\n return null;\n }\n\n return date;\n }\n\n const dateTimeMatch = value.match(dateTimePattern);\n if (!dateTimeMatch) {\n return null;\n }\n\n const [, yearToken, monthToken, dayToken, hourToken, minuteToken, secondToken] =\n dateTimeMatch;\n const year = Number.parseInt(yearToken, 10);\n const month = Number.parseInt(monthToken, 10);\n const day = Number.parseInt(dayToken, 10);\n const hour = Number.parseInt(hourToken, 10);\n const minute = Number.parseInt(minuteToken, 10);\n const second = secondToken ? Number.parseInt(secondToken, 10) : 0;\n const date = new Date(year, month - 1, day, hour, minute, second, 0);\n\n if (\n Number.isNaN(date.getTime()) ||\n date.getFullYear() !== year ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day ||\n date.getHours() !== hour ||\n date.getMinutes() !== minute ||\n date.getSeconds() !== second\n ) {\n return null;\n }\n\n return date;\n};\n\nconst toDateTimeValue = (date: Date) =>\n `${toDateValue(date)}T${formatPart(date.getHours())}:${formatPart(date.getMinutes())}`;\n\nconst setDatePart = (source: Date, targetDate: Date) =>\n new Date(\n targetDate.getFullYear(),\n targetDate.getMonth(),\n targetDate.getDate(),\n source.getHours(),\n source.getMinutes(),\n 0,\n 0,\n );\n\nconst setTimePart = (source: Date, hour: number, minute: number) =>\n new Date(\n source.getFullYear(),\n source.getMonth(),\n source.getDate(),\n hour,\n minute,\n 0,\n 0,\n );\n\nconst resolveMinuteStep = (step: number) => {\n if (!Number.isFinite(step) || step <= 0 || step % 60 !== 0) {\n return 1;\n }\n\n const minuteStep = step / 60;\n return minuteStep >= 60 ? 1 : minuteStep;\n};\n\nconst today = startOfDay(new Date());\nconst selectedDateTime = computed(() => parseBoundaryValue(props.modelValue, 'exact'));\nconst minDateTime = computed(() => parseBoundaryValue(props.min, 'start'));\nconst maxDateTime = computed(() => parseBoundaryValue(props.max, 'end'));\nconst pickerId = props.id ?? createId('t-date-time-picker');\nconst captionId = `${pickerId}-caption`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst dayRefs = new Map<string, HTMLButtonElement>();\n\nconst clampToRange = (value: Date) => {\n let nextValue = cloneDate(value);\n\n if (minDateTime.value && nextValue < minDateTime.value) {\n nextValue = cloneDate(minDateTime.value);\n }\n\n if (maxDateTime.value && nextValue > maxDateTime.value) {\n nextValue = cloneDate(maxDateTime.value);\n }\n\n return nextValue;\n};\n\nconst createDefaultDraftDateTime = () => {\n const reference = new Date();\n const stepMilliseconds = Math.max(props.step, 60) * 1000;\n const rounded = new Date(Math.ceil(reference.getTime() / stepMilliseconds) * stepMilliseconds);\n\n rounded.setSeconds(0, 0);\n return clampToRange(rounded);\n};\n\nconst initialDateTime = selectedDateTime.value ?? createDefaultDraftDateTime();\nconst draftDateTime = ref(initialDateTime);\nconst focusedDate = ref(startOfDay(initialDateTime));\nconst viewMonth = ref(startOfMonth(initialDateTime));\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, name: _name, ...rest } = attrs;\n return rest;\n});\n\nconst hiddenInputName = computed(() =>\n typeof attrs.name === 'string' ? attrs.name : undefined,\n);\n\nconst rootClasses = computed(() => [\n 't-date-picker',\n 't-date-time-picker',\n `t-date-picker--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst triggerText = computed(() => {\n if (!selectedDateTime.value) {\n return props.placeholder;\n }\n\n return new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n month: 'long',\n year: 'numeric',\n }).format(selectedDateTime.value);\n});\n\nconst draftPreview = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n month: 'long',\n year: 'numeric',\n }).format(draftDateTime.value),\n);\n\nconst monthLabel = computed(() =>\n new Intl.DateTimeFormat(props.locale, {\n month: 'long',\n year: 'numeric',\n }).format(viewMonth.value),\n);\n\nconst weekdayLabels = computed(() => {\n const formatter = new Intl.DateTimeFormat(props.locale, { weekday: 'short' });\n const weekBase = startOfWeek(new Date(2024, 0, 7), props.weekStartsOn);\n\n return Array.from({ length: 7 }, (_, index) =>\n formatter.format(addDays(weekBase, index)),\n );\n});\n\nconst minuteStep = computed(() => resolveMinuteStep(props.step));\n\nconst minuteValues = computed(() => {\n const values = new Set<number>();\n\n for (let minute = 0; minute < 60; minute += minuteStep.value) {\n values.add(minute);\n }\n\n values.add(draftDateTime.value.getMinutes());\n\n return [...values].sort((left, right) => left - right);\n});\n\nconst isDateDisabled = (date: Date) => {\n if (props.disabled) {\n return true;\n }\n\n const dayStart = startOfDay(date);\n const dayEnd = endOfDay(date);\n\n if (minDateTime.value && dayEnd < minDateTime.value) {\n return true;\n }\n\n if (maxDateTime.value && dayStart > maxDateTime.value) {\n return true;\n }\n\n return false;\n};\n\nconst isDateTimeDisabled = (value: Date) => {\n if (props.disabled) {\n return true;\n }\n\n if (minDateTime.value && value < minDateTime.value) {\n return true;\n }\n\n if (maxDateTime.value && value > maxDateTime.value) {\n return true;\n }\n\n return false;\n};\n\nconst syncCalendarView = (date: Date) => {\n focusedDate.value = startOfDay(date);\n viewMonth.value = startOfMonth(date);\n};\n\nconst syncDraftState = (dateTime: Date) => {\n const nextValue = clampToRange(dateTime);\n draftDateTime.value = nextValue;\n syncCalendarView(nextValue);\n};\n\nwatch(\n selectedDateTime,\n (value) => {\n if (isOpen.value) {\n return;\n }\n\n syncDraftState(value ?? createDefaultDraftDateTime());\n },\n { immediate: true },\n);\n\nconst draftDate = computed(() => startOfDay(draftDateTime.value));\n\nconst cells = computed(() => {\n const startDate = startOfWeek(startOfMonth(viewMonth.value), props.weekStartsOn);\n\n return Array.from({ length: 6 }, (_, weekIndex) =>\n Array.from({ length: 7 }, (_, dayIndex) => {\n const date = addDays(startDate, weekIndex * 7 + dayIndex);\n const key = toDateValue(date);\n\n return {\n date,\n dayLabel: date.getDate(),\n disabled: isDateDisabled(date),\n inMonth: date.getMonth() === viewMonth.value.getMonth(),\n isFocused: isSameDay(date, focusedDate.value),\n isSelected: isSameDay(date, draftDate.value),\n isToday: isSameDay(date, today),\n key,\n } satisfies CalendarCell;\n }),\n );\n});\n\nconst canMovePrev = computed(() => {\n if (!minDateTime.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) > startOfMonth(minDateTime.value);\n});\n\nconst canMoveNext = computed(() => {\n if (!maxDateTime.value) {\n return true;\n }\n\n return startOfMonth(viewMonth.value) < startOfMonth(maxDateTime.value);\n});\n\nconst isTimeOptionEnabled = (hour: number, minute: number) => {\n const candidate = setTimePart(draftDateTime.value, hour, minute);\n return !isDateTimeDisabled(candidate);\n};\n\nconst hourOptions = computed<TimeOption[]>(() =>\n Array.from({ length: 24 }, (_, hour) => ({\n disabled: !minuteValues.value.some((minute) => isTimeOptionEnabled(hour, minute)),\n label: formatPart(hour),\n value: hour,\n })),\n);\n\nconst minuteOptions = computed<TimeOption[]>(() =>\n minuteValues.value.map((minute) => ({\n disabled: !isTimeOptionEnabled(draftDateTime.value.getHours(), minute),\n label: formatPart(minute),\n value: minute,\n })),\n);\n\nconst focusCurrentDay = () => {\n const key = toDateValue(focusedDate.value);\n nextTick(() => {\n dayRefs.get(key)?.focus();\n });\n};\n\nconst setDayRef = (\n element: Element | ComponentPublicInstance | null,\n key: string,\n) => {\n if (element instanceof HTMLButtonElement) {\n dayRefs.set(key, element);\n return;\n }\n\n dayRefs.delete(key);\n};\n\nconst openCalendar = () => {\n if (props.disabled) {\n return;\n }\n\n syncDraftState(selectedDateTime.value ?? createDefaultDraftDateTime());\n setValue(true);\n focusCurrentDay();\n};\n\nconst closeCalendar = (restoreFocus = false) => {\n setValue(false);\n\n if (restoreFocus) {\n nextTick(() => {\n triggerRef.value?.focus();\n });\n }\n};\n\nconst toggleCalendar = () => {\n if (isOpen.value) {\n closeCalendar();\n return;\n }\n\n openCalendar();\n};\n\nconst moveCalendar = (direction: 1 | -1) => {\n const nextMonth = addMonths(viewMonth.value, direction);\n syncCalendarView(nextMonth);\n focusCurrentDay();\n};\n\nconst moveFocus = (nextDate: Date) => {\n if (isDateDisabled(nextDate)) {\n return;\n }\n\n syncCalendarView(nextDate);\n focusCurrentDay();\n};\n\nconst selectDate = (date: Date) => {\n if (isDateDisabled(date)) {\n return;\n }\n\n const candidate = clampToRange(setDatePart(draftDateTime.value, date));\n draftDateTime.value = candidate;\n syncCalendarView(candidate);\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeCalendar();\n return;\n }\n\n if (\n isActivationKey(event) ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n openCalendar();\n }\n};\n\nconst onDayKeydown = (event: KeyboardEvent, date: Date) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeCalendar(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectDate(date);\n return;\n }\n\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(addDays(date, -1));\n break;\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(addDays(date, 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(addDays(date, -7));\n break;\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(addDays(date, 7));\n break;\n case 'Home':\n event.preventDefault();\n moveFocus(startOfWeek(date, props.weekStartsOn));\n break;\n case 'End':\n event.preventDefault();\n moveFocus(addDays(startOfWeek(date, props.weekStartsOn), 6));\n break;\n case 'PageUp':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? -12 : -1));\n break;\n case 'PageDown':\n event.preventDefault();\n moveFocus(addMonths(date, event.shiftKey ? 12 : 1));\n break;\n default:\n break;\n }\n};\n\nconst updateHour = (event: Event) => {\n const nextHour = Number.parseInt((event.target as HTMLSelectElement).value, 10);\n const currentMinute = draftDateTime.value.getMinutes();\n\n if (Number.isNaN(nextHour)) {\n return;\n }\n\n const availableMinutes = minuteValues.value.filter((minute) =>\n isTimeOptionEnabled(nextHour, minute),\n );\n\n if (!availableMinutes.length) {\n return;\n }\n\n const nextMinute = availableMinutes.includes(currentMinute)\n ? currentMinute\n : availableMinutes[0];\n\n draftDateTime.value = setTimePart(draftDateTime.value, nextHour, nextMinute);\n};\n\nconst updateMinute = (event: Event) => {\n const nextMinute = Number.parseInt((event.target as HTMLSelectElement).value, 10);\n const nextHour = draftDateTime.value.getHours();\n\n if (Number.isNaN(nextMinute) || !isTimeOptionEnabled(nextHour, nextMinute)) {\n return;\n }\n\n draftDateTime.value = setTimePart(draftDateTime.value, nextHour, nextMinute);\n};\n\nconst commitDraft = () => {\n const value = toDateTimeValue(draftDateTime.value);\n\n emit('update:modelValue', value);\n emit('change', value);\n emit('select', value);\n closeCalendar(true);\n};\n\nconst clearSelection = () => {\n emit('update:modelValue', '');\n emit('change', '');\n emit('select', '');\n closeCalendar(true);\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeCalendar();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n return;\n }\n\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <input\n v-if=\"hiddenInputName\"\n type=\"hidden\"\n :name=\"hiddenInputName\"\n :value=\"modelValue\"\n >\n\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"t-date-picker__trigger t-date-time-picker__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? pickerId : undefined\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n @click=\"toggleCalendar\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-date-picker__slot t-date-picker__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n\n <span\n class=\"t-date-picker__value\"\n :data-placeholder=\"selectedDateTime ? undefined : true\"\n >\n {{ triggerText }}\n </span>\n\n <span class=\"t-date-picker__slot t-date-picker__slot--suffix\">\n <slot name=\"suffix\">\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <CalendarIcon\n v-else\n v-bind=\"treeIconDefaults\"\n />\n </slot>\n </span>\n </button>\n\n <transition name=\"t-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"pickerId\"\n class=\"t-date-picker__content t-date-time-picker__content\"\n role=\"dialog\"\n aria-modal=\"false\"\n :aria-labelledby=\"captionId\"\n >\n <div class=\"t-date-time-picker__calendar\">\n <div class=\"t-date-picker__header\">\n <button\n type=\"button\"\n class=\"t-date-picker__nav\"\n :disabled=\"!canMovePrev\"\n aria-label=\"Previous month\"\n @click=\"moveCalendar(-1)\"\n >\n <ChevronLeftIcon v-bind=\"treeIconDefaults\" />\n </button>\n\n <p\n :id=\"captionId\"\n class=\"t-date-picker__month\"\n >\n {{ monthLabel }}\n </p>\n\n <button\n type=\"button\"\n class=\"t-date-picker__nav\"\n :disabled=\"!canMoveNext\"\n aria-label=\"Next month\"\n @click=\"moveCalendar(1)\"\n >\n <ChevronRightIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <div\n class=\"t-date-picker__weekdays\"\n aria-hidden=\"true\"\n >\n <span\n v-for=\"label in weekdayLabels\"\n :key=\"label\"\n class=\"t-date-picker__weekday\"\n >\n {{ label }}\n </span>\n </div>\n\n <div\n class=\"t-date-picker__grid\"\n role=\"grid\"\n :aria-labelledby=\"captionId\"\n >\n <div\n v-for=\"(week, weekIndex) in cells\"\n :key=\"weekIndex\"\n class=\"t-date-picker__row\"\n role=\"row\"\n >\n <div\n v-for=\"cell in week\"\n :key=\"cell.key\"\n class=\"t-date-picker__cell\"\n role=\"gridcell\"\n :aria-selected=\"cell.isSelected\"\n >\n <button\n :ref=\"(element) => setDayRef(element, cell.key)\"\n type=\"button\"\n class=\"t-date-picker__day\"\n :class=\"{\n 'is-muted': !cell.inMonth,\n 'is-selected': cell.isSelected,\n 'is-today': cell.isToday,\n }\"\n :data-date=\"cell.key\"\n :tabindex=\"cell.isFocused ? 0 : -1\"\n :disabled=\"cell.disabled\"\n :aria-pressed=\"cell.isSelected\"\n @click=\"selectDate(cell.date)\"\n @keydown=\"onDayKeydown($event, cell.date)\"\n >\n {{ cell.dayLabel }}\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"t-date-time-picker__summary\">\n <p class=\"t-date-time-picker__eyebrow\">\n Selected slot\n </p>\n <p class=\"t-date-time-picker__summary-value\">\n {{ draftPreview }}\n </p>\n </div>\n\n <div class=\"t-date-time-picker__time\">\n <label class=\"t-date-time-picker__time-field\">\n <span class=\"t-date-time-picker__time-label\">Hour</span>\n <select\n class=\"t-date-time-picker__select\"\n :value=\"draftDateTime.getHours()\"\n aria-label=\"Select hour\"\n @change=\"updateHour\"\n >\n <option\n v-for=\"option in hourOptions\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </option>\n </select>\n </label>\n\n <label class=\"t-date-time-picker__time-field\">\n <span class=\"t-date-time-picker__time-label\">Minute</span>\n <select\n class=\"t-date-time-picker__select\"\n :value=\"draftDateTime.getMinutes()\"\n aria-label=\"Select minute\"\n @change=\"updateMinute\"\n >\n <option\n v-for=\"option in minuteOptions\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </option>\n </select>\n </label>\n </div>\n\n <div class=\"t-date-time-picker__footer\">\n <button\n type=\"button\"\n class=\"t-button t-button--ghost t-button--sm\"\n @click=\"clearSelection\"\n >\n Clear\n </button>\n <button\n type=\"button\"\n class=\"t-button t-button--solid t-button--sm\"\n @click=\"commitDraft\"\n >\n Apply\n </button>\n </div>\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n createId,\n focusFirst,\n focusLast,\n getFocusableElements,\n isEscapeKey,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TDrawerSide, TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n side?: TDrawerSide;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n side: 'right',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close drawer',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst drawerId = props.id ?? createId('t-drawer');\nconst titleId = `${drawerId}-title`;\nconst descriptionId = `${drawerId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-drawer', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-drawer__surface',\n `t-drawer__surface--${props.size}`,\n `t-drawer__surface--${props.side}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\n};\n\nconst focusSurface = () => {\n nextTick(() => {\n if (!surfaceRef.value) {\n return;\n }\n\n const focused = focusFirst(surfaceRef.value);\n if (!focused) {\n surfaceRef.value.focus();\n }\n });\n};\n\nconst openDrawer = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeDrawer = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openDrawer();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeDrawer();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeDrawer();\n return;\n }\n\n if (event.key !== 'Tab' || !surfaceRef.value) {\n return;\n }\n\n const focusable = getFocusableElements(surfaceRef.value);\n\n if (!focusable.length) {\n event.preventDefault();\n surfaceRef.value.focus();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n focusLast(surfaceRef.value);\n }\n\n if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n focusFirst(surfaceRef.value);\n }\n};\n\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-drawer__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-drawer-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-drawer__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-drawer__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div\n :id=\"drawerId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-drawer__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-drawer__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-drawer__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-drawer__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeDrawer\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-drawer__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-drawer__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-drawer__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n createId,\n focusFirst,\n focusLast,\n getFocusableElements,\n isEscapeKey,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TDrawerSide, TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n side?: TDrawerSide;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n side: 'right',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close drawer',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst drawerId = props.id ?? createId('t-drawer');\nconst titleId = `${drawerId}-title`;\nconst descriptionId = `${drawerId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-drawer', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-drawer__surface',\n `t-drawer__surface--${props.size}`,\n `t-drawer__surface--${props.side}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\n};\n\nconst focusSurface = () => {\n nextTick(() => {\n if (!surfaceRef.value) {\n return;\n }\n\n const focused = focusFirst(surfaceRef.value);\n if (!focused) {\n surfaceRef.value.focus();\n }\n });\n};\n\nconst openDrawer = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeDrawer = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openDrawer();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeDrawer();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeDrawer();\n return;\n }\n\n if (event.key !== 'Tab' || !surfaceRef.value) {\n return;\n }\n\n const focusable = getFocusableElements(surfaceRef.value);\n\n if (!focusable.length) {\n event.preventDefault();\n surfaceRef.value.focus();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n focusLast(surfaceRef.value);\n }\n\n if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n focusFirst(surfaceRef.value);\n }\n};\n\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-drawer__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-drawer-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-drawer__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-drawer__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div\n :id=\"drawerId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-drawer__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-drawer__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-drawer__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-drawer__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeDrawer\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-drawer__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-drawer__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-drawer__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TDropdownItem {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TDropdownItem[];\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n label?: string;\n }>(),\n {\n items: () => [],\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n label: '',\n },\n);\n\nconst emit = defineEmits<{\n select: [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n trigger(props: { isOpen: boolean }): unknown;\n item(props: { item: TDropdownItem; index: number }): unknown;\n}>();\n\nconst attrs = useAttrs();\nconst menuId = createId('t-dropdown');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-dropdown',\n `t-dropdown--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst enabledItems = computed(() => props.items.filter((i) => !i.disabled));\n\nconst openMenu = () => {\n if (props.disabled) return;\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n setValue(true);\n nextTick(() => focusItem(focusedIndex.value));\n};\n\nconst closeMenu = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst toggleMenu = () => {\n if (isOpen.value) {\n closeMenu();\n } else {\n openMenu();\n }\n};\n\nconst selectItem = (item: TDropdownItem) => {\n if (item.disabled) return;\n emit('select', item.value);\n closeMenu(true);\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n if (!item) return;\n const el = itemRefs.value.get(item.value);\n el?.focus();\n};\n\nconst setItemRef = (el: Element | null, value: string) => {\n if (el instanceof HTMLElement) {\n itemRefs.value.set(value, el);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.items.length) {\n if (!props.items[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusItem(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeMenu();\n return;\n }\n\n if (isActivationKey(event) || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n openMenu();\n }\n};\n\nconst onItemKeydown = (event: KeyboardEvent, item: TDropdownItem) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeMenu(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(item);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n focusItem(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[enabledItems.value.length - 1])\n : props.items.length - 1;\n focusItem(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeMenu();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span class=\"t-dropdown__trigger-wrapper\">\n <slot\n name=\"trigger\"\n :is-open=\"isOpen\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"t-dropdown__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? menuId : undefined\"\n aria-haspopup=\"menu\"\n :aria-expanded=\"isOpen\"\n @click=\"toggleMenu\"\n @keydown=\"onTriggerKeydown\"\n >\n <span class=\"t-dropdown__label\">{{ label }}</span>\n <svg\n class=\"t-dropdown__chevron\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </button>\n </slot>\n </span>\n <transition name=\"t-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"menuId\"\n role=\"menu\"\n class=\"t-dropdown__menu\"\n :aria-label=\"label || undefined\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n :ref=\"(el) => setItemRef(el as Element | null, item.value)\"\n role=\"menuitem\"\n class=\"t-dropdown__item\"\n :class=\"{\n 'is-disabled': item.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-disabled=\"item.disabled || undefined\"\n :tabindex=\"item.disabled ? -1 : 0\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n {{ item.label }}\n </slot>\n </li>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TDropdownItem {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TDropdownItem[];\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n label?: string;\n }>(),\n {\n items: () => [],\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n label: '',\n },\n);\n\nconst emit = defineEmits<{\n select: [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n trigger(props: { isOpen: boolean }): unknown;\n item(props: { item: TDropdownItem; index: number }): unknown;\n}>();\n\nconst attrs = useAttrs();\nconst menuId = createId('t-dropdown');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-dropdown',\n `t-dropdown--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst enabledItems = computed(() => props.items.filter((i) => !i.disabled));\n\nconst openMenu = () => {\n if (props.disabled) return;\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n setValue(true);\n nextTick(() => focusItem(focusedIndex.value));\n};\n\nconst closeMenu = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst toggleMenu = () => {\n if (isOpen.value) {\n closeMenu();\n } else {\n openMenu();\n }\n};\n\nconst selectItem = (item: TDropdownItem) => {\n if (item.disabled) return;\n emit('select', item.value);\n closeMenu(true);\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n if (!item) return;\n const el = itemRefs.value.get(item.value);\n el?.focus();\n};\n\nconst setItemRef = (el: Element | null, value: string) => {\n if (el instanceof HTMLElement) {\n itemRefs.value.set(value, el);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.items.length) {\n if (!props.items[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusItem(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeMenu();\n return;\n }\n\n if (isActivationKey(event) || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n openMenu();\n }\n};\n\nconst onItemKeydown = (event: KeyboardEvent, item: TDropdownItem) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeMenu(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(item);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[0])\n : 0;\n focusItem(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledItems.value.length > 0\n ? props.items.indexOf(enabledItems.value[enabledItems.value.length - 1])\n : props.items.length - 1;\n focusItem(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeMenu();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span class=\"t-dropdown__trigger-wrapper\">\n <slot\n name=\"trigger\"\n :is-open=\"isOpen\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"t-dropdown__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? menuId : undefined\"\n aria-haspopup=\"menu\"\n :aria-expanded=\"isOpen\"\n @click=\"toggleMenu\"\n @keydown=\"onTriggerKeydown\"\n >\n <span class=\"t-dropdown__label\">{{ label }}</span>\n <svg\n class=\"t-dropdown__chevron\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </button>\n </slot>\n </span>\n <transition name=\"t-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"menuId\"\n role=\"menu\"\n class=\"t-dropdown__menu\"\n :aria-label=\"label || undefined\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n :ref=\"(el) => setItemRef(el as Element | null, item.value)\"\n role=\"menuitem\"\n class=\"t-dropdown__item\"\n :class=\"{\n 'is-disabled': item.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-disabled=\"item.disabled || undefined\"\n :tabindex=\"item.disabled ? -1 : 0\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n {{ item.label }}\n </slot>\n </li>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst slots = defineSlots<{\n icon?: () => unknown;\n title?: () => unknown;\n description?: () => unknown;\n default?: () => unknown;\n actions?: () => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TSize;\n title?: string;\n description?: string;\n }>(),\n {\n as: 'section',\n size: 'md',\n title: '',\n description: '',\n },\n);\n\nconst attrs = useAttrs();\nconst emptyStateId = createId('t-empty-state');\nconst titleId = `${emptyStateId}-title`;\nconst descriptionId = `${emptyStateId}-description`;\n\nconst hasTitle = computed(() => Boolean(props.title || slots.title));\nconst hasDescription = computed(() => Boolean(props.description || slots.description));\n\nconst classes = computed(() => [\n 't-empty-state',\n `t-empty-state--${props.size}`,\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"classes\"\n :style=\"rootStyle\"\n :aria-labelledby=\"hasTitle ? titleId : undefined\"\n :aria-describedby=\"hasDescription ? descriptionId : undefined\"\n >\n <div\n v-if=\"$slots.icon\"\n class=\"t-empty-state__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div class=\"t-empty-state__content\">\n <h2\n v-if=\"hasTitle\"\n :id=\"titleId\"\n class=\"t-empty-state__title\"\n >\n <slot name=\"title\">\n {{ title }}\n </slot>\n </h2>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n class=\"t-empty-state__description\"\n >\n <slot name=\"description\">\n {{ description }}\n </slot>\n </p>\n\n <div\n v-if=\"$slots.default\"\n class=\"t-empty-state__body\"\n >\n <slot />\n </div>\n\n <div\n v-if=\"$slots.actions\"\n class=\"t-empty-state__actions\"\n >\n <slot name=\"actions\" />\n </div>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst slots = defineSlots<{\n icon?: () => unknown;\n title?: () => unknown;\n description?: () => unknown;\n default?: () => unknown;\n actions?: () => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TSize;\n title?: string;\n description?: string;\n }>(),\n {\n as: 'section',\n size: 'md',\n title: '',\n description: '',\n },\n);\n\nconst attrs = useAttrs();\nconst emptyStateId = createId('t-empty-state');\nconst titleId = `${emptyStateId}-title`;\nconst descriptionId = `${emptyStateId}-description`;\n\nconst hasTitle = computed(() => Boolean(props.title || slots.title));\nconst hasDescription = computed(() => Boolean(props.description || slots.description));\n\nconst classes = computed(() => [\n 't-empty-state',\n `t-empty-state--${props.size}`,\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"classes\"\n :style=\"rootStyle\"\n :aria-labelledby=\"hasTitle ? titleId : undefined\"\n :aria-describedby=\"hasDescription ? descriptionId : undefined\"\n >\n <div\n v-if=\"$slots.icon\"\n class=\"t-empty-state__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div class=\"t-empty-state__content\">\n <h2\n v-if=\"hasTitle\"\n :id=\"titleId\"\n class=\"t-empty-state__title\"\n >\n <slot name=\"title\">\n {{ title }}\n </slot>\n </h2>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n class=\"t-empty-state__description\"\n >\n <slot name=\"description\">\n {{ description }}\n </slot>\n </p>\n\n <div\n v-if=\"$slots.default\"\n class=\"t-empty-state__body\"\n >\n <slot />\n </div>\n\n <div\n v-if=\"$slots.actions\"\n class=\"t-empty-state__actions\"\n >\n <slot name=\"actions\" />\n </div>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey } from '@treeui/utils';\nimport { computed, onBeforeUnmount, onMounted, ref, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport type TFileUploadRejectionReason =\n | 'file-invalid-type'\n | 'file-too-large'\n | 'too-many-files';\n\nexport interface TFileUploadRejection {\n file: File;\n reason: TFileUploadRejectionReason;\n message: string;\n}\n\nconst slots = defineSlots<{\n icon?: () => unknown;\n default?: (props: {\n files: File[];\n isDragActive: boolean;\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n file?: (props: {\n file: File;\n index: number;\n removeFile: () => void;\n }) => unknown;\n actions?: (props: {\n files: File[];\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: File[];\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n accept?: string;\n multiple?: boolean;\n maxFiles?: number | null;\n maxFileSize?: number | null;\n label?: string;\n description?: string;\n buttonLabel?: string;\n filesLabel?: string;\n paste?: boolean;\n drop?: boolean;\n showFileList?: boolean;\n }>(),\n {\n modelValue: () => [],\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n accept: '',\n multiple: true,\n label: 'Drop files here',\n description: 'Click to browse, drag and drop, or paste with Ctrl+V.',\n buttonLabel: 'Browse files',\n filesLabel: 'Selected files',\n maxFiles: null,\n maxFileSize: null,\n paste: true,\n drop: true,\n showFileList: true,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [files: File[]];\n 'files-accepted': [files: File[]];\n 'files-rejected': [rejections: TFileUploadRejection[]];\n}>();\n\nconst attrs = useAttrs();\nconst rootRef = ref<HTMLElement | null>(null);\nconst inputRef = ref<HTMLInputElement | null>(null);\nconst isDragActive = ref(false);\nconst isFocusedWithin = ref(false);\nconst dragDepth = ref(0);\nconst feedbackMessages = ref<string[]>([]);\n\nconst uploadId = createId('t-file-upload');\nconst descriptionId = `${uploadId}-description`;\nconst feedbackId = `${uploadId}-feedback`;\nconst filesId = `${uploadId}-files`;\n\nconst isUnavailable = computed(() => props.disabled || props.loading);\nconst hasFiles = computed(() => props.modelValue.length > 0);\nconst hasCustomBody = computed(() => Boolean(slots.default));\n\nconst effectiveMaxFiles = computed(() => {\n if (!props.multiple) {\n return 1;\n }\n\n if (typeof props.maxFiles !== 'number') {\n return Number.POSITIVE_INFINITY;\n }\n\n return Math.max(props.maxFiles, 0);\n});\n\nconst rootClasses = computed(() => [\n 't-file-upload',\n `t-file-upload--${props.size}`,\n {\n 'is-disabled': isUnavailable.value,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-drag-active': isDragActive.value,\n 'has-files': hasFiles.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst describedBy = computed(() => {\n const ids: string[] = [];\n\n if (props.description && !hasCustomBody.value) {\n ids.push(descriptionId);\n }\n\n if (feedbackMessages.value.length > 0) {\n ids.push(feedbackId);\n }\n\n if (props.showFileList && hasFiles.value) {\n ids.push(filesId);\n }\n\n return ids.length > 0 ? ids.join(' ') : undefined;\n});\n\nconst selectedFilesLabel = computed(() => `${props.filesLabel} (${props.modelValue.length})`);\n\nconst formatFileSize = (size: number) => {\n if (size < 1024) {\n return `${size} B`;\n }\n\n const units = ['KB', 'MB', 'GB'];\n let value = size / 1024;\n let unitIndex = 0;\n\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex += 1;\n }\n\n const roundedValue = value >= 10 || Number.isInteger(value)\n ? Math.round(value)\n : Number(value.toFixed(1));\n\n return `${roundedValue} ${units[unitIndex]}`;\n};\n\nconst fileKey = (file: File, index: number) =>\n `${file.name}-${file.size}-${file.lastModified}-${index}`;\n\nconst matchesAccept = (file: File) => {\n if (!props.accept.trim()) {\n return true;\n }\n\n const tokens = props.accept\n .split(',')\n .map((token) => token.trim().toLowerCase())\n .filter(Boolean);\n\n const fileName = file.name.toLowerCase();\n const fileType = file.type.toLowerCase();\n\n return tokens.some((token) => {\n if (token.startsWith('.')) {\n return fileName.endsWith(token);\n }\n\n if (token.endsWith('/*')) {\n return fileType.startsWith(token.slice(0, -1));\n }\n\n return fileType === token;\n });\n};\n\nconst buildRejectionMessage = (\n file: File,\n reason: TFileUploadRejectionReason,\n) => {\n switch (reason) {\n case 'file-invalid-type':\n return `${file.name} is not an accepted file type.`;\n case 'file-too-large':\n return `${file.name} exceeds the ${formatFileSize(props.maxFileSize ?? 0)} limit.`;\n case 'too-many-files':\n return `You can only add up to ${effectiveMaxFiles.value} file${effectiveMaxFiles.value === 1 ? '' : 's'}.`;\n default:\n return `${file.name} could not be added.`;\n }\n};\n\nconst resetInputValue = () => {\n if (inputRef.value) {\n inputRef.value.value = '';\n }\n};\n\nconst openFileDialog = () => {\n if (isUnavailable.value) {\n return;\n }\n\n inputRef.value?.click();\n};\n\nconst emitFiles = (\n nextFiles: File[],\n acceptedFiles: File[],\n rejections: TFileUploadRejection[],\n) => {\n feedbackMessages.value = rejections.map((rejection) => rejection.message);\n\n if (rejections.length > 0) {\n emit('files-rejected', rejections);\n }\n\n if (acceptedFiles.length > 0) {\n emit('update:modelValue', nextFiles);\n emit('files-accepted', acceptedFiles);\n }\n};\n\nconst processFiles = (incomingFiles: File[]) => {\n if (isUnavailable.value || incomingFiles.length === 0) {\n return;\n }\n\n const nextFiles = props.multiple ? [...props.modelValue] : [];\n const acceptedFiles: File[] = [];\n const rejections: TFileUploadRejection[] = [];\n let remainingSlots = Number.isFinite(effectiveMaxFiles.value)\n ? Math.max(effectiveMaxFiles.value - nextFiles.length, 0)\n : Number.POSITIVE_INFINITY;\n\n for (const file of incomingFiles) {\n if (remainingSlots <= 0) {\n rejections.push({\n file,\n reason: 'too-many-files',\n message: buildRejectionMessage(file, 'too-many-files'),\n });\n continue;\n }\n\n if (!matchesAccept(file)) {\n rejections.push({\n file,\n reason: 'file-invalid-type',\n message: buildRejectionMessage(file, 'file-invalid-type'),\n });\n continue;\n }\n\n if (\n typeof props.maxFileSize === 'number' &&\n props.maxFileSize > 0 &&\n file.size > props.maxFileSize\n ) {\n rejections.push({\n file,\n reason: 'file-too-large',\n message: buildRejectionMessage(file, 'file-too-large'),\n });\n continue;\n }\n\n acceptedFiles.push(file);\n nextFiles.push(file);\n\n if (Number.isFinite(remainingSlots)) {\n remainingSlots -= 1;\n }\n }\n\n emitFiles(nextFiles, acceptedFiles, rejections);\n};\n\nconst removeFile = (index: number) => {\n if (isUnavailable.value) {\n return;\n }\n\n feedbackMessages.value = [];\n emit('update:modelValue', props.modelValue.filter((_, fileIndex) => fileIndex !== index));\n};\n\nconst clearFiles = () => {\n if (isUnavailable.value || !hasFiles.value) {\n return;\n }\n\n feedbackMessages.value = [];\n emit('update:modelValue', []);\n};\n\nconst hasTransferFiles = (dataTransfer?: DataTransfer | null) => {\n if (!dataTransfer) {\n return false;\n }\n\n return dataTransfer.files.length > 0 || Array.from(dataTransfer.types).includes('Files');\n};\n\nconst getClipboardFiles = (\n clipboardData?: Pick<DataTransfer, 'items'> | null,\n) => {\n if (!clipboardData?.items) {\n return [];\n }\n\n return Array.from(clipboardData.items)\n .map((item) => item.getAsFile?.() ?? null)\n .filter((file): file is File => file instanceof File);\n};\n\nconst onInputChange = (event: Event) => {\n const target = event.target as HTMLInputElement;\n processFiles(Array.from(target.files ?? []));\n resetInputValue();\n};\n\nconst onDropzoneKeydown = (event: KeyboardEvent) => {\n if (!isActivationKey(event) || isUnavailable.value) {\n return;\n }\n\n event.preventDefault();\n openFileDialog();\n};\n\nconst onFocusIn = () => {\n isFocusedWithin.value = true;\n};\n\nconst onFocusOut = (event: FocusEvent) => {\n const nextTarget = event.relatedTarget as Node | null;\n\n if (nextTarget && rootRef.value?.contains(nextTarget)) {\n return;\n }\n\n isFocusedWithin.value = false;\n};\n\nconst onPaste = (event: ClipboardEvent) => {\n if (!props.paste || isUnavailable.value) {\n return;\n }\n\n const clipboardFiles = getClipboardFiles(event.clipboardData);\n\n if (clipboardFiles.length === 0) {\n return;\n }\n\n event.preventDefault();\n processFiles(clipboardFiles);\n};\n\nconst onDocumentPaste = (event: Event) => {\n if (!isFocusedWithin.value || event.defaultPrevented) {\n return;\n }\n\n onPaste(event as ClipboardEvent);\n};\n\nconst onDragEnter = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value += 1;\n isDragActive.value = true;\n};\n\nconst onDragOver = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'copy';\n }\n\n isDragActive.value = true;\n};\n\nconst onDragLeave = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = Math.max(dragDepth.value - 1, 0);\n\n if (dragDepth.value === 0) {\n isDragActive.value = false;\n }\n};\n\nconst onDrop = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = 0;\n isDragActive.value = false;\n processFiles(Array.from(event.dataTransfer?.files ?? []));\n};\n\nonMounted(() => {\n document.addEventListener('paste', onDocumentPaste);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('paste', onDocumentPaste);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n @paste=\"onPaste\"\n >\n <input\n :id=\"uploadId\"\n ref=\"inputRef\"\n class=\"t-visually-hidden\"\n type=\"file\"\n :accept=\"accept || undefined\"\n :multiple=\"multiple\"\n :disabled=\"isUnavailable\"\n @change=\"onInputChange\"\n >\n\n <div\n class=\"t-file-upload__dropzone\"\n :aria-busy=\"loading || undefined\"\n :aria-controls=\"showFileList && hasFiles ? filesId : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-disabled=\"isUnavailable || undefined\"\n :aria-invalid=\"invalid || undefined\"\n role=\"button\"\n :tabindex=\"isUnavailable ? -1 : 0\"\n @click=\"openFileDialog\"\n @keydown=\"onDropzoneKeydown\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <div\n v-if=\"$slots.icon || !$slots.default\"\n class=\"t-file-upload__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\">\n <span class=\"t-file-upload__icon-mark\">+</span>\n </slot>\n </div>\n\n <div class=\"t-file-upload__content\">\n <slot\n :files=\"modelValue\"\n :is-drag-active=\"isDragActive\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n >\n <p class=\"t-file-upload__label\">\n {{ label }}\n </p>\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-file-upload__description\"\n >\n {{ description }}\n </p>\n <span class=\"t-file-upload__browse\">\n {{ buttonLabel }}\n </span>\n </slot>\n </div>\n\n <TSpinner\n v-if=\"loading\"\n class=\"t-file-upload__spinner\"\n size=\"sm\"\n label=\"Uploading files\"\n />\n </div>\n\n <ul\n v-if=\"feedbackMessages.length > 0\"\n :id=\"feedbackId\"\n class=\"t-file-upload__feedback\"\n aria-live=\"polite\"\n >\n <li\n v-for=\"message in feedbackMessages\"\n :key=\"message\"\n >\n {{ message }}\n </li>\n </ul>\n\n <div\n v-if=\"showFileList && hasFiles\"\n class=\"t-file-upload__files\"\n >\n <div class=\"t-file-upload__files-header\">\n <p\n :id=\"filesId\"\n class=\"t-file-upload__files-label\"\n >\n {{ selectedFilesLabel }}\n </p>\n\n <button\n class=\"t-file-upload__clear\"\n type=\"button\"\n :disabled=\"isUnavailable\"\n @click=\"clearFiles\"\n >\n Clear all\n </button>\n </div>\n\n <ul class=\"t-file-upload__list\">\n <li\n v-for=\"(file, index) in modelValue\"\n :key=\"fileKey(file, index)\"\n class=\"t-file-upload__file\"\n >\n <slot\n name=\"file\"\n :file=\"file\"\n :index=\"index\"\n :remove-file=\"() => removeFile(index)\"\n >\n <div class=\"t-file-upload__file-copy\">\n <p class=\"t-file-upload__file-name\">\n {{ file.name }}\n </p>\n <p class=\"t-file-upload__file-meta\">\n {{ formatFileSize(file.size) }}\n </p>\n </div>\n\n <button\n class=\"t-file-upload__remove\"\n type=\"button\"\n :disabled=\"isUnavailable\"\n :aria-label=\"`Remove ${file.name}`\"\n @click=\"removeFile(index)\"\n >\n Remove\n </button>\n </slot>\n </li>\n </ul>\n </div>\n\n <div\n v-if=\"$slots.actions\"\n class=\"t-file-upload__actions\"\n >\n <slot\n name=\"actions\"\n :files=\"modelValue\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey } from '@treeui/utils';\nimport { computed, onBeforeUnmount, onMounted, ref, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport type TFileUploadRejectionReason =\n | 'file-invalid-type'\n | 'file-too-large'\n | 'too-many-files';\n\nexport interface TFileUploadRejection {\n file: File;\n reason: TFileUploadRejectionReason;\n message: string;\n}\n\nconst slots = defineSlots<{\n icon?: () => unknown;\n default?: (props: {\n files: File[];\n isDragActive: boolean;\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n file?: (props: {\n file: File;\n index: number;\n removeFile: () => void;\n }) => unknown;\n actions?: (props: {\n files: File[];\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: File[];\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n accept?: string;\n multiple?: boolean;\n maxFiles?: number | null;\n maxFileSize?: number | null;\n label?: string;\n description?: string;\n buttonLabel?: string;\n filesLabel?: string;\n paste?: boolean;\n drop?: boolean;\n showFileList?: boolean;\n }>(),\n {\n modelValue: () => [],\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n accept: '',\n multiple: true,\n label: 'Drop files here',\n description: 'Click to browse, drag and drop, or paste with Ctrl+V.',\n buttonLabel: 'Browse files',\n filesLabel: 'Selected files',\n maxFiles: null,\n maxFileSize: null,\n paste: true,\n drop: true,\n showFileList: true,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [files: File[]];\n 'files-accepted': [files: File[]];\n 'files-rejected': [rejections: TFileUploadRejection[]];\n}>();\n\nconst attrs = useAttrs();\nconst rootRef = ref<HTMLElement | null>(null);\nconst inputRef = ref<HTMLInputElement | null>(null);\nconst isDragActive = ref(false);\nconst isFocusedWithin = ref(false);\nconst dragDepth = ref(0);\nconst feedbackMessages = ref<string[]>([]);\n\nconst uploadId = createId('t-file-upload');\nconst descriptionId = `${uploadId}-description`;\nconst feedbackId = `${uploadId}-feedback`;\nconst filesId = `${uploadId}-files`;\n\nconst isUnavailable = computed(() => props.disabled || props.loading);\nconst hasFiles = computed(() => props.modelValue.length > 0);\nconst hasCustomBody = computed(() => Boolean(slots.default));\n\nconst effectiveMaxFiles = computed(() => {\n if (!props.multiple) {\n return 1;\n }\n\n if (typeof props.maxFiles !== 'number') {\n return Number.POSITIVE_INFINITY;\n }\n\n return Math.max(props.maxFiles, 0);\n});\n\nconst rootClasses = computed(() => [\n 't-file-upload',\n `t-file-upload--${props.size}`,\n {\n 'is-disabled': isUnavailable.value,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-drag-active': isDragActive.value,\n 'has-files': hasFiles.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst describedBy = computed(() => {\n const ids: string[] = [];\n\n if (props.description && !hasCustomBody.value) {\n ids.push(descriptionId);\n }\n\n if (feedbackMessages.value.length > 0) {\n ids.push(feedbackId);\n }\n\n if (props.showFileList && hasFiles.value) {\n ids.push(filesId);\n }\n\n return ids.length > 0 ? ids.join(' ') : undefined;\n});\n\nconst selectedFilesLabel = computed(() => `${props.filesLabel} (${props.modelValue.length})`);\n\nconst formatFileSize = (size: number) => {\n if (size < 1024) {\n return `${size} B`;\n }\n\n const units = ['KB', 'MB', 'GB'];\n let value = size / 1024;\n let unitIndex = 0;\n\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex += 1;\n }\n\n const roundedValue = value >= 10 || Number.isInteger(value)\n ? Math.round(value)\n : Number(value.toFixed(1));\n\n return `${roundedValue} ${units[unitIndex]}`;\n};\n\nconst fileKey = (file: File, index: number) =>\n `${file.name}-${file.size}-${file.lastModified}-${index}`;\n\nconst matchesAccept = (file: File) => {\n if (!props.accept.trim()) {\n return true;\n }\n\n const tokens = props.accept\n .split(',')\n .map((token) => token.trim().toLowerCase())\n .filter(Boolean);\n\n const fileName = file.name.toLowerCase();\n const fileType = file.type.toLowerCase();\n\n return tokens.some((token) => {\n if (token.startsWith('.')) {\n return fileName.endsWith(token);\n }\n\n if (token.endsWith('/*')) {\n return fileType.startsWith(token.slice(0, -1));\n }\n\n return fileType === token;\n });\n};\n\nconst buildRejectionMessage = (\n file: File,\n reason: TFileUploadRejectionReason,\n) => {\n switch (reason) {\n case 'file-invalid-type':\n return `${file.name} is not an accepted file type.`;\n case 'file-too-large':\n return `${file.name} exceeds the ${formatFileSize(props.maxFileSize ?? 0)} limit.`;\n case 'too-many-files':\n return `You can only add up to ${effectiveMaxFiles.value} file${effectiveMaxFiles.value === 1 ? '' : 's'}.`;\n default:\n return `${file.name} could not be added.`;\n }\n};\n\nconst resetInputValue = () => {\n if (inputRef.value) {\n inputRef.value.value = '';\n }\n};\n\nconst openFileDialog = () => {\n if (isUnavailable.value) {\n return;\n }\n\n inputRef.value?.click();\n};\n\nconst emitFiles = (\n nextFiles: File[],\n acceptedFiles: File[],\n rejections: TFileUploadRejection[],\n) => {\n feedbackMessages.value = rejections.map((rejection) => rejection.message);\n\n if (rejections.length > 0) {\n emit('files-rejected', rejections);\n }\n\n if (acceptedFiles.length > 0) {\n emit('update:modelValue', nextFiles);\n emit('files-accepted', acceptedFiles);\n }\n};\n\nconst processFiles = (incomingFiles: File[]) => {\n if (isUnavailable.value || incomingFiles.length === 0) {\n return;\n }\n\n const nextFiles = props.multiple ? [...props.modelValue] : [];\n const acceptedFiles: File[] = [];\n const rejections: TFileUploadRejection[] = [];\n let remainingSlots = Number.isFinite(effectiveMaxFiles.value)\n ? Math.max(effectiveMaxFiles.value - nextFiles.length, 0)\n : Number.POSITIVE_INFINITY;\n\n for (const file of incomingFiles) {\n if (remainingSlots <= 0) {\n rejections.push({\n file,\n reason: 'too-many-files',\n message: buildRejectionMessage(file, 'too-many-files'),\n });\n continue;\n }\n\n if (!matchesAccept(file)) {\n rejections.push({\n file,\n reason: 'file-invalid-type',\n message: buildRejectionMessage(file, 'file-invalid-type'),\n });\n continue;\n }\n\n if (\n typeof props.maxFileSize === 'number' &&\n props.maxFileSize > 0 &&\n file.size > props.maxFileSize\n ) {\n rejections.push({\n file,\n reason: 'file-too-large',\n message: buildRejectionMessage(file, 'file-too-large'),\n });\n continue;\n }\n\n acceptedFiles.push(file);\n nextFiles.push(file);\n\n if (Number.isFinite(remainingSlots)) {\n remainingSlots -= 1;\n }\n }\n\n emitFiles(nextFiles, acceptedFiles, rejections);\n};\n\nconst removeFile = (index: number) => {\n if (isUnavailable.value) {\n return;\n }\n\n feedbackMessages.value = [];\n emit('update:modelValue', props.modelValue.filter((_, fileIndex) => fileIndex !== index));\n};\n\nconst clearFiles = () => {\n if (isUnavailable.value || !hasFiles.value) {\n return;\n }\n\n feedbackMessages.value = [];\n emit('update:modelValue', []);\n};\n\nconst hasTransferFiles = (dataTransfer?: DataTransfer | null) => {\n if (!dataTransfer) {\n return false;\n }\n\n return dataTransfer.files.length > 0 || Array.from(dataTransfer.types).includes('Files');\n};\n\nconst getClipboardFiles = (\n clipboardData?: Pick<DataTransfer, 'items'> | null,\n) => {\n if (!clipboardData?.items) {\n return [];\n }\n\n return Array.from(clipboardData.items)\n .map((item) => item.getAsFile?.() ?? null)\n .filter((file): file is File => file instanceof File);\n};\n\nconst onInputChange = (event: Event) => {\n const target = event.target as HTMLInputElement;\n processFiles(Array.from(target.files ?? []));\n resetInputValue();\n};\n\nconst onDropzoneKeydown = (event: KeyboardEvent) => {\n if (!isActivationKey(event) || isUnavailable.value) {\n return;\n }\n\n event.preventDefault();\n openFileDialog();\n};\n\nconst onFocusIn = () => {\n isFocusedWithin.value = true;\n};\n\nconst onFocusOut = (event: FocusEvent) => {\n const nextTarget = event.relatedTarget as Node | null;\n\n if (nextTarget && rootRef.value?.contains(nextTarget)) {\n return;\n }\n\n isFocusedWithin.value = false;\n};\n\nconst onPaste = (event: ClipboardEvent) => {\n if (!props.paste || isUnavailable.value) {\n return;\n }\n\n const clipboardFiles = getClipboardFiles(event.clipboardData);\n\n if (clipboardFiles.length === 0) {\n return;\n }\n\n event.preventDefault();\n processFiles(clipboardFiles);\n};\n\nconst onDocumentPaste = (event: Event) => {\n if (!isFocusedWithin.value || event.defaultPrevented) {\n return;\n }\n\n onPaste(event as ClipboardEvent);\n};\n\nconst onDragEnter = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value += 1;\n isDragActive.value = true;\n};\n\nconst onDragOver = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'copy';\n }\n\n isDragActive.value = true;\n};\n\nconst onDragLeave = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = Math.max(dragDepth.value - 1, 0);\n\n if (dragDepth.value === 0) {\n isDragActive.value = false;\n }\n};\n\nconst onDrop = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = 0;\n isDragActive.value = false;\n processFiles(Array.from(event.dataTransfer?.files ?? []));\n};\n\nonMounted(() => {\n document.addEventListener('paste', onDocumentPaste);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('paste', onDocumentPaste);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n @paste=\"onPaste\"\n >\n <input\n :id=\"uploadId\"\n ref=\"inputRef\"\n class=\"t-visually-hidden\"\n type=\"file\"\n :accept=\"accept || undefined\"\n :multiple=\"multiple\"\n :disabled=\"isUnavailable\"\n @change=\"onInputChange\"\n >\n\n <div\n class=\"t-file-upload__dropzone\"\n :aria-busy=\"loading || undefined\"\n :aria-controls=\"showFileList && hasFiles ? filesId : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-disabled=\"isUnavailable || undefined\"\n :aria-invalid=\"invalid || undefined\"\n role=\"button\"\n :tabindex=\"isUnavailable ? -1 : 0\"\n @click=\"openFileDialog\"\n @keydown=\"onDropzoneKeydown\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <div\n v-if=\"$slots.icon || !$slots.default\"\n class=\"t-file-upload__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\">\n <span class=\"t-file-upload__icon-mark\">+</span>\n </slot>\n </div>\n\n <div class=\"t-file-upload__content\">\n <slot\n :files=\"modelValue\"\n :is-drag-active=\"isDragActive\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n >\n <p class=\"t-file-upload__label\">\n {{ label }}\n </p>\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-file-upload__description\"\n >\n {{ description }}\n </p>\n <span class=\"t-file-upload__browse\">\n {{ buttonLabel }}\n </span>\n </slot>\n </div>\n\n <TSpinner\n v-if=\"loading\"\n class=\"t-file-upload__spinner\"\n size=\"sm\"\n label=\"Uploading files\"\n />\n </div>\n\n <ul\n v-if=\"feedbackMessages.length > 0\"\n :id=\"feedbackId\"\n class=\"t-file-upload__feedback\"\n aria-live=\"polite\"\n >\n <li\n v-for=\"message in feedbackMessages\"\n :key=\"message\"\n >\n {{ message }}\n </li>\n </ul>\n\n <div\n v-if=\"showFileList && hasFiles\"\n class=\"t-file-upload__files\"\n >\n <div class=\"t-file-upload__files-header\">\n <p\n :id=\"filesId\"\n class=\"t-file-upload__files-label\"\n >\n {{ selectedFilesLabel }}\n </p>\n\n <button\n class=\"t-file-upload__clear\"\n type=\"button\"\n :disabled=\"isUnavailable\"\n @click=\"clearFiles\"\n >\n Clear all\n </button>\n </div>\n\n <ul class=\"t-file-upload__list\">\n <li\n v-for=\"(file, index) in modelValue\"\n :key=\"fileKey(file, index)\"\n class=\"t-file-upload__file\"\n >\n <slot\n name=\"file\"\n :file=\"file\"\n :index=\"index\"\n :remove-file=\"() => removeFile(index)\"\n >\n <div class=\"t-file-upload__file-copy\">\n <p class=\"t-file-upload__file-name\">\n {{ file.name }}\n </p>\n <p class=\"t-file-upload__file-meta\">\n {{ formatFileSize(file.size) }}\n </p>\n </div>\n\n <button\n class=\"t-file-upload__remove\"\n type=\"button\"\n :disabled=\"isUnavailable\"\n :aria-label=\"`Remove ${file.name}`\"\n @click=\"removeFile(index)\"\n >\n Remove\n </button>\n </slot>\n </li>\n </ul>\n </div>\n\n <div\n v-if=\"$slots.actions\"\n class=\"t-file-upload__actions\"\n >\n <slot\n name=\"actions\"\n :files=\"modelValue\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { createId, getNextEnabledIndex, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TMultiSelectOption {\n label: string;\n value: string;\n description?: string;\n keywords?: string[];\n disabled?: boolean;\n}\n\nconst ChevronDownIcon = getTreeIcon('chevron-down');\nconst CheckIcon = getTreeIcon('check');\nconst XIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string[];\n options?: TMultiSelectOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n emptyText?: string;\n maxVisibleTags?: number;\n }>(),\n {\n modelValue: () => [],\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n emptyText: 'No results found.',\n maxVisibleTags: 2,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string[]];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n 'input-change': [value: string];\n}>();\n\ndefineSlots<{\n prefix?: () => unknown;\n tag?: (props: { option: TMultiSelectOption; remove: () => void }) => unknown;\n option?: (props: {\n option: TMultiSelectOption;\n selected: boolean;\n active: boolean;\n }) => unknown;\n empty?: (props: { query: string }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('t-multi-select');\nconst rootRef = ref<HTMLElement | null>(null);\nconst inputRef = ref<HTMLInputElement | null>(null);\nconst query = ref('');\nconst activeIndex = ref(-1);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, autocomplete, ...rest } = attrs;\n return {\n autocomplete: typeof autocomplete === 'string' ? autocomplete : 'off',\n ...rest,\n };\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-multi-select',\n `t-multi-select--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst normalize = (value: string) => value.trim().toLowerCase();\n\nconst filteredOptions = computed(() => {\n const normalizedQuery = normalize(query.value);\n\n if (!normalizedQuery) {\n return props.options;\n }\n\n return props.options.filter((option) => {\n const fields = [option.label, option.description ?? '', ...(option.keywords ?? [])];\n return fields.some((field) => field.toLowerCase().includes(normalizedQuery));\n });\n});\n\nconst selectedOptions = computed(() =>\n props.options.filter((option) => props.modelValue.includes(option.value)),\n);\n\nconst visibleTags = computed(() => selectedOptions.value.slice(0, props.maxVisibleTags));\nconst hiddenTagCount = computed(() =>\n Math.max(selectedOptions.value.length - visibleTags.value.length, 0),\n);\n\nconst enabledFilteredOptions = computed(() => filteredOptions.value.filter((option) => !option.disabled));\n\nconst activeOption = computed(() =>\n activeIndex.value >= 0 ? filteredOptions.value[activeIndex.value] : undefined,\n);\n\nconst activeDescendant = computed(() =>\n isOpen.value && activeOption.value\n ? `${listboxId}-option-${activeOption.value.value}`\n : undefined,\n);\n\nconst inputPlaceholder = computed(() =>\n props.modelValue.length === 0 && !query.value ? props.placeholder : '',\n);\n\nconst isSelected = (value: string) => props.modelValue.includes(value);\n\nconst setInitialActiveIndex = (fallback: 'first' | 'last' = 'first') => {\n const selectedIndex = filteredOptions.value.findIndex(\n (option) => isSelected(option.value) && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n activeIndex.value = selectedIndex;\n return;\n }\n\n if (enabledFilteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const targetOption =\n fallback === 'last'\n ? enabledFilteredOptions.value[enabledFilteredOptions.value.length - 1]\n : enabledFilteredOptions.value[0];\n\n activeIndex.value = filteredOptions.value.findIndex(\n (option) => option.value === targetOption.value,\n );\n};\n\nconst openListbox = (fallback: 'first' | 'last' = 'first') => {\n if (props.disabled) {\n return;\n }\n\n setValue(true);\n setInitialActiveIndex(fallback);\n};\n\nconst closeListbox = () => {\n setValue(false);\n activeIndex.value = -1;\n};\n\nconst focusInput = () => {\n nextTick(() => inputRef.value?.focus());\n};\n\nconst updateValues = (nextValues: string[]) => {\n emit('update:modelValue', nextValues);\n};\n\nconst toggleOption = (option: TMultiSelectOption) => {\n if (props.disabled || option.disabled) {\n return;\n }\n\n const nextValues = isSelected(option.value)\n ? props.modelValue.filter((value) => value !== option.value)\n : [...props.modelValue, option.value];\n\n updateValues(nextValues);\n query.value = '';\n setInitialActiveIndex('first');\n focusInput();\n};\n\nconst removeValue = (value: string) => {\n if (props.disabled) {\n return;\n }\n\n updateValues(props.modelValue.filter((item) => item !== value));\n focusInput();\n};\n\nconst moveActive = (direction: 1 | -1) => {\n if (filteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const nextIndex = getNextEnabledIndex(activeIndex.value, filteredOptions.value, direction);\n activeIndex.value = nextIndex;\n};\n\nconst onInput = (event: Event) => {\n query.value = (event.target as HTMLInputElement).value;\n emit('input-change', query.value);\n\n if (!props.disabled && !isOpen.value) {\n openListbox('first');\n return;\n }\n\n setInitialActiveIndex('first');\n};\n\nconst onInputFocus = () => {\n openListbox('first');\n};\n\nconst onInputKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Tab') {\n closeListbox();\n return;\n }\n\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeListbox();\n return;\n }\n\n if (event.key === 'Backspace' && !query.value && props.modelValue.length > 0) {\n event.preventDefault();\n removeValue(props.modelValue[props.modelValue.length - 1]);\n return;\n }\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('first');\n return;\n }\n\n moveActive(1);\n return;\n }\n\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('last');\n return;\n }\n\n moveActive(-1);\n return;\n }\n\n if (event.key === 'Home' && isOpen.value) {\n event.preventDefault();\n setInitialActiveIndex('first');\n return;\n }\n\n if (event.key === 'End' && isOpen.value) {\n event.preventDefault();\n setInitialActiveIndex('last');\n return;\n }\n\n if (event.key === 'Enter' && activeOption.value) {\n event.preventDefault();\n toggleOption(activeOption.value);\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeListbox();\n};\n\nwatch(\n isOpen,\n (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n },\n);\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <div\n class=\"t-multi-select__control\"\n @click=\"focusInput\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-multi-select__slot\"\n >\n <slot name=\"prefix\" />\n </span>\n\n <div class=\"t-multi-select__values\">\n <span\n v-for=\"option in visibleTags\"\n :key=\"option.value\"\n class=\"t-multi-select__tag\"\n >\n <slot\n name=\"tag\"\n :option=\"option\"\n :remove=\"() => removeValue(option.value)\"\n >\n <span class=\"t-multi-select__tag-label\">{{ option.label }}</span>\n <button\n type=\"button\"\n class=\"t-multi-select__tag-remove\"\n :disabled=\"disabled\"\n aria-label=\"Remove selection\"\n @mousedown.prevent\n @click.stop=\"removeValue(option.value)\"\n >\n <XIcon :size=\"12\" />\n </button>\n </slot>\n </span>\n\n <span\n v-if=\"hiddenTagCount > 0\"\n class=\"t-multi-select__overflow\"\n >\n +{{ hiddenTagCount }}\n </span>\n\n <input\n ref=\"inputRef\"\n v-bind=\"inputAttrs\"\n :value=\"query\"\n type=\"text\"\n class=\"t-multi-select__input\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n :aria-activedescendant=\"activeDescendant\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n :disabled=\"disabled\"\n :placeholder=\"inputPlaceholder\"\n @focus=\"onInputFocus\"\n @input=\"onInput\"\n @keydown=\"onInputKeydown\"\n >\n </div>\n\n <TSpinner\n v-if=\"loading\"\n class=\"t-multi-select__indicator\"\n size=\"sm\"\n />\n <ChevronDownIcon\n v-else\n class=\"t-multi-select__indicator\"\n :size=\"16\"\n />\n </div>\n\n <Transition name=\"t-fade\">\n <ul\n v-if=\"isOpen\"\n :id=\"listboxId\"\n class=\"t-multi-select__listbox\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n >\n <li\n v-if=\"filteredOptions.length === 0\"\n class=\"t-multi-select__empty\"\n >\n <slot\n name=\"empty\"\n :query=\"query\"\n >\n {{ emptyText }}\n </slot>\n </li>\n\n <template v-else>\n <li\n v-for=\"(option, index) in filteredOptions\"\n :key=\"option.value\"\n >\n <button\n :id=\"`${listboxId}-option-${option.value}`\"\n type=\"button\"\n class=\"t-multi-select__option\"\n :class=\"{\n 'is-active': index === activeIndex,\n 'is-selected': isSelected(option.value),\n 'is-disabled': option.disabled,\n }\"\n role=\"option\"\n :aria-selected=\"isSelected(option.value)\"\n :aria-disabled=\"option.disabled || undefined\"\n :disabled=\"option.disabled\"\n @mousedown.prevent\n @click=\"toggleOption(option)\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"isSelected(option.value)\"\n :active=\"index === activeIndex\"\n >\n <span class=\"t-multi-select__option-copy\">\n <span class=\"t-multi-select__option-label\">{{ option.label }}</span>\n <span\n v-if=\"option.description\"\n class=\"t-multi-select__option-description\"\n >\n {{ option.description }}\n </span>\n </span>\n\n <span\n class=\"t-multi-select__check\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"isSelected(option.value)\"\n :size=\"16\"\n />\n </span>\n </slot>\n </button>\n </li>\n </template>\n </ul>\n </Transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { createId, getNextEnabledIndex, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TMultiSelectOption {\n label: string;\n value: string;\n description?: string;\n keywords?: string[];\n disabled?: boolean;\n}\n\nconst ChevronDownIcon = getTreeIcon('chevron-down');\nconst CheckIcon = getTreeIcon('check');\nconst XIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string[];\n options?: TMultiSelectOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n emptyText?: string;\n maxVisibleTags?: number;\n }>(),\n {\n modelValue: () => [],\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n emptyText: 'No results found.',\n maxVisibleTags: 2,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string[]];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n 'input-change': [value: string];\n}>();\n\ndefineSlots<{\n prefix?: () => unknown;\n tag?: (props: { option: TMultiSelectOption; remove: () => void }) => unknown;\n option?: (props: {\n option: TMultiSelectOption;\n selected: boolean;\n active: boolean;\n }) => unknown;\n empty?: (props: { query: string }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('t-multi-select');\nconst rootRef = ref<HTMLElement | null>(null);\nconst inputRef = ref<HTMLInputElement | null>(null);\nconst query = ref('');\nconst activeIndex = ref(-1);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, autocomplete, ...rest } = attrs;\n return {\n autocomplete: typeof autocomplete === 'string' ? autocomplete : 'off',\n ...rest,\n };\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-multi-select',\n `t-multi-select--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst normalize = (value: string) => value.trim().toLowerCase();\n\nconst filteredOptions = computed(() => {\n const normalizedQuery = normalize(query.value);\n\n if (!normalizedQuery) {\n return props.options;\n }\n\n return props.options.filter((option) => {\n const fields = [option.label, option.description ?? '', ...(option.keywords ?? [])];\n return fields.some((field) => field.toLowerCase().includes(normalizedQuery));\n });\n});\n\nconst selectedOptions = computed(() =>\n props.options.filter((option) => props.modelValue.includes(option.value)),\n);\n\nconst visibleTags = computed(() => selectedOptions.value.slice(0, props.maxVisibleTags));\nconst hiddenTagCount = computed(() =>\n Math.max(selectedOptions.value.length - visibleTags.value.length, 0),\n);\n\nconst enabledFilteredOptions = computed(() => filteredOptions.value.filter((option) => !option.disabled));\n\nconst activeOption = computed(() =>\n activeIndex.value >= 0 ? filteredOptions.value[activeIndex.value] : undefined,\n);\n\nconst activeDescendant = computed(() =>\n isOpen.value && activeOption.value\n ? `${listboxId}-option-${activeOption.value.value}`\n : undefined,\n);\n\nconst inputPlaceholder = computed(() =>\n props.modelValue.length === 0 && !query.value ? props.placeholder : '',\n);\n\nconst isSelected = (value: string) => props.modelValue.includes(value);\n\nconst setInitialActiveIndex = (fallback: 'first' | 'last' = 'first') => {\n const selectedIndex = filteredOptions.value.findIndex(\n (option) => isSelected(option.value) && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n activeIndex.value = selectedIndex;\n return;\n }\n\n if (enabledFilteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const targetOption =\n fallback === 'last'\n ? enabledFilteredOptions.value[enabledFilteredOptions.value.length - 1]\n : enabledFilteredOptions.value[0];\n\n activeIndex.value = filteredOptions.value.findIndex(\n (option) => option.value === targetOption.value,\n );\n};\n\nconst openListbox = (fallback: 'first' | 'last' = 'first') => {\n if (props.disabled) {\n return;\n }\n\n setValue(true);\n setInitialActiveIndex(fallback);\n};\n\nconst closeListbox = () => {\n setValue(false);\n activeIndex.value = -1;\n};\n\nconst focusInput = () => {\n nextTick(() => inputRef.value?.focus());\n};\n\nconst updateValues = (nextValues: string[]) => {\n emit('update:modelValue', nextValues);\n};\n\nconst toggleOption = (option: TMultiSelectOption) => {\n if (props.disabled || option.disabled) {\n return;\n }\n\n const nextValues = isSelected(option.value)\n ? props.modelValue.filter((value) => value !== option.value)\n : [...props.modelValue, option.value];\n\n updateValues(nextValues);\n query.value = '';\n setInitialActiveIndex('first');\n focusInput();\n};\n\nconst removeValue = (value: string) => {\n if (props.disabled) {\n return;\n }\n\n updateValues(props.modelValue.filter((item) => item !== value));\n focusInput();\n};\n\nconst moveActive = (direction: 1 | -1) => {\n if (filteredOptions.value.length === 0) {\n activeIndex.value = -1;\n return;\n }\n\n const nextIndex = getNextEnabledIndex(activeIndex.value, filteredOptions.value, direction);\n activeIndex.value = nextIndex;\n};\n\nconst onInput = (event: Event) => {\n query.value = (event.target as HTMLInputElement).value;\n emit('input-change', query.value);\n\n if (!props.disabled && !isOpen.value) {\n openListbox('first');\n return;\n }\n\n setInitialActiveIndex('first');\n};\n\nconst onInputFocus = () => {\n openListbox('first');\n};\n\nconst onInputKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Tab') {\n closeListbox();\n return;\n }\n\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeListbox();\n return;\n }\n\n if (event.key === 'Backspace' && !query.value && props.modelValue.length > 0) {\n event.preventDefault();\n removeValue(props.modelValue[props.modelValue.length - 1]);\n return;\n }\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('first');\n return;\n }\n\n moveActive(1);\n return;\n }\n\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n\n if (!isOpen.value) {\n openListbox('last');\n return;\n }\n\n moveActive(-1);\n return;\n }\n\n if (event.key === 'Home' && isOpen.value) {\n event.preventDefault();\n setInitialActiveIndex('first');\n return;\n }\n\n if (event.key === 'End' && isOpen.value) {\n event.preventDefault();\n setInitialActiveIndex('last');\n return;\n }\n\n if (event.key === 'Enter' && activeOption.value) {\n event.preventDefault();\n toggleOption(activeOption.value);\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) {\n return;\n }\n\n const target = event.target;\n\n if (!(target instanceof Node)) {\n return;\n }\n\n if (rootRef.value?.contains(target)) {\n return;\n }\n\n closeListbox();\n};\n\nwatch(\n isOpen,\n (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n },\n);\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <div\n class=\"t-multi-select__control\"\n @click=\"focusInput\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-multi-select__slot\"\n >\n <slot name=\"prefix\" />\n </span>\n\n <div class=\"t-multi-select__values\">\n <span\n v-for=\"option in visibleTags\"\n :key=\"option.value\"\n class=\"t-multi-select__tag\"\n >\n <slot\n name=\"tag\"\n :option=\"option\"\n :remove=\"() => removeValue(option.value)\"\n >\n <span class=\"t-multi-select__tag-label\">{{ option.label }}</span>\n <button\n type=\"button\"\n class=\"t-multi-select__tag-remove\"\n :disabled=\"disabled\"\n aria-label=\"Remove selection\"\n @mousedown.prevent\n @click.stop=\"removeValue(option.value)\"\n >\n <XIcon :size=\"12\" />\n </button>\n </slot>\n </span>\n\n <span\n v-if=\"hiddenTagCount > 0\"\n class=\"t-multi-select__overflow\"\n >\n +{{ hiddenTagCount }}\n </span>\n\n <input\n ref=\"inputRef\"\n v-bind=\"inputAttrs\"\n :value=\"query\"\n type=\"text\"\n class=\"t-multi-select__input\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n :aria-activedescendant=\"activeDescendant\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n :disabled=\"disabled\"\n :placeholder=\"inputPlaceholder\"\n @focus=\"onInputFocus\"\n @input=\"onInput\"\n @keydown=\"onInputKeydown\"\n >\n </div>\n\n <TSpinner\n v-if=\"loading\"\n class=\"t-multi-select__indicator\"\n size=\"sm\"\n />\n <ChevronDownIcon\n v-else\n class=\"t-multi-select__indicator\"\n :size=\"16\"\n />\n </div>\n\n <Transition name=\"t-fade\">\n <ul\n v-if=\"isOpen\"\n :id=\"listboxId\"\n class=\"t-multi-select__listbox\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n >\n <li\n v-if=\"filteredOptions.length === 0\"\n class=\"t-multi-select__empty\"\n >\n <slot\n name=\"empty\"\n :query=\"query\"\n >\n {{ emptyText }}\n </slot>\n </li>\n\n <template v-else>\n <li\n v-for=\"(option, index) in filteredOptions\"\n :key=\"option.value\"\n >\n <button\n :id=\"`${listboxId}-option-${option.value}`\"\n type=\"button\"\n class=\"t-multi-select__option\"\n :class=\"{\n 'is-active': index === activeIndex,\n 'is-selected': isSelected(option.value),\n 'is-disabled': option.disabled,\n }\"\n role=\"option\"\n :aria-selected=\"isSelected(option.value)\"\n :aria-disabled=\"option.disabled || undefined\"\n :disabled=\"option.disabled\"\n @mousedown.prevent\n @click=\"toggleOption(option)\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"isSelected(option.value)\"\n :active=\"index === activeIndex\"\n >\n <span class=\"t-multi-select__option-copy\">\n <span class=\"t-multi-select__option-label\">{{ option.label }}</span>\n <span\n v-if=\"option.description\"\n class=\"t-multi-select__option-description\"\n >\n {{ option.description }}\n </span>\n </span>\n\n <span\n class=\"t-multi-select__check\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"isSelected(option.value)\"\n :size=\"16\"\n />\n </span>\n </slot>\n </button>\n </li>\n </template>\n </ul>\n </Transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n columns?: number;\n minItemWidth?: string;\n gap?: string;\n rowGap?: string;\n align?: string;\n justify?: string;\n dense?: boolean;\n }>(),\n {\n as: 'div',\n columns: undefined,\n minItemWidth: '16rem',\n gap: 'var(--tree-space-4)',\n rowGap: undefined,\n align: 'stretch',\n justify: 'stretch',\n dense: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-grid',\n {\n 'is-dense': props.dense,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n gap: props.gap,\n rowGap: props.rowGap ?? props.gap,\n alignItems: props.align,\n justifyItems: props.justify,\n gridTemplateColumns:\n typeof props.columns === 'number' && props.columns > 0\n ? `repeat(${props.columns}, minmax(0, 1fr))`\n : `repeat(auto-fit, minmax(min(${props.minItemWidth}, 100%), 1fr))`,\n gridAutoFlow: props.dense ? 'dense' : 'row',\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n columns?: number;\n minItemWidth?: string;\n gap?: string;\n rowGap?: string;\n align?: string;\n justify?: string;\n dense?: boolean;\n }>(),\n {\n as: 'div',\n columns: undefined,\n minItemWidth: '16rem',\n gap: 'var(--tree-space-4)',\n rowGap: undefined,\n align: 'stretch',\n justify: 'stretch',\n dense: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-grid',\n {\n 'is-dense': props.dense,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n gap: props.gap,\n rowGap: props.rowGap ?? props.gap,\n alignItems: props.align,\n justifyItems: props.justify,\n gridTemplateColumns:\n typeof props.columns === 'number' && props.columns > 0\n ? `repeat(${props.columns}, minmax(0, 1fr))`\n : `repeat(auto-fit, minmax(min(${props.minItemWidth}, 100%), 1fr))`,\n gridAutoFlow: props.dense ? 'dense' : 'row',\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TSize;\n sticky?: boolean;\n bordered?: boolean;\n elevated?: boolean;\n }>(),\n {\n as: 'header',\n size: 'md',\n sticky: false,\n bordered: true,\n elevated: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-navbar',\n `t-navbar--${props.size}`,\n {\n 'is-sticky': props.sticky,\n 'is-bordered': props.bordered,\n 'is-elevated': props.elevated,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <div class=\"t-navbar__inner\">\n <div\n v-if=\"$slots.start\"\n class=\"t-navbar__section t-navbar__section--start\"\n >\n <slot name=\"start\" />\n </div>\n\n <div\n v-if=\"$slots.default || $slots.center\"\n class=\"t-navbar__section t-navbar__section--center\"\n >\n <slot name=\"center\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.end\"\n class=\"t-navbar__section t-navbar__section--end\"\n >\n <slot name=\"end\" />\n </div>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n size?: TSize;\n sticky?: boolean;\n bordered?: boolean;\n elevated?: boolean;\n }>(),\n {\n as: 'header',\n size: 'md',\n sticky: false,\n bordered: true,\n elevated: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-navbar',\n `t-navbar--${props.size}`,\n {\n 'is-sticky': props.sticky,\n 'is-bordered': props.bordered,\n 'is-elevated': props.elevated,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <div class=\"t-navbar__inner\">\n <div\n v-if=\"$slots.start\"\n class=\"t-navbar__section t-navbar__section--start\"\n >\n <slot name=\"start\" />\n </div>\n\n <div\n v-if=\"$slots.default || $slots.center\"\n class=\"t-navbar__section t-navbar__section--center\"\n >\n <slot name=\"center\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.end\"\n class=\"t-navbar__section t-navbar__section--end\"\n >\n <slot name=\"end\" />\n </div>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, type Component } from 'vue';\n\nexport type TLinkVariant = 'default' | 'muted' | 'danger';\n\nconst props = withDefaults(\n defineProps<{\n to?: string | Record<string, unknown>;\n href?: string;\n external?: boolean;\n disabled?: boolean;\n variant?: TLinkVariant;\n }>(),\n {\n to: undefined,\n href: undefined,\n external: false,\n disabled: false,\n variant: 'default',\n },\n);\n\nconst instance = getCurrentInstance();\n\nconst routerLinkComponent = computed<Component | null>(() => {\n if (!props.to) return null;\n\n return (instance?.appContext.components.RouterLink as Component | undefined) ?? null;\n});\n\nconst hasRouterLink = computed(() => {\n return Boolean(routerLinkComponent.value);\n});\n\nconst tag = computed<string | Component>(() => {\n if (props.disabled) return 'span';\n if (props.to && routerLinkComponent.value) return routerLinkComponent.value;\n return 'a';\n});\n\nconst linkProps = computed(() => {\n if (props.disabled) return {};\n if (props.to && hasRouterLink.value) return { to: props.to };\n const href = props.href ?? (typeof props.to === 'string' ? props.to : undefined);\n return {\n href,\n ...(props.external ? { target: '_blank', rel: 'noopener noreferrer' } : {}),\n };\n});\n\nconst classes = computed(() => [\n 't-link',\n `t-link--${props.variant}`,\n {\n 'is-disabled': props.disabled,\n },\n]);\n</script>\n\n<template>\n <component\n :is=\"tag\"\n v-bind=\"linkProps\"\n :class=\"classes\"\n :aria-disabled=\"disabled || undefined\"\n :tabindex=\"disabled ? -1 : undefined\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, type Component } from 'vue';\n\nexport type TLinkVariant = 'default' | 'muted' | 'danger';\n\nconst props = withDefaults(\n defineProps<{\n to?: string | Record<string, unknown>;\n href?: string;\n external?: boolean;\n disabled?: boolean;\n variant?: TLinkVariant;\n }>(),\n {\n to: undefined,\n href: undefined,\n external: false,\n disabled: false,\n variant: 'default',\n },\n);\n\nconst instance = getCurrentInstance();\n\nconst routerLinkComponent = computed<Component | null>(() => {\n if (!props.to) return null;\n\n return (instance?.appContext.components.RouterLink as Component | undefined) ?? null;\n});\n\nconst hasRouterLink = computed(() => {\n return Boolean(routerLinkComponent.value);\n});\n\nconst tag = computed<string | Component>(() => {\n if (props.disabled) return 'span';\n if (props.to && routerLinkComponent.value) return routerLinkComponent.value;\n return 'a';\n});\n\nconst linkProps = computed(() => {\n if (props.disabled) return {};\n if (props.to && hasRouterLink.value) return { to: props.to };\n const href = props.href ?? (typeof props.to === 'string' ? props.to : undefined);\n return {\n href,\n ...(props.external ? { target: '_blank', rel: 'noopener noreferrer' } : {}),\n };\n});\n\nconst classes = computed(() => [\n 't-link',\n `t-link--${props.variant}`,\n {\n 'is-disabled': props.disabled,\n },\n]);\n</script>\n\n<template>\n <component\n :is=\"tag\"\n v-bind=\"linkProps\"\n :class=\"classes\"\n :aria-disabled=\"disabled || undefined\"\n :tabindex=\"disabled ? -1 : undefined\"\n >\n <slot />\n </component>\n</template>\n","import type { ComputedRef, InjectionKey } from 'vue';\n\nexport interface TSidebarContext {\n collapsed: ComputedRef<boolean>;\n}\n\nexport const treeSidebarInjectionKey: InjectionKey<TSidebarContext> =\n Symbol('tree-sidebar');\n","<script setup lang=\"ts\">\nimport { getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, getCurrentInstance, inject, nextTick, ref, useAttrs, watch, type Component, type ComponentPublicInstance } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TNavMenuItem {\n label: string;\n value: string;\n shortLabel?: string;\n description?: string;\n icon?: Component;\n to?: string | Record<string, unknown>;\n badge?: string | number;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TNavMenuItem[];\n size?: TSize;\n collapsed?: boolean;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n collapsed: undefined,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n select: [value: string, item: TNavMenuItem];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TNavMenuItem;\n selected: boolean;\n focused: boolean;\n collapsed: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst sidebar = inject(treeSidebarInjectionKey, null);\nconst internalValue = ref(props.defaultValue);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst instance = getCurrentInstance();\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\nconst resolvedCollapsed = computed(() => props.collapsed ?? sidebar?.collapsed.value ?? false);\n\nconst routerLinkComponent = computed<Component | null>(() => (\n (instance?.appContext.components.RouterLink as Component | undefined) ?? null\n));\n\nconst itemTag = (item: TNavMenuItem) => {\n if (item.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n return 'button';\n};\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 't-nav-menu',\n `t-nav-menu--${props.size}`,\n {\n 'is-collapsed': resolvedCollapsed.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TNavMenuItem) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n emit('select', item.value, item);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n focusItem(firstIndex);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n focusItem(props.items.length - 1 - lastIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n focusItem(nextIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n focusItem(previousIndex);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index]);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <nav\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"items.length > 0\"\n class=\"t-nav-menu__list\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"t-nav-menu__entry\"\n >\n <component\n :is=\"itemTag(item)\"\n :ref=\"(element: Element | ComponentPublicInstance | null) => setItemRef(element, item.value)\"\n :type=\"item.to ? undefined : 'button'\"\n :to=\"item.to || undefined\"\n class=\"t-nav-menu__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n :disabled=\"(!item.to && (disabled || item.disabled)) || undefined\"\n :aria-disabled=\"(item.to && (disabled || item.disabled)) || undefined\"\n :aria-current=\"isSelected(item.value) ? 'page' : undefined\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :title=\"resolvedCollapsed ? item.label : undefined\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n :collapsed=\"resolvedCollapsed\"\n >\n <component\n :is=\"item.icon\"\n v-if=\"item.icon\"\n class=\"t-nav-menu__icon\"\n aria-hidden=\"true\"\n />\n <span\n v-else\n class=\"t-nav-menu__marker\"\n aria-hidden=\"true\"\n >\n {{ (item.shortLabel ?? item.label.charAt(0)).toUpperCase() }}\n </span>\n\n <span class=\"t-nav-menu__copy\">\n <span class=\"t-nav-menu__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"t-nav-menu__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.badge !== undefined && item.badge !== null\"\n class=\"t-nav-menu__badge\"\n >\n {{ item.badge }}\n </span>\n </slot>\n </component>\n </li>\n </ul>\n\n <div\n v-else\n class=\"t-nav-menu__empty\"\n >\n <slot name=\"empty\">\n No navigation items.\n </slot>\n </div>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, getCurrentInstance, inject, nextTick, ref, useAttrs, watch, type Component, type ComponentPublicInstance } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TNavMenuItem {\n label: string;\n value: string;\n shortLabel?: string;\n description?: string;\n icon?: Component;\n to?: string | Record<string, unknown>;\n badge?: string | number;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TNavMenuItem[];\n size?: TSize;\n collapsed?: boolean;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n collapsed: undefined,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n select: [value: string, item: TNavMenuItem];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TNavMenuItem;\n selected: boolean;\n focused: boolean;\n collapsed: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst sidebar = inject(treeSidebarInjectionKey, null);\nconst internalValue = ref(props.defaultValue);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst instance = getCurrentInstance();\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\nconst resolvedCollapsed = computed(() => props.collapsed ?? sidebar?.collapsed.value ?? false);\n\nconst routerLinkComponent = computed<Component | null>(() => (\n (instance?.appContext.components.RouterLink as Component | undefined) ?? null\n));\n\nconst itemTag = (item: TNavMenuItem) => {\n if (item.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n return 'button';\n};\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 't-nav-menu',\n `t-nav-menu--${props.size}`,\n {\n 'is-collapsed': resolvedCollapsed.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TNavMenuItem) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n emit('select', item.value, item);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n focusItem(firstIndex);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n focusItem(props.items.length - 1 - lastIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n focusItem(nextIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n focusItem(previousIndex);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index]);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <nav\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"items.length > 0\"\n class=\"t-nav-menu__list\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"t-nav-menu__entry\"\n >\n <component\n :is=\"itemTag(item)\"\n :ref=\"(element: Element | ComponentPublicInstance | null) => setItemRef(element, item.value)\"\n :type=\"item.to ? undefined : 'button'\"\n :to=\"item.to || undefined\"\n class=\"t-nav-menu__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n :disabled=\"(!item.to && (disabled || item.disabled)) || undefined\"\n :aria-disabled=\"(item.to && (disabled || item.disabled)) || undefined\"\n :aria-current=\"isSelected(item.value) ? 'page' : undefined\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :title=\"resolvedCollapsed ? item.label : undefined\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n :collapsed=\"resolvedCollapsed\"\n >\n <component\n :is=\"item.icon\"\n v-if=\"item.icon\"\n class=\"t-nav-menu__icon\"\n aria-hidden=\"true\"\n />\n <span\n v-else\n class=\"t-nav-menu__marker\"\n aria-hidden=\"true\"\n >\n {{ (item.shortLabel ?? item.label.charAt(0)).toUpperCase() }}\n </span>\n\n <span class=\"t-nav-menu__copy\">\n <span class=\"t-nav-menu__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"t-nav-menu__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.badge !== undefined && item.badge !== null\"\n class=\"t-nav-menu__badge\"\n >\n {{ item.badge }}\n </span>\n </slot>\n </component>\n </li>\n </ul>\n\n <div\n v-else\n class=\"t-nav-menu__empty\"\n >\n <slot name=\"empty\">\n No navigation items.\n </slot>\n </div>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n invalid?: boolean;\n size?: TSize;\n }>(),\n {\n disabled: false,\n invalid: false,\n size: undefined,\n },\n);\n\nconst group = inject<{\n modelValue: () => string | undefined;\n name: () => string | undefined;\n disabled: () => boolean;\n invalid: () => boolean;\n size: () => TSize;\n onChange: (value: string) => void;\n} | null>('t-radio-group', null);\n\nconst attrs = useAttrs();\n\nconst isChecked = computed(() => {\n return group ? group.modelValue() === props.value : false;\n});\n\nconst isDisabled = computed(() => props.disabled || (group?.disabled() ?? false));\nconst isInvalid = computed(() => props.invalid || (group?.invalid() ?? false));\nconst resolvedSize = computed(() => props.size ?? group?.size() ?? 'md');\n\nconst rootClasses = computed(() => [\n 't-radio',\n `t-radio--${resolvedSize.value}`,\n {\n 'is-checked': isChecked.value,\n 'is-disabled': isDisabled.value,\n 'is-invalid': isInvalid.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n if (group) {\n group.onChange(props.value);\n }\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n v-bind=\"inputAttrs\"\n type=\"radio\"\n class=\"t-radio__input\"\n :value=\"value\"\n :checked=\"isChecked\"\n :disabled=\"isDisabled\"\n :name=\"group?.name()\"\n :aria-checked=\"isChecked\"\n :aria-invalid=\"isInvalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"t-radio__control\"\n aria-hidden=\"true\"\n >\n <span\n v-if=\"isChecked\"\n class=\"t-radio__dot\"\n />\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"t-radio__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n invalid?: boolean;\n size?: TSize;\n }>(),\n {\n disabled: false,\n invalid: false,\n size: undefined,\n },\n);\n\nconst group = inject<{\n modelValue: () => string | undefined;\n name: () => string | undefined;\n disabled: () => boolean;\n invalid: () => boolean;\n size: () => TSize;\n onChange: (value: string) => void;\n} | null>('t-radio-group', null);\n\nconst attrs = useAttrs();\n\nconst isChecked = computed(() => {\n return group ? group.modelValue() === props.value : false;\n});\n\nconst isDisabled = computed(() => props.disabled || (group?.disabled() ?? false));\nconst isInvalid = computed(() => props.invalid || (group?.invalid() ?? false));\nconst resolvedSize = computed(() => props.size ?? group?.size() ?? 'md');\n\nconst rootClasses = computed(() => [\n 't-radio',\n `t-radio--${resolvedSize.value}`,\n {\n 'is-checked': isChecked.value,\n 'is-disabled': isDisabled.value,\n 'is-invalid': isInvalid.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n if (group) {\n group.onChange(props.value);\n }\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n v-bind=\"inputAttrs\"\n type=\"radio\"\n class=\"t-radio__input\"\n :value=\"value\"\n :checked=\"isChecked\"\n :disabled=\"isDisabled\"\n :name=\"group?.name()\"\n :aria-checked=\"isChecked\"\n :aria-invalid=\"isInvalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"t-radio__control\"\n aria-hidden=\"true\"\n >\n <span\n v-if=\"isChecked\"\n class=\"t-radio__dot\"\n />\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"t-radio__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, provide, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n name?: string;\n disabled?: boolean;\n invalid?: boolean;\n size?: TSize;\n }>(),\n {\n modelValue: undefined,\n name: undefined,\n disabled: false,\n invalid: false,\n size: 'md',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nprovide('t-radio-group', {\n modelValue: () => props.modelValue,\n name: () => props.name,\n disabled: () => props.disabled,\n invalid: () => props.invalid,\n size: () => props.size,\n onChange: (value: string) => {\n emit('update:modelValue', value);\n },\n});\n\nconst rootClasses = computed(() => [\n 't-radio-group',\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst groupAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <div\n v-bind=\"groupAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n role=\"radiogroup\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, provide, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n name?: string;\n disabled?: boolean;\n invalid?: boolean;\n size?: TSize;\n }>(),\n {\n modelValue: undefined,\n name: undefined,\n disabled: false,\n invalid: false,\n size: 'md',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nprovide('t-radio-group', {\n modelValue: () => props.modelValue,\n name: () => props.name,\n disabled: () => props.disabled,\n invalid: () => props.invalid,\n size: () => props.size,\n onChange: (value: string) => {\n emit('update:modelValue', value);\n },\n});\n\nconst rootClasses = computed(() => [\n 't-radio-group',\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst groupAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <div\n v-bind=\"groupAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n role=\"radiogroup\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TSelectOption {\n label: string;\n value: string | number;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n options?: TSelectOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('t-select');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst optionRefs = ref<Map<string | number, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-select',\n `t-select--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst selectedLabel = computed(() => {\n const opt = props.options.find((o) => o.value === props.modelValue);\n return opt?.label ?? '';\n});\n\nconst enabledOptions = computed(() =>\n props.options.filter((o) => !o.disabled),\n);\n\nconst openDropdown = () => {\n if (props.disabled) return;\n const selectedIdx = props.options.findIndex((o) => o.value === props.modelValue);\n focusedIndex.value = selectedIdx >= 0 ? selectedIdx : 0;\n setValue(true);\n nextTick(() => focusOption(focusedIndex.value));\n};\n\nconst closeDropdown = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst toggleDropdown = () => {\n if (isOpen.value) {\n closeDropdown();\n } else {\n openDropdown();\n }\n};\n\nconst selectOption = (opt: TSelectOption) => {\n if (opt.disabled) return;\n emit('update:modelValue', opt.value);\n closeDropdown(true);\n};\n\nconst focusOption = (index: number) => {\n const opt = props.options[index];\n if (!opt) return;\n const el = optionRefs.value.get(opt.value);\n el?.focus();\n};\n\nconst setOptionRef = (el: Element | null, value: string | number) => {\n if (el instanceof HTMLElement) {\n optionRefs.value.set(value, el);\n } else {\n optionRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.options.length) {\n if (!props.options[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusOption(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeDropdown();\n return;\n }\n\n if (isActivationKey(event) || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n openDropdown();\n }\n};\n\nconst onOptionKeydown = (event: KeyboardEvent, opt: TSelectOption, _index: number) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeDropdown(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectOption(opt);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledOptions.value.length > 0\n ? props.options.indexOf(enabledOptions.value[0])\n : 0;\n focusOption(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledOptions.value.length > 0\n ? props.options.indexOf(enabledOptions.value[enabledOptions.value.length - 1])\n : props.options.length - 1;\n focusOption(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeDropdown();\n};\n\nconst hasSelection = computed(() =>\n props.modelValue !== '' && props.modelValue !== null && props.modelValue !== undefined,\n);\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"t-select__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n aria-haspopup=\"listbox\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n @click=\"toggleDropdown\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-select__slot t-select__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <span\n class=\"t-select__value\"\n :data-placeholder=\"!hasSelection ? true : undefined\"\n >\n {{ selectedLabel || placeholder }}\n </span>\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <svg\n v-else\n class=\"t-select__chevron\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </button>\n <transition name=\"t-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"listboxId\"\n role=\"listbox\"\n class=\"t-select__listbox\"\n :aria-label=\"typeof triggerAttrs['aria-label'] === 'string' ? triggerAttrs['aria-label'] : undefined\"\n >\n <li\n v-for=\"(opt, index) in options\"\n :key=\"opt.value\"\n :ref=\"(el) => setOptionRef(el as Element | null, opt.value)\"\n role=\"option\"\n class=\"t-select__option\"\n :class=\"{\n 'is-selected': opt.value === modelValue,\n 'is-disabled': opt.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-selected=\"opt.value === modelValue\"\n :aria-disabled=\"opt.disabled || undefined\"\n :tabindex=\"opt.disabled ? -1 : 0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt, index)\"\n >\n {{ opt.label }}\n <svg\n v-if=\"opt.value === modelValue\"\n class=\"t-select__check\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n </li>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TSelectOption {\n label: string;\n value: string | number;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n options?: TSelectOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | number];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('t-select');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst optionRefs = ref<Map<string | number, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-select',\n `t-select--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst selectedLabel = computed(() => {\n const opt = props.options.find((o) => o.value === props.modelValue);\n return opt?.label ?? '';\n});\n\nconst enabledOptions = computed(() =>\n props.options.filter((o) => !o.disabled),\n);\n\nconst openDropdown = () => {\n if (props.disabled) return;\n const selectedIdx = props.options.findIndex((o) => o.value === props.modelValue);\n focusedIndex.value = selectedIdx >= 0 ? selectedIdx : 0;\n setValue(true);\n nextTick(() => focusOption(focusedIndex.value));\n};\n\nconst closeDropdown = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst toggleDropdown = () => {\n if (isOpen.value) {\n closeDropdown();\n } else {\n openDropdown();\n }\n};\n\nconst selectOption = (opt: TSelectOption) => {\n if (opt.disabled) return;\n emit('update:modelValue', opt.value);\n closeDropdown(true);\n};\n\nconst focusOption = (index: number) => {\n const opt = props.options[index];\n if (!opt) return;\n const el = optionRefs.value.get(opt.value);\n el?.focus();\n};\n\nconst setOptionRef = (el: Element | null, value: string | number) => {\n if (el instanceof HTMLElement) {\n optionRefs.value.set(value, el);\n } else {\n optionRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.options.length) {\n if (!props.options[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusOption(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeDropdown();\n return;\n }\n\n if (isActivationKey(event) || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n openDropdown();\n }\n};\n\nconst onOptionKeydown = (event: KeyboardEvent, opt: TSelectOption, _index: number) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeDropdown(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectOption(opt);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledOptions.value.length > 0\n ? props.options.indexOf(enabledOptions.value[0])\n : 0;\n focusOption(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledOptions.value.length > 0\n ? props.options.indexOf(enabledOptions.value[enabledOptions.value.length - 1])\n : props.options.length - 1;\n focusOption(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeDropdown();\n};\n\nconst hasSelection = computed(() =>\n props.modelValue !== '' && props.modelValue !== null && props.modelValue !== undefined,\n);\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"t-select__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n aria-haspopup=\"listbox\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n @click=\"toggleDropdown\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-select__slot t-select__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <span\n class=\"t-select__value\"\n :data-placeholder=\"!hasSelection ? true : undefined\"\n >\n {{ selectedLabel || placeholder }}\n </span>\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <svg\n v-else\n class=\"t-select__chevron\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </button>\n <transition name=\"t-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"listboxId\"\n role=\"listbox\"\n class=\"t-select__listbox\"\n :aria-label=\"typeof triggerAttrs['aria-label'] === 'string' ? triggerAttrs['aria-label'] : undefined\"\n >\n <li\n v-for=\"(opt, index) in options\"\n :key=\"opt.value\"\n :ref=\"(el) => setOptionRef(el as Element | null, opt.value)\"\n role=\"option\"\n class=\"t-select__option\"\n :class=\"{\n 'is-selected': opt.value === modelValue,\n 'is-disabled': opt.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-selected=\"opt.value === modelValue\"\n :aria-disabled=\"opt.disabled || undefined\"\n :tabindex=\"opt.disabled ? -1 : 0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt, index)\"\n >\n {{ opt.label }}\n <svg\n v-if=\"opt.value === modelValue\"\n class=\"t-select__check\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n </li>\n </ul>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { computed, provide, toRef, useAttrs } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeSidebarSides = ['left', 'right'] as const;\n\nexport type TSidebarSide = (typeof _treeSidebarSides)[number];\n\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n collapsed?: boolean;\n defaultCollapsed?: boolean;\n collapsible?: boolean;\n size?: TSize;\n side?: TSidebarSide;\n sticky?: boolean;\n bordered?: boolean;\n width?: string;\n collapsedWidth?: string;\n collapseLabel?: string;\n expandLabel?: string;\n }>(),\n {\n as: 'aside',\n collapsed: undefined,\n defaultCollapsed: false,\n collapsible: true,\n size: 'md',\n side: 'left',\n sticky: false,\n bordered: true,\n width: '17.5rem',\n collapsedWidth: '4.75rem',\n collapseLabel: 'Collapse sidebar',\n expandLabel: 'Expand sidebar',\n },\n);\n\nconst emit = defineEmits<{\n 'update:collapsed': [value: boolean];\n 'collapse-change': [value: boolean];\n}>();\n\ndefineSlots<{\n header?: (props: { collapsed: boolean }) => unknown;\n default?: (props: { collapsed: boolean }) => unknown;\n footer?: (props: { collapsed: boolean }) => unknown;\n toggle?: (props: { collapsed: boolean }) => unknown;\n}>();\n\nconst attrs = useAttrs();\n\nconst { value: isCollapsed, setValue } = useControllableOpen(\n toRef(props, 'collapsed'),\n props.defaultCollapsed,\n (value) => {\n emit('update:collapsed', value);\n emit('collapse-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-sidebar',\n `t-sidebar--${props.size}`,\n `t-sidebar--${props.side}`,\n {\n 'is-collapsed': isCollapsed.value,\n 'is-sticky': props.sticky,\n 'is-bordered': props.bordered,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n '--tree-sidebar-width': props.width,\n '--tree-sidebar-collapsed-width': props.collapsedWidth,\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst toggleCollapsed = () => {\n if (!props.collapsible) {\n return;\n }\n\n setValue(!isCollapsed.value);\n};\n\nconst ToggleIcon = computed(() => {\n if (props.side === 'right') {\n return isCollapsed.value ? ChevronLeftIcon : ChevronRightIcon;\n }\n\n return isCollapsed.value ? ChevronRightIcon : ChevronLeftIcon;\n});\n\nconst toggleLabel = computed(() =>\n isCollapsed.value ? props.expandLabel : props.collapseLabel,\n);\n\nprovide(treeSidebarInjectionKey, {\n collapsed: computed(() => isCollapsed.value),\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isCollapsed ? 'collapsed' : 'expanded'\"\n >\n <div\n v-if=\"$slots.header\"\n class=\"t-sidebar__header\"\n >\n <slot\n name=\"header\"\n :collapsed=\"isCollapsed\"\n />\n </div>\n\n <div class=\"t-sidebar__body\">\n <slot :collapsed=\"isCollapsed\" />\n </div>\n\n <div\n v-if=\"$slots.footer || collapsible\"\n class=\"t-sidebar__footer\"\n >\n <slot\n v-if=\"$slots.footer\"\n name=\"footer\"\n :collapsed=\"isCollapsed\"\n />\n\n <button\n v-if=\"collapsible\"\n type=\"button\"\n class=\"t-sidebar__toggle\"\n :aria-label=\"toggleLabel\"\n :aria-expanded=\"!isCollapsed\"\n @click=\"toggleCollapsed\"\n >\n <slot\n name=\"toggle\"\n :collapsed=\"isCollapsed\"\n >\n <component\n :is=\"ToggleIcon\"\n :size=\"16\"\n />\n <span v-if=\"!isCollapsed\">{{ toggleLabel }}</span>\n </slot>\n </button>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { computed, provide, toRef, useAttrs } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeSidebarSides = ['left', 'right'] as const;\n\nexport type TSidebarSide = (typeof _treeSidebarSides)[number];\n\nconst ChevronLeftIcon = getTreeIcon('chevron-left');\nconst ChevronRightIcon = getTreeIcon('chevron-right');\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n collapsed?: boolean;\n defaultCollapsed?: boolean;\n collapsible?: boolean;\n size?: TSize;\n side?: TSidebarSide;\n sticky?: boolean;\n bordered?: boolean;\n width?: string;\n collapsedWidth?: string;\n collapseLabel?: string;\n expandLabel?: string;\n }>(),\n {\n as: 'aside',\n collapsed: undefined,\n defaultCollapsed: false,\n collapsible: true,\n size: 'md',\n side: 'left',\n sticky: false,\n bordered: true,\n width: '17.5rem',\n collapsedWidth: '4.75rem',\n collapseLabel: 'Collapse sidebar',\n expandLabel: 'Expand sidebar',\n },\n);\n\nconst emit = defineEmits<{\n 'update:collapsed': [value: boolean];\n 'collapse-change': [value: boolean];\n}>();\n\ndefineSlots<{\n header?: (props: { collapsed: boolean }) => unknown;\n default?: (props: { collapsed: boolean }) => unknown;\n footer?: (props: { collapsed: boolean }) => unknown;\n toggle?: (props: { collapsed: boolean }) => unknown;\n}>();\n\nconst attrs = useAttrs();\n\nconst { value: isCollapsed, setValue } = useControllableOpen(\n toRef(props, 'collapsed'),\n props.defaultCollapsed,\n (value) => {\n emit('update:collapsed', value);\n emit('collapse-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-sidebar',\n `t-sidebar--${props.size}`,\n `t-sidebar--${props.side}`,\n {\n 'is-collapsed': isCollapsed.value,\n 'is-sticky': props.sticky,\n 'is-bordered': props.bordered,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n '--tree-sidebar-width': props.width,\n '--tree-sidebar-collapsed-width': props.collapsedWidth,\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst toggleCollapsed = () => {\n if (!props.collapsible) {\n return;\n }\n\n setValue(!isCollapsed.value);\n};\n\nconst ToggleIcon = computed(() => {\n if (props.side === 'right') {\n return isCollapsed.value ? ChevronLeftIcon : ChevronRightIcon;\n }\n\n return isCollapsed.value ? ChevronRightIcon : ChevronLeftIcon;\n});\n\nconst toggleLabel = computed(() =>\n isCollapsed.value ? props.expandLabel : props.collapseLabel,\n);\n\nprovide(treeSidebarInjectionKey, {\n collapsed: computed(() => isCollapsed.value),\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isCollapsed ? 'collapsed' : 'expanded'\"\n >\n <div\n v-if=\"$slots.header\"\n class=\"t-sidebar__header\"\n >\n <slot\n name=\"header\"\n :collapsed=\"isCollapsed\"\n />\n </div>\n\n <div class=\"t-sidebar__body\">\n <slot :collapsed=\"isCollapsed\" />\n </div>\n\n <div\n v-if=\"$slots.footer || collapsible\"\n class=\"t-sidebar__footer\"\n >\n <slot\n v-if=\"$slots.footer\"\n name=\"footer\"\n :collapsed=\"isCollapsed\"\n />\n\n <button\n v-if=\"collapsible\"\n type=\"button\"\n class=\"t-sidebar__toggle\"\n :aria-label=\"toggleLabel\"\n :aria-expanded=\"!isCollapsed\"\n @click=\"toggleCollapsed\"\n >\n <slot\n name=\"toggle\"\n :collapsed=\"isCollapsed\"\n >\n <component\n :is=\"ToggleIcon\"\n :size=\"16\"\n />\n <span v-if=\"!isCollapsed\">{{ toggleLabel }}</span>\n </slot>\n </button>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-input',\n `t-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-input__slot t-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"t-input__slot t-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-input',\n `t-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-input__slot t-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"t-input__slot t-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { clamp } from '@treeui/utils';\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: number | null;\n min?: number;\n max?: number;\n step?: number;\n size?: TSize;\n disabled?: boolean;\n invalid?: boolean;\n placeholder?: string;\n controls?: boolean;\n }>(),\n {\n modelValue: null,\n min: undefined,\n max: undefined,\n step: 1,\n size: 'md',\n disabled: false,\n invalid: false,\n placeholder: '',\n controls: true,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number | null];\n}>();\n\nconst attrs = useAttrs();\nconst displayValue = ref(\n props.modelValue === null || props.modelValue === undefined ? '' : `${props.modelValue}`,\n);\n\nconst precision = computed(() => {\n const normalizedStep = `${props.step}`;\n const fractionalPart = normalizedStep.split('.')[1];\n return fractionalPart ? fractionalPart.length : 0;\n});\n\nconst rootClasses = computed(() => [\n 't-number-input',\n `t-number-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'has-controls': props.controls,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst formatValue = (value: number | null | undefined) =>\n value === null || value === undefined ? '' : `${value}`;\n\nconst normalizeValue = (value: number) => {\n const clamped = clamp(\n value,\n props.min ?? Number.NEGATIVE_INFINITY,\n props.max ?? Number.POSITIVE_INFINITY,\n );\n\n return Number(clamped.toFixed(precision.value));\n};\n\nconst parseValue = (value: string) => {\n const normalized = value.trim().replace(',', '.');\n\n if (!normalized) {\n return null;\n }\n\n const parsed = Number(normalized);\n return Number.isNaN(parsed) ? null : parsed;\n};\n\nconst currentNumericValue = computed(() => {\n const parsed = parseValue(displayValue.value);\n return parsed ?? props.modelValue ?? null;\n});\n\nconst canDecrement = computed(() => {\n if (props.disabled) {\n return false;\n }\n\n if (props.min === undefined || currentNumericValue.value === null) {\n return true;\n }\n\n return normalizeValue(currentNumericValue.value) > props.min;\n});\n\nconst canIncrement = computed(() => {\n if (props.disabled) {\n return false;\n }\n\n if (props.max === undefined || currentNumericValue.value === null) {\n return true;\n }\n\n return normalizeValue(currentNumericValue.value) < props.max;\n});\n\nconst commitValue = (value: number | null) => {\n if (value === null) {\n displayValue.value = '';\n emit('update:modelValue', null);\n return;\n }\n\n const normalized = normalizeValue(value);\n displayValue.value = `${normalized}`;\n emit('update:modelValue', normalized);\n};\n\nconst stepValue = (direction: 1 | -1) => {\n if (props.disabled) {\n return;\n }\n\n let baseValue = currentNumericValue.value ?? 0;\n\n if (currentNumericValue.value === null) {\n if (direction === 1 && props.min !== undefined) {\n baseValue = props.min - props.step;\n }\n\n if (direction === -1 && props.max !== undefined) {\n baseValue = props.max + props.step;\n }\n }\n\n commitValue(baseValue + direction * props.step);\n};\n\nconst onInput = (event: Event) => {\n const nextValue = (event.target as HTMLInputElement).value;\n displayValue.value = nextValue;\n\n if (!nextValue.trim()) {\n emit('update:modelValue', null);\n return;\n }\n\n const parsedValue = parseValue(nextValue);\n\n if (parsedValue === null) {\n return;\n }\n\n emit('update:modelValue', normalizeValue(parsedValue));\n};\n\nconst onBlur = () => {\n if (!displayValue.value.trim()) {\n displayValue.value = '';\n return;\n }\n\n const parsedValue = parseValue(displayValue.value);\n\n if (parsedValue === null) {\n displayValue.value = formatValue(props.modelValue);\n return;\n }\n\n displayValue.value = `${normalizeValue(parsedValue)}`;\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n stepValue(1);\n return;\n }\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n stepValue(-1);\n return;\n }\n\n if (event.key === 'Home' && props.min !== undefined) {\n event.preventDefault();\n commitValue(props.min);\n return;\n }\n\n if (event.key === 'End' && props.max !== undefined) {\n event.preventDefault();\n commitValue(props.max);\n }\n};\n\nwatch(\n () => props.modelValue,\n (value) => {\n const nextDisplayValue = formatValue(value);\n\n if (nextDisplayValue !== displayValue.value) {\n displayValue.value = nextDisplayValue;\n }\n },\n);\n</script>\n\n<template>\n <div\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <button\n v-if=\"controls\"\n type=\"button\"\n class=\"t-number-input__stepper t-number-input__stepper--decrement\"\n :disabled=\"!canDecrement\"\n aria-label=\"Decrease value\"\n @click=\"stepValue(-1)\"\n >\n <span aria-hidden=\"true\">-</span>\n </button>\n\n <input\n v-bind=\"inputAttrs\"\n :value=\"displayValue\"\n type=\"text\"\n inputmode=\"decimal\"\n class=\"t-number-input__field\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n @blur=\"onBlur\"\n @keydown=\"onKeydown\"\n >\n\n <button\n v-if=\"controls\"\n type=\"button\"\n class=\"t-number-input__stepper t-number-input__stepper--increment\"\n :disabled=\"!canIncrement\"\n aria-label=\"Increase value\"\n @click=\"stepValue(1)\"\n >\n <span aria-hidden=\"true\">+</span>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { clamp } from '@treeui/utils';\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: number | null;\n min?: number;\n max?: number;\n step?: number;\n size?: TSize;\n disabled?: boolean;\n invalid?: boolean;\n placeholder?: string;\n controls?: boolean;\n }>(),\n {\n modelValue: null,\n min: undefined,\n max: undefined,\n step: 1,\n size: 'md',\n disabled: false,\n invalid: false,\n placeholder: '',\n controls: true,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number | null];\n}>();\n\nconst attrs = useAttrs();\nconst displayValue = ref(\n props.modelValue === null || props.modelValue === undefined ? '' : `${props.modelValue}`,\n);\n\nconst precision = computed(() => {\n const normalizedStep = `${props.step}`;\n const fractionalPart = normalizedStep.split('.')[1];\n return fractionalPart ? fractionalPart.length : 0;\n});\n\nconst rootClasses = computed(() => [\n 't-number-input',\n `t-number-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'has-controls': props.controls,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst formatValue = (value: number | null | undefined) =>\n value === null || value === undefined ? '' : `${value}`;\n\nconst normalizeValue = (value: number) => {\n const clamped = clamp(\n value,\n props.min ?? Number.NEGATIVE_INFINITY,\n props.max ?? Number.POSITIVE_INFINITY,\n );\n\n return Number(clamped.toFixed(precision.value));\n};\n\nconst parseValue = (value: string) => {\n const normalized = value.trim().replace(',', '.');\n\n if (!normalized) {\n return null;\n }\n\n const parsed = Number(normalized);\n return Number.isNaN(parsed) ? null : parsed;\n};\n\nconst currentNumericValue = computed(() => {\n const parsed = parseValue(displayValue.value);\n return parsed ?? props.modelValue ?? null;\n});\n\nconst canDecrement = computed(() => {\n if (props.disabled) {\n return false;\n }\n\n if (props.min === undefined || currentNumericValue.value === null) {\n return true;\n }\n\n return normalizeValue(currentNumericValue.value) > props.min;\n});\n\nconst canIncrement = computed(() => {\n if (props.disabled) {\n return false;\n }\n\n if (props.max === undefined || currentNumericValue.value === null) {\n return true;\n }\n\n return normalizeValue(currentNumericValue.value) < props.max;\n});\n\nconst commitValue = (value: number | null) => {\n if (value === null) {\n displayValue.value = '';\n emit('update:modelValue', null);\n return;\n }\n\n const normalized = normalizeValue(value);\n displayValue.value = `${normalized}`;\n emit('update:modelValue', normalized);\n};\n\nconst stepValue = (direction: 1 | -1) => {\n if (props.disabled) {\n return;\n }\n\n let baseValue = currentNumericValue.value ?? 0;\n\n if (currentNumericValue.value === null) {\n if (direction === 1 && props.min !== undefined) {\n baseValue = props.min - props.step;\n }\n\n if (direction === -1 && props.max !== undefined) {\n baseValue = props.max + props.step;\n }\n }\n\n commitValue(baseValue + direction * props.step);\n};\n\nconst onInput = (event: Event) => {\n const nextValue = (event.target as HTMLInputElement).value;\n displayValue.value = nextValue;\n\n if (!nextValue.trim()) {\n emit('update:modelValue', null);\n return;\n }\n\n const parsedValue = parseValue(nextValue);\n\n if (parsedValue === null) {\n return;\n }\n\n emit('update:modelValue', normalizeValue(parsedValue));\n};\n\nconst onBlur = () => {\n if (!displayValue.value.trim()) {\n displayValue.value = '';\n return;\n }\n\n const parsedValue = parseValue(displayValue.value);\n\n if (parsedValue === null) {\n displayValue.value = formatValue(props.modelValue);\n return;\n }\n\n displayValue.value = `${normalizeValue(parsedValue)}`;\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n stepValue(1);\n return;\n }\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n stepValue(-1);\n return;\n }\n\n if (event.key === 'Home' && props.min !== undefined) {\n event.preventDefault();\n commitValue(props.min);\n return;\n }\n\n if (event.key === 'End' && props.max !== undefined) {\n event.preventDefault();\n commitValue(props.max);\n }\n};\n\nwatch(\n () => props.modelValue,\n (value) => {\n const nextDisplayValue = formatValue(value);\n\n if (nextDisplayValue !== displayValue.value) {\n displayValue.value = nextDisplayValue;\n }\n },\n);\n</script>\n\n<template>\n <div\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <button\n v-if=\"controls\"\n type=\"button\"\n class=\"t-number-input__stepper t-number-input__stepper--decrement\"\n :disabled=\"!canDecrement\"\n aria-label=\"Decrease value\"\n @click=\"stepValue(-1)\"\n >\n <span aria-hidden=\"true\">-</span>\n </button>\n\n <input\n v-bind=\"inputAttrs\"\n :value=\"displayValue\"\n type=\"text\"\n inputmode=\"decimal\"\n class=\"t-number-input__field\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n @blur=\"onBlur\"\n @keydown=\"onKeydown\"\n >\n\n <button\n v-if=\"controls\"\n type=\"button\"\n class=\"t-number-input__stepper t-number-input__stepper--increment\"\n :disabled=\"!canIncrement\"\n aria-label=\"Increase value\"\n @click=\"stepValue(1)\"\n >\n <span aria-hidden=\"true\">+</span>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, ref, useAttrs, watch, type ComponentPublicInstance } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TSelectableListItem {\n label: string;\n value: string;\n description?: string;\n meta?: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TSelectableListItem[];\n size?: TSize;\n disabled?: boolean;\n emptyText?: string;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n disabled: false,\n emptyText: 'No items available.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TSelectableListItem;\n selected: boolean;\n focused: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('t-selectable-list');\nconst itemRefs = ref<Map<string, HTMLButtonElement>>(new Map());\nconst internalValue = ref(props.defaultValue);\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 't-selectable-list',\n `t-selectable-list--${props.size}`,\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLButtonElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLButtonElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLButtonElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TSelectableListItem, focus = false) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n\n if (focus) {\n const index = props.items.findIndex((candidate) => candidate.value === item.value);\n\n if (index >= 0) {\n focusItem(index);\n }\n }\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n selectItem(props.items[firstIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n const resolvedIndex = props.items.length - 1 - lastIndex;\n selectItem(props.items[resolvedIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n selectItem(props.items[nextIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n selectItem(props.items[previousIndex], true);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index], true);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <div\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n role=\"listbox\"\n :aria-disabled=\"disabled || undefined\"\n >\n <template v-if=\"items.length > 0\">\n <button\n v-for=\"(item, index) in items\"\n :id=\"`${baseId}-${item.value}`\"\n :ref=\"(element) => setItemRef(element, item.value)\"\n :key=\"item.value\"\n type=\"button\"\n class=\"t-selectable-list__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n role=\"option\"\n :aria-selected=\"isSelected(item.value)\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :disabled=\"disabled || item.disabled\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n >\n <span\n class=\"t-selectable-list__indicator\"\n aria-hidden=\"true\"\n />\n\n <span class=\"t-selectable-list__copy\">\n <span class=\"t-selectable-list__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"t-selectable-list__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.meta\"\n class=\"t-selectable-list__meta\"\n >\n {{ item.meta }}\n </span>\n </slot>\n </button>\n </template>\n\n <div\n v-else\n class=\"t-selectable-list__empty\"\n >\n <slot name=\"empty\">\n {{ emptyText }}\n </slot>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, ref, useAttrs, watch, type ComponentPublicInstance } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TSelectableListItem {\n label: string;\n value: string;\n description?: string;\n meta?: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TSelectableListItem[];\n size?: TSize;\n disabled?: boolean;\n emptyText?: string;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n disabled: false,\n emptyText: 'No items available.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TSelectableListItem;\n selected: boolean;\n focused: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('t-selectable-list');\nconst itemRefs = ref<Map<string, HTMLButtonElement>>(new Map());\nconst internalValue = ref(props.defaultValue);\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 't-selectable-list',\n `t-selectable-list--${props.size}`,\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLButtonElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLButtonElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLButtonElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TSelectableListItem, focus = false) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n\n if (focus) {\n const index = props.items.findIndex((candidate) => candidate.value === item.value);\n\n if (index >= 0) {\n focusItem(index);\n }\n }\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n selectItem(props.items[firstIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n const resolvedIndex = props.items.length - 1 - lastIndex;\n selectItem(props.items[resolvedIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n selectItem(props.items[nextIndex], true);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n selectItem(props.items[previousIndex], true);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index], true);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <div\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n role=\"listbox\"\n :aria-disabled=\"disabled || undefined\"\n >\n <template v-if=\"items.length > 0\">\n <button\n v-for=\"(item, index) in items\"\n :id=\"`${baseId}-${item.value}`\"\n :ref=\"(element) => setItemRef(element, item.value)\"\n :key=\"item.value\"\n type=\"button\"\n class=\"t-selectable-list__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n role=\"option\"\n :aria-selected=\"isSelected(item.value)\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :disabled=\"disabled || item.disabled\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n >\n <span\n class=\"t-selectable-list__indicator\"\n aria-hidden=\"true\"\n />\n\n <span class=\"t-selectable-list__copy\">\n <span class=\"t-selectable-list__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"t-selectable-list__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.meta\"\n class=\"t-selectable-list__meta\"\n >\n {{ item.meta }}\n </span>\n </slot>\n </button>\n </template>\n\n <div\n v-else\n class=\"t-selectable-list__empty\"\n >\n <slot name=\"empty\">\n {{ emptyText }}\n </slot>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeStackDirections = ['vertical', 'horizontal'] as const;\n\nexport type TStackDirection = (typeof _treeStackDirections)[number];\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n direction?: TStackDirection;\n gap?: string;\n align?: string;\n justify?: string;\n wrap?: boolean;\n reverse?: boolean;\n }>(),\n {\n as: 'div',\n direction: 'vertical',\n gap: 'var(--tree-space-4)',\n align: 'stretch',\n justify: 'flex-start',\n wrap: false,\n reverse: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-stack',\n `t-stack--${props.direction}`,\n {\n 'is-wrapping': props.wrap,\n 'is-reversed': props.reverse,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n gap: props.gap,\n alignItems: props.align,\n justifyContent: props.justify,\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeStackDirections = ['vertical', 'horizontal'] as const;\n\nexport type TStackDirection = (typeof _treeStackDirections)[number];\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n direction?: TStackDirection;\n gap?: string;\n align?: string;\n justify?: string;\n wrap?: boolean;\n reverse?: boolean;\n }>(),\n {\n as: 'div',\n direction: 'vertical',\n gap: 'var(--tree-space-4)',\n align: 'stretch',\n justify: 'flex-start',\n wrap: false,\n reverse: false,\n },\n);\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-stack',\n `t-stack--${props.direction}`,\n {\n 'is-wrapping': props.wrap,\n 'is-reversed': props.reverse,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n gap: props.gap,\n alignItems: props.align,\n justifyContent: props.justify,\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <slot />\n </component>\n</template>\n","import type { ComputedRef, InjectionKey, Ref } from 'vue';\n\nexport interface TTreeViewNode {\n id: string;\n label: string;\n description?: string;\n meta?: string;\n disabled?: boolean;\n children?: TTreeViewNode[];\n}\n\nexport const treeTreeViewSelectionModes = ['single', 'multiple'] as const;\n\nexport type TTreeViewSelectionMode = (typeof treeTreeViewSelectionModes)[number];\n\nexport interface TTreeViewRecord {\n node: TTreeViewNode;\n level: number;\n parentId?: string;\n}\n\nexport interface TTreeViewContext {\n baseId: string;\n disabled: ComputedRef<boolean>;\n selectionMode: ComputedRef<TTreeViewSelectionMode>;\n focusedId: Ref<string>;\n isExpanded: (id: string) => boolean;\n toggleExpanded: (id: string) => void;\n isSelected: (id: string) => boolean;\n toggleSelected: (id: string) => void;\n setFocusedId: (id: string, shouldFocus?: boolean) => void;\n onItemKeydown: (event: KeyboardEvent, id: string) => void;\n registerItem: (id: string, element: HTMLElement) => void;\n unregisterItem: (id: string) => void;\n}\n\nexport const treeTreeViewInjectionKey: InjectionKey<TTreeViewContext> =\n Symbol('tree-tree-view');\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { computed, inject, type ComponentPublicInstance } from 'vue';\nimport { treeTreeViewInjectionKey, type TTreeViewNode } from './tree-view';\n\ndefineOptions({\n name: 'TTreeViewItem',\n});\n\nconst ChevronRightIcon = getTreeIcon('chevron-right');\nconst CheckIcon = getTreeIcon('check');\n\nconst props = defineProps<{\n node: TTreeViewNode;\n level: number;\n}>();\n\nconst ctx = inject(treeTreeViewInjectionKey);\n\nif (!ctx) {\n throw new Error('[TreeUI] TTreeView items must be rendered inside a TTreeView.');\n}\n\nconst hasChildren = computed(() => Boolean(props.node.children?.length));\nconst isExpanded = computed(() => (hasChildren.value ? ctx.isExpanded(props.node.id) : false));\nconst isSelected = computed(() => ctx.isSelected(props.node.id));\nconst isDisabled = computed(() => ctx.disabled.value || props.node.disabled);\nconst isFocused = computed(() => ctx.focusedId.value === props.node.id);\nconst itemId = computed(() => `${ctx.baseId}-${props.node.id}`);\n\nconst rowClasses = computed(() => ({\n 'is-expanded': isExpanded.value,\n 'is-selected': isSelected.value,\n 'is-disabled': isDisabled.value,\n 'is-focused': isFocused.value,\n}));\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLElement) {\n ctx.registerItem(props.node.id, resolvedElement);\n } else {\n ctx.unregisterItem(props.node.id);\n }\n};\n\nconst onRowClick = () => {\n ctx.setFocusedId(props.node.id);\n ctx.toggleSelected(props.node.id);\n};\n\nconst onToggleClick = () => {\n if (isDisabled.value || !hasChildren.value) {\n return;\n }\n\n ctx.toggleExpanded(props.node.id);\n ctx.setFocusedId(props.node.id);\n};\n</script>\n\n<template>\n <li\n class=\"t-tree-view__node\"\n role=\"none\"\n >\n <div\n :id=\"itemId\"\n :ref=\"setItemRef\"\n class=\"t-tree-view__row\"\n :class=\"rowClasses\"\n :style=\"{ '--tree-tree-view-level': `${level}` }\"\n role=\"treeitem\"\n :aria-level=\"level\"\n :aria-expanded=\"hasChildren ? isExpanded : undefined\"\n :aria-selected=\"isSelected\"\n :aria-disabled=\"isDisabled || undefined\"\n :tabindex=\"isDisabled ? -1 : isFocused ? 0 : -1\"\n @click=\"onRowClick\"\n @keydown=\"ctx.onItemKeydown($event, node.id)\"\n @focus=\"ctx.setFocusedId(node.id)\"\n >\n <button\n v-if=\"hasChildren\"\n type=\"button\"\n class=\"t-tree-view__toggle\"\n :class=\"{ 'is-expanded': isExpanded }\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :aria-label=\"isExpanded ? 'Collapse node' : 'Expand node'\"\n @click.stop=\"onToggleClick\"\n >\n <ChevronRightIcon :size=\"16\" />\n </button>\n\n <span\n v-else\n class=\"t-tree-view__spacer\"\n aria-hidden=\"true\"\n />\n\n <span\n class=\"t-tree-view__marker\"\n :class=\"{\n 'is-selected': isSelected,\n 'is-multiple': ctx.selectionMode.value === 'multiple',\n }\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"ctx.selectionMode.value === 'multiple' && isSelected\"\n :size=\"14\"\n />\n </span>\n\n <span class=\"t-tree-view__copy\">\n <span class=\"t-tree-view__label\">{{ node.label }}</span>\n <span\n v-if=\"node.description\"\n class=\"t-tree-view__description\"\n >\n {{ node.description }}\n </span>\n </span>\n\n <span\n v-if=\"node.meta\"\n class=\"t-tree-view__meta\"\n >\n {{ node.meta }}\n </span>\n </div>\n\n <ul\n v-if=\"hasChildren && isExpanded\"\n class=\"t-tree-view__group\"\n role=\"group\"\n >\n <TTreeViewItem\n v-for=\"child in node.children\"\n :key=\"child.id\"\n :node=\"child\"\n :level=\"level + 1\"\n />\n </ul>\n </li>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon } from '@treeui/icons';\nimport { computed, inject, type ComponentPublicInstance } from 'vue';\nimport { treeTreeViewInjectionKey, type TTreeViewNode } from './tree-view';\n\ndefineOptions({\n name: 'TTreeViewItem',\n});\n\nconst ChevronRightIcon = getTreeIcon('chevron-right');\nconst CheckIcon = getTreeIcon('check');\n\nconst props = defineProps<{\n node: TTreeViewNode;\n level: number;\n}>();\n\nconst ctx = inject(treeTreeViewInjectionKey);\n\nif (!ctx) {\n throw new Error('[TreeUI] TTreeView items must be rendered inside a TTreeView.');\n}\n\nconst hasChildren = computed(() => Boolean(props.node.children?.length));\nconst isExpanded = computed(() => (hasChildren.value ? ctx.isExpanded(props.node.id) : false));\nconst isSelected = computed(() => ctx.isSelected(props.node.id));\nconst isDisabled = computed(() => ctx.disabled.value || props.node.disabled);\nconst isFocused = computed(() => ctx.focusedId.value === props.node.id);\nconst itemId = computed(() => `${ctx.baseId}-${props.node.id}`);\n\nconst rowClasses = computed(() => ({\n 'is-expanded': isExpanded.value,\n 'is-selected': isSelected.value,\n 'is-disabled': isDisabled.value,\n 'is-focused': isFocused.value,\n}));\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLElement) {\n ctx.registerItem(props.node.id, resolvedElement);\n } else {\n ctx.unregisterItem(props.node.id);\n }\n};\n\nconst onRowClick = () => {\n ctx.setFocusedId(props.node.id);\n ctx.toggleSelected(props.node.id);\n};\n\nconst onToggleClick = () => {\n if (isDisabled.value || !hasChildren.value) {\n return;\n }\n\n ctx.toggleExpanded(props.node.id);\n ctx.setFocusedId(props.node.id);\n};\n</script>\n\n<template>\n <li\n class=\"t-tree-view__node\"\n role=\"none\"\n >\n <div\n :id=\"itemId\"\n :ref=\"setItemRef\"\n class=\"t-tree-view__row\"\n :class=\"rowClasses\"\n :style=\"{ '--tree-tree-view-level': `${level}` }\"\n role=\"treeitem\"\n :aria-level=\"level\"\n :aria-expanded=\"hasChildren ? isExpanded : undefined\"\n :aria-selected=\"isSelected\"\n :aria-disabled=\"isDisabled || undefined\"\n :tabindex=\"isDisabled ? -1 : isFocused ? 0 : -1\"\n @click=\"onRowClick\"\n @keydown=\"ctx.onItemKeydown($event, node.id)\"\n @focus=\"ctx.setFocusedId(node.id)\"\n >\n <button\n v-if=\"hasChildren\"\n type=\"button\"\n class=\"t-tree-view__toggle\"\n :class=\"{ 'is-expanded': isExpanded }\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :aria-label=\"isExpanded ? 'Collapse node' : 'Expand node'\"\n @click.stop=\"onToggleClick\"\n >\n <ChevronRightIcon :size=\"16\" />\n </button>\n\n <span\n v-else\n class=\"t-tree-view__spacer\"\n aria-hidden=\"true\"\n />\n\n <span\n class=\"t-tree-view__marker\"\n :class=\"{\n 'is-selected': isSelected,\n 'is-multiple': ctx.selectionMode.value === 'multiple',\n }\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"ctx.selectionMode.value === 'multiple' && isSelected\"\n :size=\"14\"\n />\n </span>\n\n <span class=\"t-tree-view__copy\">\n <span class=\"t-tree-view__label\">{{ node.label }}</span>\n <span\n v-if=\"node.description\"\n class=\"t-tree-view__description\"\n >\n {{ node.description }}\n </span>\n </span>\n\n <span\n v-if=\"node.meta\"\n class=\"t-tree-view__meta\"\n >\n {{ node.meta }}\n </span>\n </div>\n\n <ul\n v-if=\"hasChildren && isExpanded\"\n class=\"t-tree-view__group\"\n role=\"group\"\n >\n <TTreeViewItem\n v-for=\"child in node.children\"\n :key=\"child.id\"\n :node=\"child\"\n :level=\"level + 1\"\n />\n </ul>\n </li>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, provide, ref, useAttrs, watch } from 'vue';\nimport TTreeViewItem from './TTreeViewItem.vue';\nimport {\n treeTreeViewInjectionKey,\n type TTreeViewNode,\n type TTreeViewRecord,\n type TTreeViewSelectionMode,\n} from './tree-view';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | string[];\n defaultValue?: string | string[];\n nodes?: TTreeViewNode[];\n selectionMode?: TTreeViewSelectionMode;\n expanded?: string[];\n defaultExpanded?: string[];\n disabled?: boolean;\n emptyText?: string;\n }>(),\n {\n modelValue: undefined,\n defaultValue: undefined,\n nodes: () => [],\n selectionMode: 'single',\n expanded: undefined,\n defaultExpanded: () => [],\n disabled: false,\n emptyText: 'No items available.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined];\n 'update:expanded': [value: string[]];\n 'selection-change': [value: string | string[] | undefined];\n 'expanded-change': [value: string[]];\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('t-tree-view');\nconst internalValue = ref<string | string[] | undefined>(props.defaultValue);\nconst internalExpanded = ref<string[]>(props.defaultExpanded);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\n\nconst rootClasses = computed(() => [\n 't-tree-view',\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst treeAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst selectedValues = computed(() => {\n const value = props.modelValue ?? internalValue.value;\n\n if (value === undefined || value === null || value === '') {\n return [] as string[];\n }\n\n return Array.isArray(value) ? value : [value];\n});\n\nconst expandedValues = computed(() => props.expanded ?? internalExpanded.value);\n\nconst updateSelection = (nextValues: string[]) => {\n if (props.selectionMode === 'multiple') {\n if (props.modelValue === undefined) {\n internalValue.value = nextValues;\n }\n\n emit('update:modelValue', nextValues);\n emit('selection-change', nextValues);\n return;\n }\n\n const nextValue = nextValues[0];\n\n if (props.modelValue === undefined) {\n internalValue.value = nextValue;\n }\n\n emit('update:modelValue', nextValue);\n emit('selection-change', nextValue);\n};\n\nconst updateExpanded = (nextValues: string[]) => {\n if (props.expanded === undefined) {\n internalExpanded.value = nextValues;\n }\n\n emit('update:expanded', nextValues);\n emit('expanded-change', nextValues);\n};\n\nconst isSelected = (id: string) => selectedValues.value.includes(id);\nconst isExpanded = (id: string) => expandedValues.value.includes(id);\n\nconst flattenNodes = (\n nodes: TTreeViewNode[],\n level = 1,\n parentId?: string,\n): TTreeViewRecord[] =>\n nodes.reduce<TTreeViewRecord[]>((records, node) => {\n records.push({\n node,\n level,\n parentId,\n });\n\n if (node.children?.length && isExpanded(node.id)) {\n records.push(...flattenNodes(node.children, level + 1, node.id));\n }\n\n return records;\n }, []);\n\nconst visibleNodes = computed(() => flattenNodes(props.nodes));\nconst enabledNodes = computed(() => visibleNodes.value.filter((record) => !record.node.disabled));\n\nconst getInitialFocusedId = () => {\n const selectedId = selectedValues.value.find((value) =>\n visibleNodes.value.some((record) => record.node.id === value && !record.node.disabled),\n );\n\n if (selectedId) {\n return selectedId;\n }\n\n return enabledNodes.value[0]?.node.id ?? '';\n};\n\nconst focusedId = ref(getInitialFocusedId());\n\nconst registerItem = (id: string, element: HTMLElement) => {\n itemRefs.value.set(id, element);\n};\n\nconst unregisterItem = (id: string) => {\n itemRefs.value.delete(id);\n};\n\nconst focusItem = (id: string) => {\n nextTick(() => itemRefs.value.get(id)?.focus());\n};\n\nconst setFocusedId = (id: string, shouldFocus = false) => {\n focusedId.value = id;\n\n if (shouldFocus) {\n focusItem(id);\n }\n};\n\nconst getVisibleRecord = (id: string) =>\n visibleNodes.value.find((record) => record.node.id === id);\n\nconst focusBoundary = (position: 'first' | 'last') => {\n const target =\n position === 'first' ? enabledNodes.value[0] : enabledNodes.value[enabledNodes.value.length - 1];\n\n if (target) {\n setFocusedId(target.node.id, true);\n }\n};\n\nconst focusAdjacent = (direction: 1 | -1) => {\n const currentIndex = enabledNodes.value.findIndex((record) => record.node.id === focusedId.value);\n\n if (currentIndex === -1) {\n focusBoundary(direction === 1 ? 'first' : 'last');\n return;\n }\n\n const nextIndex = currentIndex + direction;\n\n if (nextIndex < 0 || nextIndex >= enabledNodes.value.length) {\n return;\n }\n\n setFocusedId(enabledNodes.value[nextIndex].node.id, true);\n};\n\nconst toggleExpanded = (id: string) => {\n const nextValues = isExpanded(id)\n ? expandedValues.value.filter((value) => value !== id)\n : [...expandedValues.value, id];\n\n updateExpanded(nextValues);\n};\n\nconst toggleSelected = (id: string) => {\n const record = getVisibleRecord(id);\n\n if (!record || record.node.disabled || props.disabled) {\n return;\n }\n\n if (props.selectionMode === 'multiple') {\n const nextValues = isSelected(id)\n ? selectedValues.value.filter((value) => value !== id)\n : [...selectedValues.value, id];\n\n updateSelection(nextValues);\n return;\n }\n\n updateSelection([id]);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, id: string) => {\n const record = getVisibleRecord(id);\n\n if (!record || record.node.disabled || props.disabled) {\n return;\n }\n\n const hasChildren = Boolean(record.node.children?.length);\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusAdjacent(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusAdjacent(-1);\n break;\n case 'ArrowRight':\n event.preventDefault();\n\n if (hasChildren && !isExpanded(id)) {\n toggleExpanded(id);\n return;\n }\n\n if (hasChildren) {\n const firstChild = visibleNodes.value.find(\n (item) => item.parentId === id && !item.node.disabled,\n );\n\n if (firstChild) {\n setFocusedId(firstChild.node.id, true);\n }\n }\n\n break;\n case 'ArrowLeft':\n event.preventDefault();\n\n if (hasChildren && isExpanded(id)) {\n toggleExpanded(id);\n return;\n }\n\n if (record.parentId) {\n setFocusedId(record.parentId, true);\n }\n\n break;\n case 'Home':\n event.preventDefault();\n focusBoundary('first');\n break;\n case 'End':\n event.preventDefault();\n focusBoundary('last');\n break;\n default:\n if (isActivationKey(event)) {\n event.preventDefault();\n toggleSelected(id);\n }\n break;\n }\n};\n\nwatch(\n () => [visibleNodes.value, props.modelValue] as const,\n () => {\n const focusedRecord = visibleNodes.value.find(\n (record) => record.node.id === focusedId.value && !record.node.disabled,\n );\n\n if (!focusedRecord) {\n focusedId.value = getInitialFocusedId();\n }\n },\n { deep: true, immediate: true },\n);\n\nprovide(treeTreeViewInjectionKey, {\n baseId,\n disabled: computed(() => props.disabled),\n selectionMode: computed(() => props.selectionMode),\n focusedId,\n isExpanded,\n toggleExpanded,\n isSelected,\n toggleSelected,\n setFocusedId,\n onItemKeydown,\n registerItem,\n unregisterItem,\n});\n</script>\n\n<template>\n <div\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"nodes.length > 0\"\n v-bind=\"treeAttrs\"\n class=\"t-tree-view__root\"\n role=\"tree\"\n :aria-multiselectable=\"selectionMode === 'multiple' || undefined\"\n >\n <TTreeViewItem\n v-for=\"node in nodes\"\n :key=\"node.id\"\n :node=\"node\"\n :level=\"1\"\n />\n </ul>\n\n <div\n v-else\n class=\"t-tree-view__empty\"\n >\n {{ emptyText }}\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, provide, ref, useAttrs, watch } from 'vue';\nimport TTreeViewItem from './TTreeViewItem.vue';\nimport {\n treeTreeViewInjectionKey,\n type TTreeViewNode,\n type TTreeViewRecord,\n type TTreeViewSelectionMode,\n} from './tree-view';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | string[];\n defaultValue?: string | string[];\n nodes?: TTreeViewNode[];\n selectionMode?: TTreeViewSelectionMode;\n expanded?: string[];\n defaultExpanded?: string[];\n disabled?: boolean;\n emptyText?: string;\n }>(),\n {\n modelValue: undefined,\n defaultValue: undefined,\n nodes: () => [],\n selectionMode: 'single',\n expanded: undefined,\n defaultExpanded: () => [],\n disabled: false,\n emptyText: 'No items available.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined];\n 'update:expanded': [value: string[]];\n 'selection-change': [value: string | string[] | undefined];\n 'expanded-change': [value: string[]];\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('t-tree-view');\nconst internalValue = ref<string | string[] | undefined>(props.defaultValue);\nconst internalExpanded = ref<string[]>(props.defaultExpanded);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\n\nconst rootClasses = computed(() => [\n 't-tree-view',\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst treeAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst selectedValues = computed(() => {\n const value = props.modelValue ?? internalValue.value;\n\n if (value === undefined || value === null || value === '') {\n return [] as string[];\n }\n\n return Array.isArray(value) ? value : [value];\n});\n\nconst expandedValues = computed(() => props.expanded ?? internalExpanded.value);\n\nconst updateSelection = (nextValues: string[]) => {\n if (props.selectionMode === 'multiple') {\n if (props.modelValue === undefined) {\n internalValue.value = nextValues;\n }\n\n emit('update:modelValue', nextValues);\n emit('selection-change', nextValues);\n return;\n }\n\n const nextValue = nextValues[0];\n\n if (props.modelValue === undefined) {\n internalValue.value = nextValue;\n }\n\n emit('update:modelValue', nextValue);\n emit('selection-change', nextValue);\n};\n\nconst updateExpanded = (nextValues: string[]) => {\n if (props.expanded === undefined) {\n internalExpanded.value = nextValues;\n }\n\n emit('update:expanded', nextValues);\n emit('expanded-change', nextValues);\n};\n\nconst isSelected = (id: string) => selectedValues.value.includes(id);\nconst isExpanded = (id: string) => expandedValues.value.includes(id);\n\nconst flattenNodes = (\n nodes: TTreeViewNode[],\n level = 1,\n parentId?: string,\n): TTreeViewRecord[] =>\n nodes.reduce<TTreeViewRecord[]>((records, node) => {\n records.push({\n node,\n level,\n parentId,\n });\n\n if (node.children?.length && isExpanded(node.id)) {\n records.push(...flattenNodes(node.children, level + 1, node.id));\n }\n\n return records;\n }, []);\n\nconst visibleNodes = computed(() => flattenNodes(props.nodes));\nconst enabledNodes = computed(() => visibleNodes.value.filter((record) => !record.node.disabled));\n\nconst getInitialFocusedId = () => {\n const selectedId = selectedValues.value.find((value) =>\n visibleNodes.value.some((record) => record.node.id === value && !record.node.disabled),\n );\n\n if (selectedId) {\n return selectedId;\n }\n\n return enabledNodes.value[0]?.node.id ?? '';\n};\n\nconst focusedId = ref(getInitialFocusedId());\n\nconst registerItem = (id: string, element: HTMLElement) => {\n itemRefs.value.set(id, element);\n};\n\nconst unregisterItem = (id: string) => {\n itemRefs.value.delete(id);\n};\n\nconst focusItem = (id: string) => {\n nextTick(() => itemRefs.value.get(id)?.focus());\n};\n\nconst setFocusedId = (id: string, shouldFocus = false) => {\n focusedId.value = id;\n\n if (shouldFocus) {\n focusItem(id);\n }\n};\n\nconst getVisibleRecord = (id: string) =>\n visibleNodes.value.find((record) => record.node.id === id);\n\nconst focusBoundary = (position: 'first' | 'last') => {\n const target =\n position === 'first' ? enabledNodes.value[0] : enabledNodes.value[enabledNodes.value.length - 1];\n\n if (target) {\n setFocusedId(target.node.id, true);\n }\n};\n\nconst focusAdjacent = (direction: 1 | -1) => {\n const currentIndex = enabledNodes.value.findIndex((record) => record.node.id === focusedId.value);\n\n if (currentIndex === -1) {\n focusBoundary(direction === 1 ? 'first' : 'last');\n return;\n }\n\n const nextIndex = currentIndex + direction;\n\n if (nextIndex < 0 || nextIndex >= enabledNodes.value.length) {\n return;\n }\n\n setFocusedId(enabledNodes.value[nextIndex].node.id, true);\n};\n\nconst toggleExpanded = (id: string) => {\n const nextValues = isExpanded(id)\n ? expandedValues.value.filter((value) => value !== id)\n : [...expandedValues.value, id];\n\n updateExpanded(nextValues);\n};\n\nconst toggleSelected = (id: string) => {\n const record = getVisibleRecord(id);\n\n if (!record || record.node.disabled || props.disabled) {\n return;\n }\n\n if (props.selectionMode === 'multiple') {\n const nextValues = isSelected(id)\n ? selectedValues.value.filter((value) => value !== id)\n : [...selectedValues.value, id];\n\n updateSelection(nextValues);\n return;\n }\n\n updateSelection([id]);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, id: string) => {\n const record = getVisibleRecord(id);\n\n if (!record || record.node.disabled || props.disabled) {\n return;\n }\n\n const hasChildren = Boolean(record.node.children?.length);\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusAdjacent(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusAdjacent(-1);\n break;\n case 'ArrowRight':\n event.preventDefault();\n\n if (hasChildren && !isExpanded(id)) {\n toggleExpanded(id);\n return;\n }\n\n if (hasChildren) {\n const firstChild = visibleNodes.value.find(\n (item) => item.parentId === id && !item.node.disabled,\n );\n\n if (firstChild) {\n setFocusedId(firstChild.node.id, true);\n }\n }\n\n break;\n case 'ArrowLeft':\n event.preventDefault();\n\n if (hasChildren && isExpanded(id)) {\n toggleExpanded(id);\n return;\n }\n\n if (record.parentId) {\n setFocusedId(record.parentId, true);\n }\n\n break;\n case 'Home':\n event.preventDefault();\n focusBoundary('first');\n break;\n case 'End':\n event.preventDefault();\n focusBoundary('last');\n break;\n default:\n if (isActivationKey(event)) {\n event.preventDefault();\n toggleSelected(id);\n }\n break;\n }\n};\n\nwatch(\n () => [visibleNodes.value, props.modelValue] as const,\n () => {\n const focusedRecord = visibleNodes.value.find(\n (record) => record.node.id === focusedId.value && !record.node.disabled,\n );\n\n if (!focusedRecord) {\n focusedId.value = getInitialFocusedId();\n }\n },\n { deep: true, immediate: true },\n);\n\nprovide(treeTreeViewInjectionKey, {\n baseId,\n disabled: computed(() => props.disabled),\n selectionMode: computed(() => props.selectionMode),\n focusedId,\n isExpanded,\n toggleExpanded,\n isSelected,\n toggleSelected,\n setFocusedId,\n onItemKeydown,\n registerItem,\n unregisterItem,\n});\n</script>\n\n<template>\n <div\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"nodes.length > 0\"\n v-bind=\"treeAttrs\"\n class=\"t-tree-view__root\"\n role=\"tree\"\n :aria-multiselectable=\"selectionMode === 'multiple' || undefined\"\n >\n <TTreeViewItem\n v-for=\"node in nodes\"\n :key=\"node.id\"\n :node=\"node\"\n :level=\"1\"\n />\n </ul>\n\n <div\n v-else\n class=\"t-tree-view__empty\"\n >\n {{ emptyText }}\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TStepItem {\n label: string;\n value: string;\n description?: string;\n meta?: string;\n status?: TStepStatus;\n disabled?: boolean;\n}\n\nconst _treeStepStatuses = ['complete', 'current', 'upcoming', 'error'] as const;\nconst _treeStepOrientations = ['horizontal', 'vertical'] as const;\n\nexport type TStepStatus = (typeof _treeStepStatuses)[number];\nexport type TStepOrientation = (typeof _treeStepOrientations)[number];\n\nconst CheckIcon = getTreeIcon('check');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TStepItem[];\n size?: TSize;\n orientation?: TStepOrientation;\n interactive?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n orientation: 'horizontal',\n interactive: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TStepItem;\n index: number;\n status: TStepStatus;\n current: boolean;\n }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst internalValue = ref(props.defaultValue || props.items[0]?.value || '');\n\nconst activeValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst currentIndex = computed(() => {\n const activeIndex = props.items.findIndex((item) => item.value === activeValue.value);\n return activeIndex >= 0 ? activeIndex : 0;\n});\n\nconst rootClasses = computed(() => [\n 't-steps',\n `t-steps--${props.size}`,\n `t-steps--${props.orientation}`,\n {\n 'is-interactive': props.interactive,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst resolveStatus = (item: TStepItem, index: number): TStepStatus => {\n if (item.status) {\n return item.status;\n }\n\n if (index < currentIndex.value) {\n return 'complete';\n }\n\n if (index === currentIndex.value) {\n return 'current';\n }\n\n return 'upcoming';\n};\n\nconst selectStep = (item: TStepItem) => {\n if (!props.interactive || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n};\n\nwatch(\n () => props.items,\n (items) => {\n const hasCurrentItem = items.some((item) => item.value === activeValue.value);\n\n if (!hasCurrentItem && items[0] && props.modelValue === undefined) {\n internalValue.value = items[0].value;\n }\n },\n { deep: true },\n);\n</script>\n\n<template>\n <ol\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"t-steps__item\"\n :class=\"`is-${resolveStatus(item, index)}`\"\n >\n <button\n type=\"button\"\n class=\"t-steps__button\"\n :class=\"{\n 'is-current': resolveStatus(item, index) === 'current',\n 'is-disabled': item.disabled,\n }\"\n :disabled=\"!interactive || item.disabled\"\n :aria-current=\"resolveStatus(item, index) === 'current' ? 'step' : undefined\"\n @click=\"selectStep(item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n :status=\"resolveStatus(item, index)\"\n :current=\"resolveStatus(item, index) === 'current'\"\n >\n <span\n class=\"t-steps__indicator\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"resolveStatus(item, index) === 'complete'\"\n v-bind=\"treeIconDefaults\"\n />\n <span v-else-if=\"resolveStatus(item, index) === 'error'\">!</span>\n <span v-else>{{ index + 1 }}</span>\n </span>\n\n <span class=\"t-steps__copy\">\n <span class=\"t-steps__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"t-steps__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.meta\"\n class=\"t-steps__meta\"\n >\n {{ item.meta }}\n </span>\n </slot>\n </button>\n </li>\n </ol>\n</template>\n","<script setup lang=\"ts\">\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport { computed, ref, useAttrs, watch } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TStepItem {\n label: string;\n value: string;\n description?: string;\n meta?: string;\n status?: TStepStatus;\n disabled?: boolean;\n}\n\nconst _treeStepStatuses = ['complete', 'current', 'upcoming', 'error'] as const;\nconst _treeStepOrientations = ['horizontal', 'vertical'] as const;\n\nexport type TStepStatus = (typeof _treeStepStatuses)[number];\nexport type TStepOrientation = (typeof _treeStepOrientations)[number];\n\nconst CheckIcon = getTreeIcon('check');\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TStepItem[];\n size?: TSize;\n orientation?: TStepOrientation;\n interactive?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n orientation: 'horizontal',\n interactive: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TStepItem;\n index: number;\n status: TStepStatus;\n current: boolean;\n }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst internalValue = ref(props.defaultValue || props.items[0]?.value || '');\n\nconst activeValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst currentIndex = computed(() => {\n const activeIndex = props.items.findIndex((item) => item.value === activeValue.value);\n return activeIndex >= 0 ? activeIndex : 0;\n});\n\nconst rootClasses = computed(() => [\n 't-steps',\n `t-steps--${props.size}`,\n `t-steps--${props.orientation}`,\n {\n 'is-interactive': props.interactive,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst resolveStatus = (item: TStepItem, index: number): TStepStatus => {\n if (item.status) {\n return item.status;\n }\n\n if (index < currentIndex.value) {\n return 'complete';\n }\n\n if (index === currentIndex.value) {\n return 'current';\n }\n\n return 'upcoming';\n};\n\nconst selectStep = (item: TStepItem) => {\n if (!props.interactive || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n};\n\nwatch(\n () => props.items,\n (items) => {\n const hasCurrentItem = items.some((item) => item.value === activeValue.value);\n\n if (!hasCurrentItem && items[0] && props.modelValue === undefined) {\n internalValue.value = items[0].value;\n }\n },\n { deep: true },\n);\n</script>\n\n<template>\n <ol\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"t-steps__item\"\n :class=\"`is-${resolveStatus(item, index)}`\"\n >\n <button\n type=\"button\"\n class=\"t-steps__button\"\n :class=\"{\n 'is-current': resolveStatus(item, index) === 'current',\n 'is-disabled': item.disabled,\n }\"\n :disabled=\"!interactive || item.disabled\"\n :aria-current=\"resolveStatus(item, index) === 'current' ? 'step' : undefined\"\n @click=\"selectStep(item)\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n :status=\"resolveStatus(item, index)\"\n :current=\"resolveStatus(item, index) === 'current'\"\n >\n <span\n class=\"t-steps__indicator\"\n aria-hidden=\"true\"\n >\n <CheckIcon\n v-if=\"resolveStatus(item, index) === 'complete'\"\n v-bind=\"treeIconDefaults\"\n />\n <span v-else-if=\"resolveStatus(item, index) === 'error'\">!</span>\n <span v-else>{{ index + 1 }}</span>\n </span>\n\n <span class=\"t-steps__copy\">\n <span class=\"t-steps__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"t-steps__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.meta\"\n class=\"t-steps__meta\"\n >\n {{ item.meta }}\n </span>\n </slot>\n </button>\n </li>\n </ol>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, ref, useAttrs, watch, type ComponentPublicInstance } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TToggleGroupOption {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst _treeToggleGroupSelectionModes = ['single', 'multiple'] as const;\nconst _treeToggleGroupVariants = ['outline', 'soft', 'solid'] as const;\n\nexport type TToggleGroupSelectionMode = (typeof _treeToggleGroupSelectionModes)[number];\nexport type TToggleGroupVariant = (typeof _treeToggleGroupVariants)[number];\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | string[];\n options?: TToggleGroupOption[];\n selectionMode?: TToggleGroupSelectionMode;\n size?: TSize;\n variant?: TToggleGroupVariant;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n options: () => [],\n selectionMode: 'single',\n size: 'md',\n variant: 'outline',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined];\n}>();\n\ndefineSlots<{\n option?: (props: { option: TToggleGroupOption; selected: boolean }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('t-toggle-group');\nconst buttonRefs = ref<Map<string, HTMLButtonElement>>(new Map());\n\nconst normalizedValues = computed(() =>\n props.selectionMode === 'multiple'\n ? Array.isArray(props.modelValue)\n ? props.modelValue\n : []\n : typeof props.modelValue === 'string' && props.modelValue\n ? [props.modelValue]\n : [],\n);\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.options.findIndex((option) =>\n normalizedValues.value.includes(option.value) && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.options.findIndex((option) => !option.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 't-toggle-group',\n `t-toggle-group--${props.size}`,\n `t-toggle-group--${props.variant}`,\n `t-toggle-group--${props.selectionMode}`,\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => normalizedValues.value.includes(value);\n\nconst setButtonRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLButtonElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLButtonElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLButtonElement) {\n buttonRefs.value.set(value, resolvedElement);\n } else {\n buttonRefs.value.delete(value);\n }\n};\n\nconst focusOption = (index: number) => {\n const option = props.options[index];\n\n if (!option) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => buttonRefs.value.get(option.value)?.focus());\n};\n\nconst selectValue = (value: string) => {\n const option = props.options.find((item) => item.value === value);\n\n if (!option || option.disabled || props.disabled) {\n return;\n }\n\n if (props.selectionMode === 'multiple') {\n const nextValues = isSelected(value)\n ? normalizedValues.value.filter((item) => item !== value)\n : [...normalizedValues.value, value];\n\n emit('update:modelValue', nextValues);\n return;\n }\n\n emit('update:modelValue', value);\n};\n\nconst onOptionKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.options.findIndex((option) => !option.disabled);\n\n if (firstIndex >= 0) {\n focusOption(firstIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[firstIndex].value);\n }\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.options].reverse().findIndex((option) => !option.disabled);\n\n if (lastIndex >= 0) {\n const resolvedIndex = props.options.length - 1 - lastIndex;\n focusOption(resolvedIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[resolvedIndex].value);\n }\n }\n\n return;\n }\n\n if (\n event.key === 'ArrowRight' ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowLeft' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n const direction = event.key === 'ArrowRight' || event.key === 'ArrowDown' ? 1 : -1;\n const nextIndex = getNextEnabledIndex(index, props.options, direction as 1 | -1);\n\n if (nextIndex >= 0) {\n focusOption(nextIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[nextIndex].value);\n }\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectValue(props.options[index].value);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.modelValue, props.options] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <div\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :role=\"selectionMode === 'single' ? 'radiogroup' : 'group'\"\n >\n <button\n v-for=\"(option, index) in options\"\n :id=\"`${baseId}-${option.value}`\"\n :ref=\"(element) => setButtonRef(element, option.value)\"\n :key=\"option.value\"\n type=\"button\"\n class=\"t-toggle-group__item\"\n :class=\"{\n 'is-selected': isSelected(option.value),\n 'is-disabled': disabled || option.disabled,\n }\"\n :role=\"selectionMode === 'single' ? 'radio' : undefined\"\n :aria-checked=\"selectionMode === 'single' ? isSelected(option.value) : undefined\"\n :aria-pressed=\"selectionMode === 'multiple' ? isSelected(option.value) : undefined\"\n :tabindex=\"option.disabled || disabled ? -1 : getTabIndex(index)\"\n :disabled=\"disabled || option.disabled\"\n @click=\"selectValue(option.value)\"\n @keydown=\"onOptionKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"isSelected(option.value)\"\n >\n {{ option.label }}\n </slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId, getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, nextTick, ref, useAttrs, watch, type ComponentPublicInstance } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TToggleGroupOption {\n label: string;\n value: string;\n disabled?: boolean;\n}\n\nconst _treeToggleGroupSelectionModes = ['single', 'multiple'] as const;\nconst _treeToggleGroupVariants = ['outline', 'soft', 'solid'] as const;\n\nexport type TToggleGroupSelectionMode = (typeof _treeToggleGroupSelectionModes)[number];\nexport type TToggleGroupVariant = (typeof _treeToggleGroupVariants)[number];\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | string[];\n options?: TToggleGroupOption[];\n selectionMode?: TToggleGroupSelectionMode;\n size?: TSize;\n variant?: TToggleGroupVariant;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n options: () => [],\n selectionMode: 'single',\n size: 'md',\n variant: 'outline',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined];\n}>();\n\ndefineSlots<{\n option?: (props: { option: TToggleGroupOption; selected: boolean }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst baseId = createId('t-toggle-group');\nconst buttonRefs = ref<Map<string, HTMLButtonElement>>(new Map());\n\nconst normalizedValues = computed(() =>\n props.selectionMode === 'multiple'\n ? Array.isArray(props.modelValue)\n ? props.modelValue\n : []\n : typeof props.modelValue === 'string' && props.modelValue\n ? [props.modelValue]\n : [],\n);\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.options.findIndex((option) =>\n normalizedValues.value.includes(option.value) && !option.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.options.findIndex((option) => !option.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 't-toggle-group',\n `t-toggle-group--${props.size}`,\n `t-toggle-group--${props.variant}`,\n `t-toggle-group--${props.selectionMode}`,\n {\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => normalizedValues.value.includes(value);\n\nconst setButtonRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLButtonElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLButtonElement\n ? element.$el\n : null;\n\n if (resolvedElement instanceof HTMLButtonElement) {\n buttonRefs.value.set(value, resolvedElement);\n } else {\n buttonRefs.value.delete(value);\n }\n};\n\nconst focusOption = (index: number) => {\n const option = props.options[index];\n\n if (!option) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => buttonRefs.value.get(option.value)?.focus());\n};\n\nconst selectValue = (value: string) => {\n const option = props.options.find((item) => item.value === value);\n\n if (!option || option.disabled || props.disabled) {\n return;\n }\n\n if (props.selectionMode === 'multiple') {\n const nextValues = isSelected(value)\n ? normalizedValues.value.filter((item) => item !== value)\n : [...normalizedValues.value, value];\n\n emit('update:modelValue', nextValues);\n return;\n }\n\n emit('update:modelValue', value);\n};\n\nconst onOptionKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.options.findIndex((option) => !option.disabled);\n\n if (firstIndex >= 0) {\n focusOption(firstIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[firstIndex].value);\n }\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.options].reverse().findIndex((option) => !option.disabled);\n\n if (lastIndex >= 0) {\n const resolvedIndex = props.options.length - 1 - lastIndex;\n focusOption(resolvedIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[resolvedIndex].value);\n }\n }\n\n return;\n }\n\n if (\n event.key === 'ArrowRight' ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowLeft' ||\n event.key === 'ArrowUp'\n ) {\n event.preventDefault();\n const direction = event.key === 'ArrowRight' || event.key === 'ArrowDown' ? 1 : -1;\n const nextIndex = getNextEnabledIndex(index, props.options, direction as 1 | -1);\n\n if (nextIndex >= 0) {\n focusOption(nextIndex);\n\n if (props.selectionMode === 'single') {\n selectValue(props.options[nextIndex].value);\n }\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectValue(props.options[index].value);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.modelValue, props.options] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <div\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :role=\"selectionMode === 'single' ? 'radiogroup' : 'group'\"\n >\n <button\n v-for=\"(option, index) in options\"\n :id=\"`${baseId}-${option.value}`\"\n :ref=\"(element) => setButtonRef(element, option.value)\"\n :key=\"option.value\"\n type=\"button\"\n class=\"t-toggle-group__item\"\n :class=\"{\n 'is-selected': isSelected(option.value),\n 'is-disabled': disabled || option.disabled,\n }\"\n :role=\"selectionMode === 'single' ? 'radio' : undefined\"\n :aria-checked=\"selectionMode === 'single' ? isSelected(option.value) : undefined\"\n :aria-pressed=\"selectionMode === 'multiple' ? isSelected(option.value) : undefined\"\n :tabindex=\"option.disabled || disabled ? -1 : getTabIndex(index)\"\n :disabled=\"disabled || option.disabled\"\n @click=\"selectValue(option.value)\"\n @keydown=\"onOptionKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"option\"\n :option=\"option\"\n :selected=\"isSelected(option.value)\"\n >\n {{ option.label }}\n </slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs, ref, watch, nextTick } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n rows?: number;\n autoGrow?: boolean;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n rows: 3,\n autoGrow: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\nconst textareaRef = ref<HTMLTextAreaElement | null>(null);\n\nconst rootClasses = computed(() => [\n 't-textarea',\n `t-textarea--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst textareaAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value);\n};\n\nconst adjustHeight = () => {\n const el = textareaRef.value;\n if (!el || !props.autoGrow) return;\n el.style.height = 'auto';\n el.style.height = `${el.scrollHeight}px`;\n};\n\nwatch(\n () => props.modelValue,\n async () => {\n if (!props.autoGrow) return;\n await nextTick();\n adjustHeight();\n },\n);\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <textarea\n ref=\"textareaRef\"\n v-bind=\"textareaAttrs\"\n class=\"t-textarea__field\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n />\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs, ref, watch, nextTick } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n rows?: number;\n autoGrow?: boolean;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n rows: 3,\n autoGrow: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\nconst textareaRef = ref<HTMLTextAreaElement | null>(null);\n\nconst rootClasses = computed(() => [\n 't-textarea',\n `t-textarea--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst textareaAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value);\n};\n\nconst adjustHeight = () => {\n const el = textareaRef.value;\n if (!el || !props.autoGrow) return;\n el.style.height = 'auto';\n el.style.height = `${el.scrollHeight}px`;\n};\n\nwatch(\n () => props.modelValue,\n async () => {\n if (!props.autoGrow) return;\n await nextTick();\n adjustHeight();\n },\n);\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <textarea\n ref=\"textareaRef\"\n v-bind=\"textareaAttrs\"\n class=\"t-textarea__field\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n />\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n width?: string;\n height?: string;\n animation?: 'pulse' | 'wave' | 'none';\n }>(),\n {\n width: '100%',\n height: undefined,\n animation: 'pulse',\n },\n);\n\nconst classes = computed(() => [\n 't-skeleton',\n props.animation !== 'none' ? `t-skeleton--${props.animation}` : '',\n]);\n\nconst style = computed(() => ({\n width: props.width,\n height: props.height,\n}));\n</script>\n\n<template>\n <span\n :class=\"classes\"\n :style=\"style\"\n aria-hidden=\"true\"\n >\n <slot />\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n width?: string;\n height?: string;\n animation?: 'pulse' | 'wave' | 'none';\n }>(),\n {\n width: '100%',\n height: undefined,\n animation: 'pulse',\n },\n);\n\nconst classes = computed(() => [\n 't-skeleton',\n props.animation !== 'none' ? `t-skeleton--${props.animation}` : '',\n]);\n\nconst style = computed(() => ({\n width: props.width,\n height: props.height,\n}));\n</script>\n\n<template>\n <span\n :class=\"classes\"\n :style=\"style\"\n aria-hidden=\"true\"\n >\n <slot />\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs, useSlots } from 'vue';\nimport TSkeleton from './TSkeleton.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeStatTones = ['neutral', 'success', 'warning', 'danger', 'info'] as const;\nconst _treeStatTrendDirections = ['up', 'down', 'neutral'] as const;\n\nexport type TStatTone = (typeof _treeStatTones)[number];\nexport type TStatTrendDirection = (typeof _treeStatTrendDirections)[number];\n\nconst props = withDefaults(\n defineProps<{\n label?: string;\n value?: string | number;\n trend?: string;\n meta?: string;\n tone?: TStatTone;\n trendDirection?: TStatTrendDirection;\n loading?: boolean;\n }>(),\n {\n label: '',\n value: '',\n trend: '',\n meta: '',\n tone: 'neutral',\n trendDirection: 'neutral',\n loading: false,\n },\n);\n\ndefineSlots<{\n icon?: () => unknown;\n label?: () => unknown;\n value?: () => unknown;\n trend?: () => unknown;\n meta?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst slots = useSlots();\n\nconst rootClasses = computed(() => [\n 't-stat',\n `t-stat--${props.tone}`,\n {\n 'has-icon': Boolean(slots.icon) && !props.loading,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst loadingAttrs = computed(() => ({\n ...rootAttrs.value,\n 'aria-busy': props.loading || undefined,\n}));\n\nconst hasValue = computed(() => props.value !== '' && props.value !== null && props.value !== undefined);\nconst hasTrend = computed(() => Boolean(slots.trend || props.trend));\nconst hasMeta = computed(() => Boolean(slots.meta || props.meta));\nconst hasLabel = computed(() => Boolean(slots.label || props.label));\n\nconst trendSymbol = computed(() => {\n if (props.trendDirection === 'up') {\n return '+';\n }\n\n if (props.trendDirection === 'down') {\n return '-';\n }\n\n return '•';\n});\n</script>\n\n<template>\n <div\n v-bind=\"loadingAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <template v-if=\"loading\">\n <div class=\"t-stat__loading\">\n <TSkeleton class=\"t-stat__loading-label\" />\n <TSkeleton class=\"t-stat__loading-value\" />\n <TSkeleton class=\"t-stat__loading-trend\" />\n </div>\n </template>\n <template v-else>\n <div\n v-if=\"$slots.icon\"\n class=\"t-stat__icon\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div class=\"t-stat__body\">\n <div\n v-if=\"hasLabel || hasMeta\"\n class=\"t-stat__topline\"\n >\n <p\n v-if=\"hasLabel\"\n class=\"t-stat__label\"\n >\n <slot name=\"label\">\n {{ label }}\n </slot>\n </p>\n\n <p\n v-if=\"hasMeta\"\n class=\"t-stat__meta\"\n >\n <slot name=\"meta\">\n {{ meta }}\n </slot>\n </p>\n </div>\n\n <div class=\"t-stat__content\">\n <p\n v-if=\"hasValue || $slots.value\"\n class=\"t-stat__value\"\n >\n <slot name=\"value\">\n {{ value }}\n </slot>\n </p>\n\n <p\n v-if=\"hasTrend\"\n class=\"t-stat__trend\"\n >\n <slot name=\"trend\">\n <span\n class=\"t-stat__trend-indicator\"\n aria-hidden=\"true\"\n >\n {{ trendSymbol }}\n </span>\n <span>{{ trend }}</span>\n </slot>\n </p>\n </div>\n </div>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs, useSlots } from 'vue';\nimport TSkeleton from './TSkeleton.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst _treeStatTones = ['neutral', 'success', 'warning', 'danger', 'info'] as const;\nconst _treeStatTrendDirections = ['up', 'down', 'neutral'] as const;\n\nexport type TStatTone = (typeof _treeStatTones)[number];\nexport type TStatTrendDirection = (typeof _treeStatTrendDirections)[number];\n\nconst props = withDefaults(\n defineProps<{\n label?: string;\n value?: string | number;\n trend?: string;\n meta?: string;\n tone?: TStatTone;\n trendDirection?: TStatTrendDirection;\n loading?: boolean;\n }>(),\n {\n label: '',\n value: '',\n trend: '',\n meta: '',\n tone: 'neutral',\n trendDirection: 'neutral',\n loading: false,\n },\n);\n\ndefineSlots<{\n icon?: () => unknown;\n label?: () => unknown;\n value?: () => unknown;\n trend?: () => unknown;\n meta?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst slots = useSlots();\n\nconst rootClasses = computed(() => [\n 't-stat',\n `t-stat--${props.tone}`,\n {\n 'has-icon': Boolean(slots.icon) && !props.loading,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst loadingAttrs = computed(() => ({\n ...rootAttrs.value,\n 'aria-busy': props.loading || undefined,\n}));\n\nconst hasValue = computed(() => props.value !== '' && props.value !== null && props.value !== undefined);\nconst hasTrend = computed(() => Boolean(slots.trend || props.trend));\nconst hasMeta = computed(() => Boolean(slots.meta || props.meta));\nconst hasLabel = computed(() => Boolean(slots.label || props.label));\n\nconst trendSymbol = computed(() => {\n if (props.trendDirection === 'up') {\n return '+';\n }\n\n if (props.trendDirection === 'down') {\n return '-';\n }\n\n return '•';\n});\n</script>\n\n<template>\n <div\n v-bind=\"loadingAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <template v-if=\"loading\">\n <div class=\"t-stat__loading\">\n <TSkeleton class=\"t-stat__loading-label\" />\n <TSkeleton class=\"t-stat__loading-value\" />\n <TSkeleton class=\"t-stat__loading-trend\" />\n </div>\n </template>\n <template v-else>\n <div\n v-if=\"$slots.icon\"\n class=\"t-stat__icon\"\n >\n <slot name=\"icon\" />\n </div>\n\n <div class=\"t-stat__body\">\n <div\n v-if=\"hasLabel || hasMeta\"\n class=\"t-stat__topline\"\n >\n <p\n v-if=\"hasLabel\"\n class=\"t-stat__label\"\n >\n <slot name=\"label\">\n {{ label }}\n </slot>\n </p>\n\n <p\n v-if=\"hasMeta\"\n class=\"t-stat__meta\"\n >\n <slot name=\"meta\">\n {{ meta }}\n </slot>\n </p>\n </div>\n\n <div class=\"t-stat__content\">\n <p\n v-if=\"hasValue || $slots.value\"\n class=\"t-stat__value\"\n >\n <slot name=\"value\">\n {{ value }}\n </slot>\n </p>\n\n <p\n v-if=\"hasTrend\"\n class=\"t-stat__trend\"\n >\n <slot name=\"trend\">\n <span\n class=\"t-stat__trend-indicator\"\n aria-hidden=\"true\"\n >\n {{ trendSymbol }}\n </span>\n <span>{{ trend }}</span>\n </slot>\n </p>\n </div>\n </div>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean;\n size?: TSize;\n disabled?: boolean;\n invalid?: boolean;\n }>(),\n {\n modelValue: false,\n size: 'md',\n disabled: false,\n invalid: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-switch',\n `t-switch--${props.size}`,\n {\n 'is-checked': props.modelValue,\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n emit('update:modelValue', !props.modelValue);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n v-bind=\"inputAttrs\"\n type=\"checkbox\"\n role=\"switch\"\n class=\"t-switch__input\"\n :checked=\"modelValue\"\n :disabled=\"disabled\"\n :aria-checked=\"modelValue\"\n :aria-invalid=\"invalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"t-switch__track\"\n aria-hidden=\"true\"\n >\n <span class=\"t-switch__thumb\" />\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"t-switch__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean;\n size?: TSize;\n disabled?: boolean;\n invalid?: boolean;\n }>(),\n {\n modelValue: false,\n size: 'md',\n disabled: false,\n invalid: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-switch',\n `t-switch--${props.size}`,\n {\n 'is-checked': props.modelValue,\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst onChange = () => {\n emit('update:modelValue', !props.modelValue);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <input\n v-bind=\"inputAttrs\"\n type=\"checkbox\"\n role=\"switch\"\n class=\"t-switch__input\"\n :checked=\"modelValue\"\n :disabled=\"disabled\"\n :aria-checked=\"modelValue\"\n :aria-invalid=\"invalid || undefined\"\n @change=\"onChange\"\n >\n <span\n class=\"t-switch__track\"\n aria-hidden=\"true\"\n >\n <span class=\"t-switch__thumb\" />\n </span>\n <span\n v-if=\"$slots.default\"\n class=\"t-switch__label\"\n >\n <slot />\n </span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, toRef, useAttrs } from 'vue';\nimport { createId } from '@treeui/utils';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TTooltipSide } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n content?: string;\n side?: TTooltipSide;\n delay?: number;\n id?: string;\n }>(),\n {\n defaultOpen: false,\n disabled: false,\n content: '',\n side: 'top',\n delay: 80,\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst contentId = props.id ?? createId('t-tooltip');\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst rootClasses = computed(() => ['t-tooltip', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nlet openTimer: ReturnType<typeof setTimeout> | undefined;\n\nconst clearOpenTimer = () => {\n if (openTimer) {\n clearTimeout(openTimer);\n openTimer = undefined;\n }\n};\n\nconst show = (immediate = false) => {\n if (props.disabled) {\n return;\n }\n\n clearOpenTimer();\n\n if (immediate) {\n setValue(true);\n return;\n }\n\n openTimer = setTimeout(() => {\n setValue(true);\n }, props.delay);\n};\n\nconst showOnFocus = () => {\n show(true);\n};\n\nconst showOnPointer = () => {\n show();\n};\n\nconst hide = () => {\n clearOpenTimer();\n setValue(false);\n};\n\nconst tooltipClasses = computed(() => [\n 't-tooltip__content',\n `t-tooltip__content--${props.side}`,\n]);\n\nonBeforeUnmount(clearOpenTimer);\n</script>\n\n<template>\n <span\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n @mouseenter=\"showOnPointer\"\n @mouseleave=\"hide\"\n @focus.capture=\"showOnFocus\"\n @blur.capture=\"hide\"\n >\n <span\n class=\"t-tooltip__trigger\"\n :aria-describedby=\"isOpen ? contentId : undefined\"\n v-bind=\"triggerAttrs\"\n >\n <slot name=\"trigger\">\n <slot />\n </slot>\n </span>\n <transition name=\"t-fade\">\n <span\n v-if=\"isOpen && !disabled\"\n :id=\"contentId\"\n role=\"tooltip\"\n :class=\"tooltipClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <slot name=\"content\">\n {{ content }}\n </slot>\n </span>\n </transition>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, toRef, useAttrs } from 'vue';\nimport { createId } from '@treeui/utils';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TTooltipSide } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n content?: string;\n side?: TTooltipSide;\n delay?: number;\n id?: string;\n }>(),\n {\n defaultOpen: false,\n disabled: false,\n content: '',\n side: 'top',\n delay: 80,\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst contentId = props.id ?? createId('t-tooltip');\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst rootClasses = computed(() => ['t-tooltip', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nlet openTimer: ReturnType<typeof setTimeout> | undefined;\n\nconst clearOpenTimer = () => {\n if (openTimer) {\n clearTimeout(openTimer);\n openTimer = undefined;\n }\n};\n\nconst show = (immediate = false) => {\n if (props.disabled) {\n return;\n }\n\n clearOpenTimer();\n\n if (immediate) {\n setValue(true);\n return;\n }\n\n openTimer = setTimeout(() => {\n setValue(true);\n }, props.delay);\n};\n\nconst showOnFocus = () => {\n show(true);\n};\n\nconst showOnPointer = () => {\n show();\n};\n\nconst hide = () => {\n clearOpenTimer();\n setValue(false);\n};\n\nconst tooltipClasses = computed(() => [\n 't-tooltip__content',\n `t-tooltip__content--${props.side}`,\n]);\n\nonBeforeUnmount(clearOpenTimer);\n</script>\n\n<template>\n <span\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n @mouseenter=\"showOnPointer\"\n @mouseleave=\"hide\"\n @focus.capture=\"showOnFocus\"\n @blur.capture=\"hide\"\n >\n <span\n class=\"t-tooltip__trigger\"\n :aria-describedby=\"isOpen ? contentId : undefined\"\n v-bind=\"triggerAttrs\"\n >\n <slot name=\"trigger\">\n <slot />\n </slot>\n </span>\n <transition name=\"t-fade\">\n <span\n v-if=\"isOpen && !disabled\"\n :id=\"contentId\"\n role=\"tooltip\"\n :class=\"tooltipClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <slot name=\"content\">\n {{ content }}\n </slot>\n </span>\n </transition>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n label?: string;\n htmlFor?: string;\n error?: string;\n hint?: string;\n required?: boolean;\n disabled?: boolean;\n size?: TSize;\n }>(),\n {\n label: undefined,\n htmlFor: undefined,\n error: undefined,\n hint: undefined,\n required: false,\n disabled: false,\n size: 'md',\n },\n);\n\nconst attrs = useAttrs();\n\nconst hasError = computed(() => !!props.error || !!slots.error);\n\nconst slots = defineSlots<{\n default?: (props: Record<string, never>) => unknown;\n label?: (props: Record<string, never>) => unknown;\n error?: (props: Record<string, never>) => unknown;\n hint?: (props: Record<string, never>) => unknown;\n}>();\n\nconst rootClasses = computed(() => [\n 't-form-field',\n `t-form-field--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': hasError.value,\n 'is-required': props.required,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst fieldAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <div\n v-bind=\"fieldAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <label\n v-if=\"label || $slots.label\"\n class=\"t-form-field__label\"\n :for=\"htmlFor\"\n >\n <slot name=\"label\">{{ label }}</slot>\n <span\n v-if=\"required\"\n class=\"t-form-field__required\"\n aria-hidden=\"true\"\n >*</span>\n </label>\n\n <div class=\"t-form-field__control\">\n <slot />\n </div>\n\n <p\n v-if=\"hasError\"\n class=\"t-form-field__error\"\n role=\"alert\"\n >\n <slot name=\"error\">\n {{ error }}\n </slot>\n </p>\n\n <p\n v-else-if=\"hint || $slots.hint\"\n class=\"t-form-field__hint\"\n >\n <slot name=\"hint\">\n {{ hint }}\n </slot>\n </p>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n label?: string;\n htmlFor?: string;\n error?: string;\n hint?: string;\n required?: boolean;\n disabled?: boolean;\n size?: TSize;\n }>(),\n {\n label: undefined,\n htmlFor: undefined,\n error: undefined,\n hint: undefined,\n required: false,\n disabled: false,\n size: 'md',\n },\n);\n\nconst attrs = useAttrs();\n\nconst hasError = computed(() => !!props.error || !!slots.error);\n\nconst slots = defineSlots<{\n default?: (props: Record<string, never>) => unknown;\n label?: (props: Record<string, never>) => unknown;\n error?: (props: Record<string, never>) => unknown;\n hint?: (props: Record<string, never>) => unknown;\n}>();\n\nconst rootClasses = computed(() => [\n 't-form-field',\n `t-form-field--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': hasError.value,\n 'is-required': props.required,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst fieldAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n</script>\n\n<template>\n <div\n v-bind=\"fieldAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <label\n v-if=\"label || $slots.label\"\n class=\"t-form-field__label\"\n :for=\"htmlFor\"\n >\n <slot name=\"label\">{{ label }}</slot>\n <span\n v-if=\"required\"\n class=\"t-form-field__required\"\n aria-hidden=\"true\"\n >*</span>\n </label>\n\n <div class=\"t-form-field__control\">\n <slot />\n </div>\n\n <p\n v-if=\"hasError\"\n class=\"t-form-field__error\"\n role=\"alert\"\n >\n <slot name=\"error\">\n {{ error }}\n </slot>\n </p>\n\n <p\n v-else-if=\"hint || $slots.hint\"\n class=\"t-form-field__hint\"\n >\n <slot name=\"hint\">\n {{ hint }}\n </slot>\n </p>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n /** Current active page (1-based) */\n modelValue?: number;\n /** Total number of pages */\n totalPages: number;\n /** Number of sibling pages shown around the current page */\n siblings?: number;\n /** Size variant */\n size?: TSize;\n /** Disable all controls */\n disabled?: boolean;\n /** Accessible label for the nav element */\n label?: string;\n }>(),\n {\n modelValue: 1,\n siblings: 1,\n size: 'md',\n disabled: false,\n label: 'Pagination',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [page: number];\n}>();\n\ndefineSlots<{\n previous?: (props: Record<string, never>) => unknown;\n next?: (props: Record<string, never>) => unknown;\n}>();\n\nconst currentPage = computed(() =>\n Math.min(Math.max(1, props.modelValue), props.totalPages),\n);\n\nconst pages = computed(() => {\n const total = props.totalPages;\n const current = currentPage.value;\n const siblings = props.siblings;\n const items: (number | 'ellipsis')[] = [];\n\n const rangeStart = Math.max(2, current - siblings);\n const rangeEnd = Math.min(total - 1, current + siblings);\n\n // Always show page 1\n items.push(1);\n\n // Leading ellipsis\n if (rangeStart > 2) {\n items.push('ellipsis');\n }\n\n // Sibling pages\n for (let i = rangeStart; i <= rangeEnd; i++) {\n items.push(i);\n }\n\n // Trailing ellipsis\n if (rangeEnd < total - 1) {\n items.push('ellipsis');\n }\n\n // Always show last page (if more than 1 page)\n if (total > 1) {\n items.push(total);\n }\n\n return items;\n});\n\nconst classes = computed(() => [\n 't-pagination',\n `t-pagination--${props.size}`,\n { 'is-disabled': props.disabled },\n]);\n\nfunction goToPage(page: number) {\n if (props.disabled) return;\n const clamped = Math.min(Math.max(1, page), props.totalPages);\n if (clamped !== currentPage.value) {\n emit('update:modelValue', clamped);\n }\n}\n\nfunction onKeydown(event: KeyboardEvent, page: number) {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n goToPage(page);\n }\n}\n</script>\n\n<template>\n <nav\n :class=\"classes\"\n :aria-label=\"label\"\n >\n <ul class=\"t-pagination__list\">\n <!-- Previous button -->\n <li class=\"t-pagination__item\">\n <button\n class=\"t-pagination__button t-pagination__button--prev\"\n type=\"button\"\n :disabled=\"disabled || currentPage <= 1\"\n :aria-label=\"'Go to previous page'\"\n @click=\"goToPage(currentPage - 1)\"\n >\n <slot name=\"previous\">\n <svg\n class=\"t-pagination__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M10 12L6 8l4-4\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>\n </button>\n </li>\n\n <!-- Page items -->\n <li\n v-for=\"(page, index) in pages\"\n :key=\"page === 'ellipsis' ? `ellipsis-${index}` : page\"\n class=\"t-pagination__item\"\n >\n <span\n v-if=\"page === 'ellipsis'\"\n class=\"t-pagination__ellipsis\"\n aria-hidden=\"true\"\n >\n &hellip;\n </span>\n <button\n v-else\n class=\"t-pagination__button\"\n :class=\"{ 'is-active': page === currentPage }\"\n type=\"button\"\n :disabled=\"disabled\"\n :aria-label=\"`Go to page ${page}`\"\n :aria-current=\"page === currentPage ? 'page' : undefined\"\n @click=\"goToPage(page)\"\n @keydown=\"onKeydown($event, page)\"\n >\n {{ page }}\n </button>\n </li>\n\n <!-- Next button -->\n <li class=\"t-pagination__item\">\n <button\n class=\"t-pagination__button t-pagination__button--next\"\n type=\"button\"\n :disabled=\"disabled || currentPage >= totalPages\"\n :aria-label=\"'Go to next page'\"\n @click=\"goToPage(currentPage + 1)\"\n >\n <slot name=\"next\">\n <svg\n class=\"t-pagination__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>\n </button>\n </li>\n </ul>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n /** Current active page (1-based) */\n modelValue?: number;\n /** Total number of pages */\n totalPages: number;\n /** Number of sibling pages shown around the current page */\n siblings?: number;\n /** Size variant */\n size?: TSize;\n /** Disable all controls */\n disabled?: boolean;\n /** Accessible label for the nav element */\n label?: string;\n }>(),\n {\n modelValue: 1,\n siblings: 1,\n size: 'md',\n disabled: false,\n label: 'Pagination',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [page: number];\n}>();\n\ndefineSlots<{\n previous?: (props: Record<string, never>) => unknown;\n next?: (props: Record<string, never>) => unknown;\n}>();\n\nconst currentPage = computed(() =>\n Math.min(Math.max(1, props.modelValue), props.totalPages),\n);\n\nconst pages = computed(() => {\n const total = props.totalPages;\n const current = currentPage.value;\n const siblings = props.siblings;\n const items: (number | 'ellipsis')[] = [];\n\n const rangeStart = Math.max(2, current - siblings);\n const rangeEnd = Math.min(total - 1, current + siblings);\n\n // Always show page 1\n items.push(1);\n\n // Leading ellipsis\n if (rangeStart > 2) {\n items.push('ellipsis');\n }\n\n // Sibling pages\n for (let i = rangeStart; i <= rangeEnd; i++) {\n items.push(i);\n }\n\n // Trailing ellipsis\n if (rangeEnd < total - 1) {\n items.push('ellipsis');\n }\n\n // Always show last page (if more than 1 page)\n if (total > 1) {\n items.push(total);\n }\n\n return items;\n});\n\nconst classes = computed(() => [\n 't-pagination',\n `t-pagination--${props.size}`,\n { 'is-disabled': props.disabled },\n]);\n\nfunction goToPage(page: number) {\n if (props.disabled) return;\n const clamped = Math.min(Math.max(1, page), props.totalPages);\n if (clamped !== currentPage.value) {\n emit('update:modelValue', clamped);\n }\n}\n\nfunction onKeydown(event: KeyboardEvent, page: number) {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n goToPage(page);\n }\n}\n</script>\n\n<template>\n <nav\n :class=\"classes\"\n :aria-label=\"label\"\n >\n <ul class=\"t-pagination__list\">\n <!-- Previous button -->\n <li class=\"t-pagination__item\">\n <button\n class=\"t-pagination__button t-pagination__button--prev\"\n type=\"button\"\n :disabled=\"disabled || currentPage <= 1\"\n :aria-label=\"'Go to previous page'\"\n @click=\"goToPage(currentPage - 1)\"\n >\n <slot name=\"previous\">\n <svg\n class=\"t-pagination__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M10 12L6 8l4-4\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>\n </button>\n </li>\n\n <!-- Page items -->\n <li\n v-for=\"(page, index) in pages\"\n :key=\"page === 'ellipsis' ? `ellipsis-${index}` : page\"\n class=\"t-pagination__item\"\n >\n <span\n v-if=\"page === 'ellipsis'\"\n class=\"t-pagination__ellipsis\"\n aria-hidden=\"true\"\n >\n &hellip;\n </span>\n <button\n v-else\n class=\"t-pagination__button\"\n :class=\"{ 'is-active': page === currentPage }\"\n type=\"button\"\n :disabled=\"disabled\"\n :aria-label=\"`Go to page ${page}`\"\n :aria-current=\"page === currentPage ? 'page' : undefined\"\n @click=\"goToPage(page)\"\n @keydown=\"onKeydown($event, page)\"\n >\n {{ page }}\n </button>\n </li>\n\n <!-- Next button -->\n <li class=\"t-pagination__item\">\n <button\n class=\"t-pagination__button t-pagination__button--next\"\n type=\"button\"\n :disabled=\"disabled || currentPage >= totalPages\"\n :aria-label=\"'Go to next page'\"\n @click=\"goToPage(currentPage + 1)\"\n >\n <slot name=\"next\">\n <svg\n class=\"t-pagination__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6 4l4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>\n </button>\n </li>\n </ul>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { createId, focusFirst, isEscapeKey } from '@treeui/utils';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TTooltipSide } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n side?: TTooltipSide;\n align?: 'start' | 'center' | 'end';\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n side: 'bottom',\n align: 'center',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n trigger(props: { isOpen: boolean }): unknown;\n default(): unknown;\n}>();\n\nconst attrs = useAttrs();\nconst contentId = props.id ?? createId('t-popover');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst contentRef = ref<HTMLElement | null>(null);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-popover',\n {\n 'is-open': isOpen.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst contentClasses = computed(() => [\n 't-popover__content',\n `t-popover__content--${props.side}`,\n `t-popover__content--align-${props.align}`,\n]);\n\nconst openPopover = () => {\n if (props.disabled) return;\n setValue(true);\n nextTick(() => {\n if (contentRef.value) {\n if (!focusFirst(contentRef.value)) {\n contentRef.value.focus();\n }\n }\n });\n};\n\nconst closePopover = (restoreFocus = false) => {\n setValue(false);\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst togglePopover = () => {\n if (isOpen.value) {\n closePopover();\n } else {\n openPopover();\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closePopover();\n }\n};\n\nconst onContentKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closePopover(true);\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closePopover();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-popover__anchor\"\n @click=\"togglePopover\"\n @keydown=\"onTriggerKeydown\"\n >\n <slot\n name=\"trigger\"\n :is-open=\"isOpen\"\n >\n <button\n ref=\"triggerRef\"\n type=\"button\"\n class=\"t-popover__trigger\"\n :disabled=\"disabled\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"isOpen ? contentId : undefined\"\n aria-haspopup=\"dialog\"\n v-bind=\"triggerAttrs\"\n />\n </slot>\n </div>\n <transition name=\"t-popover-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"contentId\"\n ref=\"contentRef\"\n role=\"dialog\"\n :class=\"contentClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n tabindex=\"-1\"\n @keydown=\"onContentKeydown\"\n >\n <slot />\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { createId, focusFirst, isEscapeKey } from '@treeui/utils';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TTooltipSide } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n side?: TTooltipSide;\n align?: 'start' | 'center' | 'end';\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n side: 'bottom',\n align: 'center',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n trigger(props: { isOpen: boolean }): unknown;\n default(): unknown;\n}>();\n\nconst attrs = useAttrs();\nconst contentId = props.id ?? createId('t-popover');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst contentRef = ref<HTMLElement | null>(null);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst rootClasses = computed(() => [\n 't-popover',\n {\n 'is-open': isOpen.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst contentClasses = computed(() => [\n 't-popover__content',\n `t-popover__content--${props.side}`,\n `t-popover__content--align-${props.align}`,\n]);\n\nconst openPopover = () => {\n if (props.disabled) return;\n setValue(true);\n nextTick(() => {\n if (contentRef.value) {\n if (!focusFirst(contentRef.value)) {\n contentRef.value.focus();\n }\n }\n });\n};\n\nconst closePopover = (restoreFocus = false) => {\n setValue(false);\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst togglePopover = () => {\n if (isOpen.value) {\n closePopover();\n } else {\n openPopover();\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closePopover();\n }\n};\n\nconst onContentKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closePopover(true);\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closePopover();\n};\n\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-popover__anchor\"\n @click=\"togglePopover\"\n @keydown=\"onTriggerKeydown\"\n >\n <slot\n name=\"trigger\"\n :is-open=\"isOpen\"\n >\n <button\n ref=\"triggerRef\"\n type=\"button\"\n class=\"t-popover__trigger\"\n :disabled=\"disabled\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"isOpen ? contentId : undefined\"\n aria-haspopup=\"dialog\"\n v-bind=\"triggerAttrs\"\n />\n </slot>\n </div>\n <transition name=\"t-popover-fade\">\n <div\n v-if=\"isOpen && !disabled\"\n :id=\"contentId\"\n ref=\"contentRef\"\n role=\"dialog\"\n :class=\"contentClasses\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n tabindex=\"-1\"\n @keydown=\"onContentKeydown\"\n >\n <slot />\n </div>\n </transition>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n /** Current progress value (0–100). Omit for indeterminate. */\n value?: number;\n /** Maximum value. Defaults to 100. */\n max?: number;\n /** Size variant */\n size?: TSize;\n /** Accessible label */\n label?: string;\n }>(),\n {\n value: undefined,\n max: 100,\n size: 'md',\n label: 'Progress',\n },\n);\n\nconst isIndeterminate = computed(() => props.value === undefined || props.value === null);\n\nconst percentage = computed(() => {\n if (isIndeterminate.value) return 0;\n return Math.min(100, Math.max(0, (props.value! / props.max) * 100));\n});\n\nconst classes = computed(() => [\n 't-progress',\n `t-progress--${props.size}`,\n { 't-progress--indeterminate': isIndeterminate.value },\n]);\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"progressbar\"\n :aria-valuenow=\"isIndeterminate ? undefined : percentage\"\n :aria-valuemin=\"0\"\n :aria-valuemax=\"100\"\n :aria-label=\"label\"\n >\n <div class=\"t-progress__track\">\n <div\n class=\"t-progress__fill\"\n :style=\"isIndeterminate ? undefined : { width: `${percentage}%` }\"\n />\n </div>\n\n <span class=\"t-visually-hidden\">{{ label }}</span>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nconst props = withDefaults(\n defineProps<{\n /** Current progress value (0–100). Omit for indeterminate. */\n value?: number;\n /** Maximum value. Defaults to 100. */\n max?: number;\n /** Size variant */\n size?: TSize;\n /** Accessible label */\n label?: string;\n }>(),\n {\n value: undefined,\n max: 100,\n size: 'md',\n label: 'Progress',\n },\n);\n\nconst isIndeterminate = computed(() => props.value === undefined || props.value === null);\n\nconst percentage = computed(() => {\n if (isIndeterminate.value) return 0;\n return Math.min(100, Math.max(0, (props.value! / props.max) * 100));\n});\n\nconst classes = computed(() => [\n 't-progress',\n `t-progress--${props.size}`,\n { 't-progress--indeterminate': isIndeterminate.value },\n]);\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"progressbar\"\n :aria-valuenow=\"isIndeterminate ? undefined : percentage\"\n :aria-valuemin=\"0\"\n :aria-valuemax=\"100\"\n :aria-label=\"label\"\n >\n <div class=\"t-progress__track\">\n <div\n class=\"t-progress__fill\"\n :style=\"isIndeterminate ? undefined : { width: `${percentage}%` }\"\n />\n </div>\n\n <span class=\"t-visually-hidden\">{{ label }}</span>\n </div>\n</template>\n","import type { InjectionKey, Ref } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nexport type TabsActivationMode = 'automatic' | 'manual';\n\nexport interface TabsContext {\n activeValue: Ref<string>;\n setActiveValue: (value: string) => void;\n size: Ref<TSize>;\n activationMode: Ref<TabsActivationMode>;\n disabled: Ref<boolean>;\n baseId: string;\n registerTab: (value: string) => void;\n unregisterTab: (value: string) => void;\n getTabValues: () => string[];\n isTabDisabled: (value: string) => boolean;\n setTabDisabled: (value: string, disabled: boolean) => void;\n}\n\nexport const TABS_INJECTION_KEY: InjectionKey<TabsContext> = Symbol('TTabs');\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { computed, provide, reactive, ref, toRef, watch } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport type { TabsActivationMode } from './tabs-context';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n size?: TSize;\n activationMode?: TabsActivationMode;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n size: 'md',\n activationMode: 'automatic',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst baseId = createId('t-tabs');\nconst internalValue = ref(props.defaultValue);\nconst tabOrder = ref<string[]>([]);\nconst disabledTabs: Record<string, boolean> = reactive({});\n\nconst activeValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst setActiveValue = (value: string) => {\n if (value === activeValue.value) return;\n if (props.modelValue === undefined) {\n internalValue.value = value;\n }\n emit('update:modelValue', value);\n};\n\nconst registerTab = (value: string) => {\n if (!tabOrder.value.includes(value)) {\n tabOrder.value.push(value);\n }\n};\n\nconst unregisterTab = (value: string) => {\n const idx = tabOrder.value.indexOf(value);\n if (idx >= 0) tabOrder.value.splice(idx, 1);\n delete disabledTabs[value];\n};\n\nconst getTabValues = () => tabOrder.value;\n\nconst isTabDisabled = (value: string) => props.disabled || !!disabledTabs[value];\n\nconst setTabDisabled = (value: string, disabled: boolean) => {\n if (disabled) {\n disabledTabs[value] = true;\n } else {\n delete disabledTabs[value];\n }\n};\n\nwatch(\n () => props.modelValue,\n (val) => {\n if (val !== undefined) {\n internalValue.value = val;\n }\n },\n);\n\nprovide(TABS_INJECTION_KEY, {\n activeValue,\n setActiveValue,\n size: toRef(props, 'size'),\n activationMode: toRef(props, 'activationMode'),\n disabled: toRef(props, 'disabled'),\n baseId,\n registerTab,\n unregisterTab,\n getTabValues,\n isTabDisabled,\n setTabDisabled,\n});\n\nconst rootClasses = computed(() => [\n 't-tabs',\n `t-tabs--${props.size}`,\n]);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { computed, provide, reactive, ref, toRef, watch } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport type { TabsActivationMode } from './tabs-context';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n size?: TSize;\n activationMode?: TabsActivationMode;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n size: 'md',\n activationMode: 'automatic',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst baseId = createId('t-tabs');\nconst internalValue = ref(props.defaultValue);\nconst tabOrder = ref<string[]>([]);\nconst disabledTabs: Record<string, boolean> = reactive({});\n\nconst activeValue = computed(() => props.modelValue ?? internalValue.value);\n\nconst setActiveValue = (value: string) => {\n if (value === activeValue.value) return;\n if (props.modelValue === undefined) {\n internalValue.value = value;\n }\n emit('update:modelValue', value);\n};\n\nconst registerTab = (value: string) => {\n if (!tabOrder.value.includes(value)) {\n tabOrder.value.push(value);\n }\n};\n\nconst unregisterTab = (value: string) => {\n const idx = tabOrder.value.indexOf(value);\n if (idx >= 0) tabOrder.value.splice(idx, 1);\n delete disabledTabs[value];\n};\n\nconst getTabValues = () => tabOrder.value;\n\nconst isTabDisabled = (value: string) => props.disabled || !!disabledTabs[value];\n\nconst setTabDisabled = (value: string, disabled: boolean) => {\n if (disabled) {\n disabledTabs[value] = true;\n } else {\n delete disabledTabs[value];\n }\n};\n\nwatch(\n () => props.modelValue,\n (val) => {\n if (val !== undefined) {\n internalValue.value = val;\n }\n },\n);\n\nprovide(TABS_INJECTION_KEY, {\n activeValue,\n setActiveValue,\n size: toRef(props, 'size'),\n activationMode: toRef(props, 'activationMode'),\n disabled: toRef(props, 'disabled'),\n baseId,\n registerTab,\n unregisterTab,\n getTabValues,\n isTabDisabled,\n setTabDisabled,\n});\n\nconst rootClasses = computed(() => [\n 't-tabs',\n `t-tabs--${props.size}`,\n]);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { isActivationKey } from '@treeui/utils';\nimport { computed, inject, ref } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTabList must be used inside TTabs');\n}\n\nconst listRef = ref<HTMLElement | null>(null);\n\nconst getAllTabElements = (): HTMLElement[] => {\n if (!listRef.value) return [];\n return Array.from(\n listRef.value.querySelectorAll<HTMLElement>('[role=\"tab\"]'),\n );\n};\n\nconst getEnabledTabElements = (): HTMLElement[] => {\n return getAllTabElements().filter((el) => {\n const value = el.dataset.tabValue;\n return value ? !ctx.isTabDisabled(value) : false;\n });\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n\n const current = document.activeElement as HTMLElement;\n const currentIndex = tabs.indexOf(current);\n let nextIndex = currentIndex + direction;\n\n if (nextIndex < 0) nextIndex = tabs.length - 1;\n if (nextIndex >= tabs.length) nextIndex = 0;\n\n const nextTab = tabs[nextIndex];\n nextTab.focus();\n\n if (ctx.activationMode.value === 'automatic') {\n const value = nextTab.dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst focusFirst = () => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n tabs[0].focus();\n if (ctx.activationMode.value === 'automatic') {\n const value = tabs[0].dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst focusLast = () => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n const last = tabs[tabs.length - 1];\n last.focus();\n if (ctx.activationMode.value === 'automatic') {\n const value = last.dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n switch (event.key) {\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusFirst();\n break;\n case 'End':\n event.preventDefault();\n focusLast();\n break;\n default:\n if (ctx.activationMode.value === 'manual' && isActivationKey(event)) {\n event.preventDefault();\n const target = event.target as HTMLElement;\n const value = target.dataset?.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n break;\n }\n};\n\nconst classes = computed(() => [\n 't-tabs__list',\n]);\n</script>\n\n<template>\n <div\n ref=\"listRef\"\n role=\"tablist\"\n aria-orientation=\"horizontal\"\n :class=\"classes\"\n @keydown=\"onKeydown\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { isActivationKey } from '@treeui/utils';\nimport { computed, inject, ref } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTabList must be used inside TTabs');\n}\n\nconst listRef = ref<HTMLElement | null>(null);\n\nconst getAllTabElements = (): HTMLElement[] => {\n if (!listRef.value) return [];\n return Array.from(\n listRef.value.querySelectorAll<HTMLElement>('[role=\"tab\"]'),\n );\n};\n\nconst getEnabledTabElements = (): HTMLElement[] => {\n return getAllTabElements().filter((el) => {\n const value = el.dataset.tabValue;\n return value ? !ctx.isTabDisabled(value) : false;\n });\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n\n const current = document.activeElement as HTMLElement;\n const currentIndex = tabs.indexOf(current);\n let nextIndex = currentIndex + direction;\n\n if (nextIndex < 0) nextIndex = tabs.length - 1;\n if (nextIndex >= tabs.length) nextIndex = 0;\n\n const nextTab = tabs[nextIndex];\n nextTab.focus();\n\n if (ctx.activationMode.value === 'automatic') {\n const value = nextTab.dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst focusFirst = () => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n tabs[0].focus();\n if (ctx.activationMode.value === 'automatic') {\n const value = tabs[0].dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst focusLast = () => {\n const tabs = getEnabledTabElements();\n if (!tabs.length) return;\n const last = tabs[tabs.length - 1];\n last.focus();\n if (ctx.activationMode.value === 'automatic') {\n const value = last.dataset.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n switch (event.key) {\n case 'ArrowRight':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowLeft':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusFirst();\n break;\n case 'End':\n event.preventDefault();\n focusLast();\n break;\n default:\n if (ctx.activationMode.value === 'manual' && isActivationKey(event)) {\n event.preventDefault();\n const target = event.target as HTMLElement;\n const value = target.dataset?.tabValue;\n if (value) ctx.setActiveValue(value);\n }\n break;\n }\n};\n\nconst classes = computed(() => [\n 't-tabs__list',\n]);\n</script>\n\n<template>\n <div\n ref=\"listRef\"\n role=\"tablist\"\n aria-orientation=\"horizontal\"\n :class=\"classes\"\n @keydown=\"onKeydown\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onBeforeUnmount, onMounted, watch } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n }>(),\n {\n disabled: false,\n },\n);\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTab must be used inside TTabs');\n}\n\nonMounted(() => {\n ctx.registerTab(props.value);\n ctx.setTabDisabled(props.value, props.disabled);\n});\n\nwatch(\n () => props.disabled,\n (val) => ctx.setTabDisabled(props.value, val),\n);\n\nonBeforeUnmount(() => {\n ctx.unregisterTab(props.value);\n});\n\nconst isActive = computed(() => ctx.activeValue.value === props.value);\nconst isDisabled = computed(() => ctx.isTabDisabled(props.value));\nconst tabId = computed(() => `${ctx.baseId}-tab-${props.value}`);\nconst panelId = computed(() => `${ctx.baseId}-panel-${props.value}`);\n\nconst onClick = () => {\n if (isDisabled.value) return;\n ctx.setActiveValue(props.value);\n};\n\nconst classes = computed(() => [\n 't-tabs__tab',\n `t-tabs__tab--${ctx.size.value}`,\n {\n 'is-active': isActive.value,\n 'is-disabled': isDisabled.value,\n },\n]);\n</script>\n\n<template>\n <button\n :id=\"tabId\"\n role=\"tab\"\n type=\"button\"\n :class=\"classes\"\n :aria-selected=\"isActive\"\n :aria-controls=\"panelId\"\n :tabindex=\"isActive ? 0 : -1\"\n :disabled=\"isDisabled || undefined\"\n :data-tab-value=\"value\"\n @click=\"onClick\"\n >\n <slot />\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onBeforeUnmount, onMounted, watch } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = withDefaults(\n defineProps<{\n value: string;\n disabled?: boolean;\n }>(),\n {\n disabled: false,\n },\n);\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTab must be used inside TTabs');\n}\n\nonMounted(() => {\n ctx.registerTab(props.value);\n ctx.setTabDisabled(props.value, props.disabled);\n});\n\nwatch(\n () => props.disabled,\n (val) => ctx.setTabDisabled(props.value, val),\n);\n\nonBeforeUnmount(() => {\n ctx.unregisterTab(props.value);\n});\n\nconst isActive = computed(() => ctx.activeValue.value === props.value);\nconst isDisabled = computed(() => ctx.isTabDisabled(props.value));\nconst tabId = computed(() => `${ctx.baseId}-tab-${props.value}`);\nconst panelId = computed(() => `${ctx.baseId}-panel-${props.value}`);\n\nconst onClick = () => {\n if (isDisabled.value) return;\n ctx.setActiveValue(props.value);\n};\n\nconst classes = computed(() => [\n 't-tabs__tab',\n `t-tabs__tab--${ctx.size.value}`,\n {\n 'is-active': isActive.value,\n 'is-disabled': isDisabled.value,\n },\n]);\n</script>\n\n<template>\n <button\n :id=\"tabId\"\n role=\"tab\"\n type=\"button\"\n :class=\"classes\"\n :aria-selected=\"isActive\"\n :aria-controls=\"panelId\"\n :tabindex=\"isActive ? 0 : -1\"\n :disabled=\"isDisabled || undefined\"\n :data-tab-value=\"value\"\n @click=\"onClick\"\n >\n <slot />\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = defineProps<{\n value: string;\n}>();\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTabPanel must be used inside TTabs');\n}\n\nconst isActive = computed(() => ctx.activeValue.value === props.value);\nconst panelId = computed(() => `${ctx.baseId}-panel-${props.value}`);\nconst tabId = computed(() => `${ctx.baseId}-tab-${props.value}`);\n</script>\n\n<template>\n <div\n v-if=\"isActive\"\n :id=\"panelId\"\n role=\"tabpanel\"\n :aria-labelledby=\"tabId\"\n tabindex=\"0\"\n class=\"t-tabs__panel\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue';\nimport { TABS_INJECTION_KEY } from './tabs-context';\n\nconst props = defineProps<{\n value: string;\n}>();\n\nconst ctx = inject(TABS_INJECTION_KEY);\nif (!ctx) {\n throw new Error('TTabPanel must be used inside TTabs');\n}\n\nconst isActive = computed(() => ctx.activeValue.value === props.value);\nconst panelId = computed(() => `${ctx.baseId}-panel-${props.value}`);\nconst tabId = computed(() => `${ctx.baseId}-tab-${props.value}`);\n</script>\n\n<template>\n <div\n v-if=\"isActive\"\n :id=\"panelId\"\n role=\"tabpanel\"\n :aria-labelledby=\"tabId\"\n tabindex=\"0\"\n class=\"t-tabs__panel\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport { computed } from 'vue';\nimport type { ToastItem } from '../composables/useToast';\n\nconst XIcon = getTreeIcon('x');\n\nconst iconMap = {\n info: getTreeIcon('info'),\n success: getTreeIcon('check'),\n warning: getTreeIcon('alert-circle'),\n danger: getTreeIcon('alert-circle'),\n} as const;\n\nconst props = withDefaults(\n defineProps<{\n toast: ToastItem;\n }>(),\n {},\n);\n\nconst emit = defineEmits<{\n close: [id: string];\n}>();\n\nconst toastId = createId('t-toast-item');\nconst titleId = `${toastId}-title`;\nconst descriptionId = `${toastId}-description`;\n\nconst classes = computed(() => [\n 't-toast',\n `t-toast--${props.toast.variant}`,\n]);\n\nconst StatusIcon = computed(() => iconMap[props.toast.variant]);\n\nfunction handleClose() {\n emit('close', props.toast.id);\n}\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"status\"\n :aria-labelledby=\"titleId\"\n :aria-describedby=\"toast.description ? descriptionId : undefined\"\n >\n <span\n class=\"t-toast__icon\"\n aria-hidden=\"true\"\n >\n <StatusIcon\n v-bind=\"treeIconDefaults\"\n :size=\"18\"\n />\n </span>\n <div class=\"t-toast__content\">\n <p\n :id=\"titleId\"\n class=\"t-toast__title\"\n >\n {{ toast.title }}\n </p>\n <p\n v-if=\"toast.description\"\n :id=\"descriptionId\"\n class=\"t-toast__description\"\n >\n {{ toast.description }}\n </p>\n </div>\n <button\n v-if=\"toast.closable\"\n type=\"button\"\n class=\"t-toast__close\"\n aria-label=\"Dismiss notification\"\n @click=\"handleClose\"\n >\n <XIcon\n v-bind=\"treeIconDefaults\"\n :size=\"16\"\n />\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { createId } from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport { computed } from 'vue';\nimport type { ToastItem } from '../composables/useToast';\n\nconst XIcon = getTreeIcon('x');\n\nconst iconMap = {\n info: getTreeIcon('info'),\n success: getTreeIcon('check'),\n warning: getTreeIcon('alert-circle'),\n danger: getTreeIcon('alert-circle'),\n} as const;\n\nconst props = withDefaults(\n defineProps<{\n toast: ToastItem;\n }>(),\n {},\n);\n\nconst emit = defineEmits<{\n close: [id: string];\n}>();\n\nconst toastId = createId('t-toast-item');\nconst titleId = `${toastId}-title`;\nconst descriptionId = `${toastId}-description`;\n\nconst classes = computed(() => [\n 't-toast',\n `t-toast--${props.toast.variant}`,\n]);\n\nconst StatusIcon = computed(() => iconMap[props.toast.variant]);\n\nfunction handleClose() {\n emit('close', props.toast.id);\n}\n</script>\n\n<template>\n <div\n :class=\"classes\"\n role=\"status\"\n :aria-labelledby=\"titleId\"\n :aria-describedby=\"toast.description ? descriptionId : undefined\"\n >\n <span\n class=\"t-toast__icon\"\n aria-hidden=\"true\"\n >\n <StatusIcon\n v-bind=\"treeIconDefaults\"\n :size=\"18\"\n />\n </span>\n <div class=\"t-toast__content\">\n <p\n :id=\"titleId\"\n class=\"t-toast__title\"\n >\n {{ toast.title }}\n </p>\n <p\n v-if=\"toast.description\"\n :id=\"descriptionId\"\n class=\"t-toast__description\"\n >\n {{ toast.description }}\n </p>\n </div>\n <button\n v-if=\"toast.closable\"\n type=\"button\"\n class=\"t-toast__close\"\n aria-label=\"Dismiss notification\"\n @click=\"handleClose\"\n >\n <XIcon\n v-bind=\"treeIconDefaults\"\n :size=\"16\"\n />\n </button>\n </div>\n</template>\n","import { readonly, ref } from 'vue';\nimport { createId } from '@treeui/utils';\n\nexport type ToastVariant = 'info' | 'success' | 'warning' | 'danger';\n\nexport type ToastPosition =\n | 'top-right'\n | 'top-left'\n | 'bottom-right'\n | 'bottom-left'\n | 'top-center'\n | 'bottom-center';\n\nexport interface ToastOptions {\n title: string;\n description?: string;\n variant?: ToastVariant;\n duration?: number;\n closable?: boolean;\n}\n\nexport interface ToastItem extends Required<Pick<ToastOptions, 'title' | 'variant' | 'duration' | 'closable'>> {\n id: string;\n description?: string;\n}\n\nconst toasts = ref<ToastItem[]>([]);\nconst timers = new Map<string, ReturnType<typeof setTimeout>>();\n\nfunction add(options: ToastOptions): string {\n const id = createId('tree-toast');\n\n const item: ToastItem = {\n id,\n title: options.title,\n description: options.description,\n variant: options.variant ?? 'info',\n duration: options.duration ?? 5000,\n closable: options.closable ?? true,\n };\n\n toasts.value = [...toasts.value, item];\n\n if (item.duration > 0) {\n const timer = setTimeout(() => {\n remove(id);\n }, item.duration);\n timers.set(id, timer);\n }\n\n return id;\n}\n\nfunction remove(id: string) {\n const timer = timers.get(id);\n\n if (timer) {\n clearTimeout(timer);\n timers.delete(id);\n }\n\n toasts.value = toasts.value.filter((t) => t.id !== id);\n}\n\nfunction clear() {\n for (const timer of timers.values()) {\n clearTimeout(timer);\n }\n\n timers.clear();\n toasts.value = [];\n}\n\nexport function useToast() {\n return {\n toasts: readonly(toasts),\n add,\n remove,\n clear,\n };\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { useToast, type ToastPosition } from '../composables/useToast';\nimport TToast from './TToast.vue';\n\nconst props = withDefaults(\n defineProps<{\n position?: ToastPosition;\n max?: number;\n }>(),\n {\n position: 'bottom-right',\n max: 5,\n },\n);\n\nconst { toasts, remove } = useToast();\n\nconst visibleToasts = computed(() =>\n toasts.value.slice(-props.max),\n);\n\nconst classes = computed(() => [\n 't-toast-provider',\n `t-toast-provider--${props.position}`,\n]);\n\nfunction handleClose(id: string) {\n remove(id);\n}\n</script>\n\n<template>\n <slot />\n\n <Teleport to=\"body\">\n <div\n :class=\"classes\"\n aria-live=\"polite\"\n aria-relevant=\"additions removals\"\n >\n <TransitionGroup name=\"t-toast\">\n <TToast\n v-for=\"toast in visibleToasts\"\n :key=\"toast.id\"\n :toast=\"toast\"\n @close=\"handleClose\"\n />\n </TransitionGroup>\n </div>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { useToast, type ToastPosition } from '../composables/useToast';\nimport TToast from './TToast.vue';\n\nconst props = withDefaults(\n defineProps<{\n position?: ToastPosition;\n max?: number;\n }>(),\n {\n position: 'bottom-right',\n max: 5,\n },\n);\n\nconst { toasts, remove } = useToast();\n\nconst visibleToasts = computed(() =>\n toasts.value.slice(-props.max),\n);\n\nconst classes = computed(() => [\n 't-toast-provider',\n `t-toast-provider--${props.position}`,\n]);\n\nfunction handleClose(id: string) {\n remove(id);\n}\n</script>\n\n<template>\n <slot />\n\n <Teleport to=\"body\">\n <div\n :class=\"classes\"\n aria-live=\"polite\"\n aria-relevant=\"additions removals\"\n >\n <TransitionGroup name=\"t-toast\">\n <TToast\n v-for=\"toast in visibleToasts\"\n :key=\"toast.id\"\n :toast=\"toast\"\n @close=\"handleClose\"\n />\n </TransitionGroup>\n </div>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nexport type TAvatarStatus = 'online' | 'offline' | 'busy' | 'away';\n\nconst props = withDefaults(\n defineProps<{\n src?: string;\n alt?: string;\n initials?: string;\n size?: TSize;\n status?: TAvatarStatus;\n }>(),\n {\n src: undefined,\n alt: '',\n initials: undefined,\n size: 'md',\n status: undefined,\n },\n);\n\nconst classes = computed(() => [\n 't-avatar',\n `t-avatar--${props.size}`,\n]);\n\nconst computedInitials = computed(() => {\n if (props.initials) return props.initials;\n if (props.alt) {\n return props.alt\n .split(' ')\n .filter(Boolean)\n .map((w) => w[0])\n .slice(0, 2)\n .join('')\n .toUpperCase();\n }\n return '';\n});\n\nfunction onImgError(event: Event) {\n const target = event.target as HTMLImageElement;\n target.style.display = 'none';\n}\n</script>\n\n<template>\n <span\n :class=\"classes\"\n role=\"img\"\n :aria-label=\"alt || undefined\"\n >\n <img\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt\"\n class=\"t-avatar__image\"\n @error=\"onImgError\"\n >\n <span\n v-else\n class=\"t-avatar__initials\"\n aria-hidden=\"true\"\n >\n {{ computedInitials }}\n </span>\n <slot />\n <span\n v-if=\"status\"\n class=\"t-avatar__status\"\n :class=\"`t-avatar__status--${status}`\"\n :aria-label=\"status\"\n />\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nexport type TAvatarStatus = 'online' | 'offline' | 'busy' | 'away';\n\nconst props = withDefaults(\n defineProps<{\n src?: string;\n alt?: string;\n initials?: string;\n size?: TSize;\n status?: TAvatarStatus;\n }>(),\n {\n src: undefined,\n alt: '',\n initials: undefined,\n size: 'md',\n status: undefined,\n },\n);\n\nconst classes = computed(() => [\n 't-avatar',\n `t-avatar--${props.size}`,\n]);\n\nconst computedInitials = computed(() => {\n if (props.initials) return props.initials;\n if (props.alt) {\n return props.alt\n .split(' ')\n .filter(Boolean)\n .map((w) => w[0])\n .slice(0, 2)\n .join('')\n .toUpperCase();\n }\n return '';\n});\n\nfunction onImgError(event: Event) {\n const target = event.target as HTMLImageElement;\n target.style.display = 'none';\n}\n</script>\n\n<template>\n <span\n :class=\"classes\"\n role=\"img\"\n :aria-label=\"alt || undefined\"\n >\n <img\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt\"\n class=\"t-avatar__image\"\n @error=\"onImgError\"\n >\n <span\n v-else\n class=\"t-avatar__initials\"\n aria-hidden=\"true\"\n >\n {{ computedInitials }}\n </span>\n <slot />\n <span\n v-if=\"status\"\n class=\"t-avatar__status\"\n :class=\"`t-avatar__status--${status}`\"\n :aria-label=\"status\"\n />\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n orientation?: 'horizontal' | 'vertical';\n decorative?: boolean;\n label?: string;\n }>(),\n {\n orientation: 'horizontal',\n decorative: true,\n label: undefined,\n },\n);\n\nconst classes = computed(() => [\n 't-divider',\n `t-divider--${props.orientation}`,\n]);\n</script>\n\n<template>\n <hr\n :class=\"classes\"\n :role=\"decorative ? 'none' : 'separator'\"\n :aria-orientation=\"!decorative ? orientation : undefined\"\n :aria-label=\"!decorative ? label : undefined\"\n >\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\nconst props = withDefaults(\n defineProps<{\n orientation?: 'horizontal' | 'vertical';\n decorative?: boolean;\n label?: string;\n }>(),\n {\n orientation: 'horizontal',\n decorative: true,\n label: undefined,\n },\n);\n\nconst classes = computed(() => [\n 't-divider',\n `t-divider--${props.orientation}`,\n]);\n</script>\n\n<template>\n <hr\n :class=\"classes\"\n :role=\"decorative ? 'none' : 'separator'\"\n :aria-orientation=\"!decorative ? orientation : undefined\"\n :aria-label=\"!decorative ? label : undefined\"\n >\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nexport type TTableColumn = {\n key: string;\n label: string;\n sortable?: boolean;\n align?: 'left' | 'center' | 'right';\n width?: string;\n};\n\nexport type TTableSortDirection = 'asc' | 'desc' | 'none';\n\nexport type TTableSortState = {\n key: string;\n direction: TTableSortDirection;\n};\n\nconst props = withDefaults(\n defineProps<{\n columns: TTableColumn[];\n rows: Record<string, unknown>[];\n size?: TSize;\n sortBy?: TTableSortState;\n }>(),\n {\n size: 'md',\n sortBy: undefined,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'sort', state: TTableSortState): void;\n}>();\n\ndefineSlots<{\n [key: `cell-${string}`]: (props: { row: Record<string, unknown>; value: unknown }) => void;\n [key: `header-${string}`]: (props: { column: TTableColumn }) => void;\n empty: () => void;\n}>();\n\nconst internalSort = ref<TTableSortState | undefined>(undefined);\n\nconst currentSort = computed(() => props.sortBy ?? internalSort.value);\n\nconst classes = computed(() => [\n 't-table',\n `t-table--${props.size}`,\n]);\n\nconst sortedRows = computed(() => {\n const sort = currentSort.value;\n if (!sort || sort.direction === 'none') return props.rows;\n\n return [...props.rows].sort((a, b) => {\n const aVal = a[sort.key];\n const bVal = b[sort.key];\n\n if (aVal == null && bVal == null) return 0;\n if (aVal == null) return 1;\n if (bVal == null) return -1;\n\n const cmp =\n typeof aVal === 'number' && typeof bVal === 'number'\n ? aVal - bVal\n : String(aVal).localeCompare(String(bVal));\n\n return sort.direction === 'desc' ? -cmp : cmp;\n });\n});\n\nfunction handleSort(column: TTableColumn) {\n if (!column.sortable) return;\n\n const cur = currentSort.value;\n let direction: TTableSortDirection = 'asc';\n\n if (cur?.key === column.key) {\n if (cur.direction === 'asc') direction = 'desc';\n else if (cur.direction === 'desc') direction = 'none';\n else direction = 'asc';\n }\n\n const state: TTableSortState = { key: column.key, direction };\n internalSort.value = state;\n emit('sort', state);\n}\n\nfunction sortAriaSort(column: TTableColumn): 'none' | 'ascending' | 'descending' | undefined {\n if (!column.sortable) return undefined;\n const cur = currentSort.value;\n if (cur?.key !== column.key || cur.direction === 'none') return 'none';\n return cur.direction === 'asc' ? 'ascending' : 'descending';\n}\n\nfunction handleHeaderKeydown(event: KeyboardEvent, column: TTableColumn) {\n if (column.sortable && (event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n handleSort(column);\n }\n}\n</script>\n\n<template>\n <div class=\"t-table-wrapper\">\n <table\n :class=\"classes\"\n role=\"grid\"\n >\n <thead class=\"t-table__head\">\n <tr class=\"t-table__row\">\n <th\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"t-table__header\"\n :class=\"[\n column.sortable ? 't-table__header--sortable' : '',\n column.align ? `t-table__header--${column.align}` : '',\n ]\"\n :style=\"column.width ? { width: column.width } : undefined\"\n :aria-sort=\"sortAriaSort(column)\"\n :tabindex=\"column.sortable ? 0 : undefined\"\n scope=\"col\"\n @click=\"handleSort(column)\"\n @keydown=\"handleHeaderKeydown($event, column)\"\n >\n <slot\n :name=\"`header-${column.key}`\"\n :column=\"column\"\n >\n <span class=\"t-table__header-content\">\n {{ column.label }}\n <span\n v-if=\"column.sortable\"\n class=\"t-table__sort-icon\"\n aria-hidden=\"true\"\n >\n <svg\n v-if=\"currentSort?.key === column.key && currentSort.direction === 'asc'\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n <svg\n v-else-if=\"currentSort?.key === column.key && currentSort.direction === 'desc'\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n <svg\n v-else\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n style=\"opacity: 0.4\"\n >\n <path d=\"m7 15 5 5 5-5\" />\n <path d=\"m7 9 5-5 5 5\" />\n </svg>\n </span>\n </span>\n </slot>\n </th>\n </tr>\n </thead>\n <tbody class=\"t-table__body\">\n <tr\n v-if=\"sortedRows.length === 0\"\n class=\"t-table__row t-table__row--empty\"\n >\n <td\n :colspan=\"columns.length\"\n class=\"t-table__cell t-table__cell--empty\"\n >\n <slot name=\"empty\">\n No data available.\n </slot>\n </td>\n </tr>\n <tr\n v-for=\"(row, index) in sortedRows\"\n :key=\"index\"\n class=\"t-table__row\"\n >\n <td\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"t-table__cell\"\n :class=\"column.align ? `t-table__cell--${column.align}` : ''\"\n >\n <slot\n :name=\"`cell-${column.key}`\"\n :row=\"row\"\n :value=\"row[column.key]\"\n >\n {{ row[column.key] ?? '' }}\n </slot>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nexport type TTableColumn = {\n key: string;\n label: string;\n sortable?: boolean;\n align?: 'left' | 'center' | 'right';\n width?: string;\n};\n\nexport type TTableSortDirection = 'asc' | 'desc' | 'none';\n\nexport type TTableSortState = {\n key: string;\n direction: TTableSortDirection;\n};\n\nconst props = withDefaults(\n defineProps<{\n columns: TTableColumn[];\n rows: Record<string, unknown>[];\n size?: TSize;\n sortBy?: TTableSortState;\n }>(),\n {\n size: 'md',\n sortBy: undefined,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'sort', state: TTableSortState): void;\n}>();\n\ndefineSlots<{\n [key: `cell-${string}`]: (props: { row: Record<string, unknown>; value: unknown }) => void;\n [key: `header-${string}`]: (props: { column: TTableColumn }) => void;\n empty: () => void;\n}>();\n\nconst internalSort = ref<TTableSortState | undefined>(undefined);\n\nconst currentSort = computed(() => props.sortBy ?? internalSort.value);\n\nconst classes = computed(() => [\n 't-table',\n `t-table--${props.size}`,\n]);\n\nconst sortedRows = computed(() => {\n const sort = currentSort.value;\n if (!sort || sort.direction === 'none') return props.rows;\n\n return [...props.rows].sort((a, b) => {\n const aVal = a[sort.key];\n const bVal = b[sort.key];\n\n if (aVal == null && bVal == null) return 0;\n if (aVal == null) return 1;\n if (bVal == null) return -1;\n\n const cmp =\n typeof aVal === 'number' && typeof bVal === 'number'\n ? aVal - bVal\n : String(aVal).localeCompare(String(bVal));\n\n return sort.direction === 'desc' ? -cmp : cmp;\n });\n});\n\nfunction handleSort(column: TTableColumn) {\n if (!column.sortable) return;\n\n const cur = currentSort.value;\n let direction: TTableSortDirection = 'asc';\n\n if (cur?.key === column.key) {\n if (cur.direction === 'asc') direction = 'desc';\n else if (cur.direction === 'desc') direction = 'none';\n else direction = 'asc';\n }\n\n const state: TTableSortState = { key: column.key, direction };\n internalSort.value = state;\n emit('sort', state);\n}\n\nfunction sortAriaSort(column: TTableColumn): 'none' | 'ascending' | 'descending' | undefined {\n if (!column.sortable) return undefined;\n const cur = currentSort.value;\n if (cur?.key !== column.key || cur.direction === 'none') return 'none';\n return cur.direction === 'asc' ? 'ascending' : 'descending';\n}\n\nfunction handleHeaderKeydown(event: KeyboardEvent, column: TTableColumn) {\n if (column.sortable && (event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n handleSort(column);\n }\n}\n</script>\n\n<template>\n <div class=\"t-table-wrapper\">\n <table\n :class=\"classes\"\n role=\"grid\"\n >\n <thead class=\"t-table__head\">\n <tr class=\"t-table__row\">\n <th\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"t-table__header\"\n :class=\"[\n column.sortable ? 't-table__header--sortable' : '',\n column.align ? `t-table__header--${column.align}` : '',\n ]\"\n :style=\"column.width ? { width: column.width } : undefined\"\n :aria-sort=\"sortAriaSort(column)\"\n :tabindex=\"column.sortable ? 0 : undefined\"\n scope=\"col\"\n @click=\"handleSort(column)\"\n @keydown=\"handleHeaderKeydown($event, column)\"\n >\n <slot\n :name=\"`header-${column.key}`\"\n :column=\"column\"\n >\n <span class=\"t-table__header-content\">\n {{ column.label }}\n <span\n v-if=\"column.sortable\"\n class=\"t-table__sort-icon\"\n aria-hidden=\"true\"\n >\n <svg\n v-if=\"currentSort?.key === column.key && currentSort.direction === 'asc'\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n <svg\n v-else-if=\"currentSort?.key === column.key && currentSort.direction === 'desc'\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n <svg\n v-else\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n style=\"opacity: 0.4\"\n >\n <path d=\"m7 15 5 5 5-5\" />\n <path d=\"m7 9 5-5 5 5\" />\n </svg>\n </span>\n </span>\n </slot>\n </th>\n </tr>\n </thead>\n <tbody class=\"t-table__body\">\n <tr\n v-if=\"sortedRows.length === 0\"\n class=\"t-table__row t-table__row--empty\"\n >\n <td\n :colspan=\"columns.length\"\n class=\"t-table__cell t-table__cell--empty\"\n >\n <slot name=\"empty\">\n No data available.\n </slot>\n </td>\n </tr>\n <tr\n v-for=\"(row, index) in sortedRows\"\n :key=\"index\"\n class=\"t-table__row\"\n >\n <td\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"t-table__cell\"\n :class=\"column.align ? `t-table__cell--${column.align}` : ''\"\n >\n <slot\n :name=\"`cell-${column.key}`\"\n :row=\"row\"\n :value=\"row[column.key]\"\n >\n {{ row[column.key] ?? '' }}\n </slot>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nexport type TTagVariant = 'solid' | 'outline' | 'soft';\n\nconst props = withDefaults(\n defineProps<{\n variant?: TTagVariant;\n size?: TSize;\n removable?: boolean;\n disabled?: boolean;\n }>(),\n {\n variant: 'soft',\n size: 'md',\n removable: false,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'remove'): void;\n}>();\n\nconst classes = computed(() => [\n 't-tag',\n `t-tag--${props.variant}`,\n `t-tag--${props.size}`,\n props.disabled ? 'is-disabled' : '',\n]);\n\nfunction handleRemove() {\n if (props.disabled) return;\n emit('remove');\n}\n</script>\n\n<template>\n <span :class=\"classes\">\n <span\n v-if=\"$slots.icon\"\n class=\"t-tag__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span class=\"t-tag__label\">\n <slot />\n </span>\n <button\n v-if=\"removable\"\n type=\"button\"\n class=\"t-tag__remove\"\n :disabled=\"disabled\"\n aria-label=\"Remove\"\n @click=\"handleRemove\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\n\nexport type TTagVariant = 'solid' | 'outline' | 'soft';\n\nconst props = withDefaults(\n defineProps<{\n variant?: TTagVariant;\n size?: TSize;\n removable?: boolean;\n disabled?: boolean;\n }>(),\n {\n variant: 'soft',\n size: 'md',\n removable: false,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'remove'): void;\n}>();\n\nconst classes = computed(() => [\n 't-tag',\n `t-tag--${props.variant}`,\n `t-tag--${props.size}`,\n props.disabled ? 'is-disabled' : '',\n]);\n\nfunction handleRemove() {\n if (props.disabled) return;\n emit('remove');\n}\n</script>\n\n<template>\n <span :class=\"classes\">\n <span\n v-if=\"$slots.icon\"\n class=\"t-tag__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span class=\"t-tag__label\">\n <slot />\n </span>\n <button\n v-if=\"removable\"\n type=\"button\"\n class=\"t-tag__remove\"\n :disabled=\"disabled\"\n aria-label=\"Remove\"\n @click=\"handleRemove\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport type TTimelineTone = 'neutral' | 'brand' | 'success' | 'warning' | 'danger';\n\nexport interface TTimelineItem {\n id?: string | number;\n title: string;\n description?: string;\n meta?: string;\n timestamp?: string;\n datetime?: string;\n tone?: TTimelineTone;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TTimelineItem[];\n size?: TSize;\n }>(),\n {\n items: () => [],\n size: 'md',\n },\n);\n\ndefineSlots<{\n marker?: (props: { item: TTimelineItem; index: number }) => unknown;\n item?: (props: { item: TTimelineItem; index: number }) => unknown;\n}>();\n\nconst attrs = useAttrs();\n\nconst classes = computed(() => [\n 't-timeline',\n `t-timeline--${props.size}`,\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst normalizeTone = (tone?: TTimelineTone) => tone ?? 'neutral';\nconst itemKey = (item: TTimelineItem, index: number) => item.id ?? `${item.title}-${index}`;\n</script>\n\n<template>\n <ol\n v-bind=\"rootAttrs\"\n :class=\"classes\"\n :style=\"rootStyle\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"itemKey(item, index)\"\n class=\"t-timeline__item\"\n >\n <div class=\"t-timeline__rail\">\n <span\n v-if=\"index < items.length - 1\"\n class=\"t-timeline__line\"\n aria-hidden=\"true\"\n />\n <div\n class=\"t-timeline__marker\"\n :class=\"`t-timeline__marker--${normalizeTone(item.tone)}`\"\n aria-hidden=\"true\"\n >\n <slot\n name=\"marker\"\n :item=\"item\"\n :index=\"index\"\n />\n </div>\n </div>\n\n <div class=\"t-timeline__content\">\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n <div\n v-if=\"item.meta\"\n class=\"t-timeline__meta\"\n >\n {{ item.meta }}\n </div>\n\n <div class=\"t-timeline__header\">\n <p class=\"t-timeline__title\">\n {{ item.title }}\n </p>\n <time\n v-if=\"item.timestamp\"\n class=\"t-timeline__timestamp\"\n :datetime=\"item.datetime || undefined\"\n >\n {{ item.timestamp }}\n </time>\n </div>\n\n <p\n v-if=\"item.description\"\n class=\"t-timeline__description\"\n >\n {{ item.description }}\n </p>\n </slot>\n </div>\n </li>\n </ol>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport type TTimelineTone = 'neutral' | 'brand' | 'success' | 'warning' | 'danger';\n\nexport interface TTimelineItem {\n id?: string | number;\n title: string;\n description?: string;\n meta?: string;\n timestamp?: string;\n datetime?: string;\n tone?: TTimelineTone;\n}\n\nconst props = withDefaults(\n defineProps<{\n items?: TTimelineItem[];\n size?: TSize;\n }>(),\n {\n items: () => [],\n size: 'md',\n },\n);\n\ndefineSlots<{\n marker?: (props: { item: TTimelineItem; index: number }) => unknown;\n item?: (props: { item: TTimelineItem; index: number }) => unknown;\n}>();\n\nconst attrs = useAttrs();\n\nconst classes = computed(() => [\n 't-timeline',\n `t-timeline--${props.size}`,\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst normalizeTone = (tone?: TTimelineTone) => tone ?? 'neutral';\nconst itemKey = (item: TTimelineItem, index: number) => item.id ?? `${item.title}-${index}`;\n</script>\n\n<template>\n <ol\n v-bind=\"rootAttrs\"\n :class=\"classes\"\n :style=\"rootStyle\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"itemKey(item, index)\"\n class=\"t-timeline__item\"\n >\n <div class=\"t-timeline__rail\">\n <span\n v-if=\"index < items.length - 1\"\n class=\"t-timeline__line\"\n aria-hidden=\"true\"\n />\n <div\n class=\"t-timeline__marker\"\n :class=\"`t-timeline__marker--${normalizeTone(item.tone)}`\"\n aria-hidden=\"true\"\n >\n <slot\n name=\"marker\"\n :item=\"item\"\n :index=\"index\"\n />\n </div>\n </div>\n\n <div class=\"t-timeline__content\">\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n >\n <div\n v-if=\"item.meta\"\n class=\"t-timeline__meta\"\n >\n {{ item.meta }}\n </div>\n\n <div class=\"t-timeline__header\">\n <p class=\"t-timeline__title\">\n {{ item.title }}\n </p>\n <time\n v-if=\"item.timestamp\"\n class=\"t-timeline__timestamp\"\n :datetime=\"item.datetime || undefined\"\n >\n {{ item.timestamp }}\n </time>\n </div>\n\n <p\n v-if=\"item.description\"\n class=\"t-timeline__description\"\n >\n {{ item.description }}\n </p>\n </slot>\n </div>\n </li>\n </ol>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TButton from './TButton.vue';\nimport TBadge from './TBadge.vue';\n\nexport interface PricingFeature {\n text: string;\n included?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n title: string;\n description?: string;\n price: string | number;\n currency?: string;\n period?: string;\n features?: PricingFeature[];\n highlighted?: boolean;\n badge?: string;\n buttonText?: string;\n size?: TSize;\n disabled?: boolean;\n }>(),\n {\n description: undefined,\n currency: '$',\n period: undefined,\n features: () => [],\n highlighted: false,\n badge: undefined,\n buttonText: undefined,\n size: 'md',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n select: [];\n}>();\n\ndefineSlots<{\n header?: () => unknown;\n price?: () => unknown;\n features?: () => unknown;\n action?: () => unknown;\n badge?: () => unknown;\n}>();\n\nconst classes = computed(() => [\n 't-pricing-card',\n `t-pricing-card--${props.size}`,\n {\n 't-pricing-card--highlighted': props.highlighted,\n },\n]);\n\nconst onSelect = () => {\n if (!props.disabled) {\n emit('select');\n }\n};\n</script>\n\n<template>\n <article :class=\"classes\">\n <div\n v-if=\"badge || $slots.badge\"\n class=\"t-pricing-card__badge\"\n >\n <slot name=\"badge\">\n <TBadge\n variant=\"solid\"\n size=\"sm\"\n >\n {{ badge }}\n </TBadge>\n </slot>\n </div>\n\n <header class=\"t-pricing-card__header\">\n <slot name=\"header\">\n <h3 class=\"t-pricing-card__title\">\n {{ title }}\n </h3>\n <p\n v-if=\"description\"\n class=\"t-pricing-card__description\"\n >\n {{ description }}\n </p>\n </slot>\n </header>\n\n <div class=\"t-pricing-card__price\">\n <slot name=\"price\">\n <span class=\"t-pricing-card__currency\">{{ currency }}</span>\n <span class=\"t-pricing-card__amount\">{{ price }}</span>\n <span\n v-if=\"period\"\n class=\"t-pricing-card__period\"\n >{{ period }}</span>\n </slot>\n </div>\n\n <div\n v-if=\"features.length > 0 || $slots.features\"\n class=\"t-pricing-card__features\"\n >\n <slot name=\"features\">\n <ul\n class=\"t-pricing-card__feature-list\"\n role=\"list\"\n >\n <li\n v-for=\"(feature, index) in features\"\n :key=\"index\"\n class=\"t-pricing-card__feature-item\"\n :class=\"{ 't-pricing-card__feature-item--excluded': feature.included === false }\"\n >\n <span\n class=\"t-pricing-card__feature-icon\"\n aria-hidden=\"true\"\n >\n {{ feature.included === false ? '✕' : '✓' }}\n </span>\n <span>{{ feature.text }}</span>\n </li>\n </ul>\n </slot>\n </div>\n\n <footer\n v-if=\"buttonText || $slots.action\"\n class=\"t-pricing-card__action\"\n >\n <slot name=\"action\">\n <TButton\n :variant=\"highlighted ? 'solid' : 'outline'\"\n :size=\"size\"\n :disabled=\"disabled\"\n @click=\"onSelect\"\n >\n {{ buttonText }}\n </TButton>\n </slot>\n </footer>\n </article>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TButton from './TButton.vue';\nimport TBadge from './TBadge.vue';\n\nexport interface PricingFeature {\n text: string;\n included?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n title: string;\n description?: string;\n price: string | number;\n currency?: string;\n period?: string;\n features?: PricingFeature[];\n highlighted?: boolean;\n badge?: string;\n buttonText?: string;\n size?: TSize;\n disabled?: boolean;\n }>(),\n {\n description: undefined,\n currency: '$',\n period: undefined,\n features: () => [],\n highlighted: false,\n badge: undefined,\n buttonText: undefined,\n size: 'md',\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n select: [];\n}>();\n\ndefineSlots<{\n header?: () => unknown;\n price?: () => unknown;\n features?: () => unknown;\n action?: () => unknown;\n badge?: () => unknown;\n}>();\n\nconst classes = computed(() => [\n 't-pricing-card',\n `t-pricing-card--${props.size}`,\n {\n 't-pricing-card--highlighted': props.highlighted,\n },\n]);\n\nconst onSelect = () => {\n if (!props.disabled) {\n emit('select');\n }\n};\n</script>\n\n<template>\n <article :class=\"classes\">\n <div\n v-if=\"badge || $slots.badge\"\n class=\"t-pricing-card__badge\"\n >\n <slot name=\"badge\">\n <TBadge\n variant=\"solid\"\n size=\"sm\"\n >\n {{ badge }}\n </TBadge>\n </slot>\n </div>\n\n <header class=\"t-pricing-card__header\">\n <slot name=\"header\">\n <h3 class=\"t-pricing-card__title\">\n {{ title }}\n </h3>\n <p\n v-if=\"description\"\n class=\"t-pricing-card__description\"\n >\n {{ description }}\n </p>\n </slot>\n </header>\n\n <div class=\"t-pricing-card__price\">\n <slot name=\"price\">\n <span class=\"t-pricing-card__currency\">{{ currency }}</span>\n <span class=\"t-pricing-card__amount\">{{ price }}</span>\n <span\n v-if=\"period\"\n class=\"t-pricing-card__period\"\n >{{ period }}</span>\n </slot>\n </div>\n\n <div\n v-if=\"features.length > 0 || $slots.features\"\n class=\"t-pricing-card__features\"\n >\n <slot name=\"features\">\n <ul\n class=\"t-pricing-card__feature-list\"\n role=\"list\"\n >\n <li\n v-for=\"(feature, index) in features\"\n :key=\"index\"\n class=\"t-pricing-card__feature-item\"\n :class=\"{ 't-pricing-card__feature-item--excluded': feature.included === false }\"\n >\n <span\n class=\"t-pricing-card__feature-icon\"\n aria-hidden=\"true\"\n >\n {{ feature.included === false ? '✕' : '✓' }}\n </span>\n <span>{{ feature.text }}</span>\n </li>\n </ul>\n </slot>\n </div>\n\n <footer\n v-if=\"buttonText || $slots.action\"\n class=\"t-pricing-card__action\"\n >\n <slot name=\"action\">\n <TButton\n :variant=\"highlighted ? 'solid' : 'outline'\"\n :size=\"size\"\n :disabled=\"disabled\"\n @click=\"onSelect\"\n >\n {{ buttonText }}\n </TButton>\n </slot>\n </footer>\n </article>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TPricingCard from './TPricingCard.vue';\nimport type { PricingFeature } from './TPricingCard.vue';\n\nexport interface PricingPlan {\n title: string;\n description?: string;\n price: string | number;\n currency?: string;\n period?: string;\n features?: PricingFeature[];\n highlighted?: boolean;\n badge?: string;\n buttonText?: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n plans: PricingPlan[];\n size?: TSize;\n columns?: number;\n }>(),\n {\n size: 'md',\n columns: undefined,\n },\n);\n\nconst emit = defineEmits<{\n select: [plan: PricingPlan, index: number];\n}>();\n\nconst gridStyle = computed(() => {\n if (props.columns) {\n return { gridTemplateColumns: `repeat(${props.columns}, 1fr)` };\n }\n return { gridTemplateColumns: `repeat(${props.plans.length}, 1fr)` };\n});\n</script>\n\n<template>\n <div\n class=\"t-pricing\"\n :style=\"gridStyle\"\n role=\"list\"\n >\n <div\n v-for=\"(plan, index) in plans\"\n :key=\"index\"\n role=\"listitem\"\n >\n <slot\n name=\"plan\"\n :plan=\"plan\"\n :index=\"index\"\n >\n <TPricingCard\n v-bind=\"plan\"\n :size=\"size\"\n @select=\"emit('select', plan, index)\"\n />\n </slot>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TPricingCard from './TPricingCard.vue';\nimport type { PricingFeature } from './TPricingCard.vue';\n\nexport interface PricingPlan {\n title: string;\n description?: string;\n price: string | number;\n currency?: string;\n period?: string;\n features?: PricingFeature[];\n highlighted?: boolean;\n badge?: string;\n buttonText?: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n plans: PricingPlan[];\n size?: TSize;\n columns?: number;\n }>(),\n {\n size: 'md',\n columns: undefined,\n },\n);\n\nconst emit = defineEmits<{\n select: [plan: PricingPlan, index: number];\n}>();\n\nconst gridStyle = computed(() => {\n if (props.columns) {\n return { gridTemplateColumns: `repeat(${props.columns}, 1fr)` };\n }\n return { gridTemplateColumns: `repeat(${props.plans.length}, 1fr)` };\n});\n</script>\n\n<template>\n <div\n class=\"t-pricing\"\n :style=\"gridStyle\"\n role=\"list\"\n >\n <div\n v-for=\"(plan, index) in plans\"\n :key=\"index\"\n role=\"listitem\"\n >\n <slot\n name=\"plan\"\n :plan=\"plan\"\n :index=\"index\"\n >\n <TPricingCard\n v-bind=\"plan\"\n :size=\"size\"\n @select=\"emit('select', plan, index)\"\n />\n </slot>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs, nextTick } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n size?: TSize;\n disabled?: boolean;\n placeholder?: string;\n uploadImage?: (file: File) => Promise<string>;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n placeholder: 'Write your markdown here...',\n uploadImage: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'image-upload': [file: File, url: string];\n 'image-upload-error': [file: File, error: Error];\n}>();\n\ndefineSlots<{\n toolbar?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst textareaRef = ref<HTMLTextAreaElement | null>(null);\nconst isUploading = ref(false);\n\nconst rootClasses = computed(() => [\n 't-md-editor',\n `t-md-editor--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-uploading': isUploading.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst editorAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value);\n};\n\n/* ──────── Toolbar Actions ──────── */\n\nconst insertAtCursor = (before: string, after = '') => {\n const el = textareaRef.value;\n if (!el) return;\n\n const start = el.selectionStart;\n const end = el.selectionEnd;\n const text = stringValue.value;\n const selected = text.slice(start, end);\n\n const newText = text.slice(0, start) + before + selected + after + text.slice(end);\n emit('update:modelValue', newText);\n\n nextTick(() => {\n el.focus();\n const cursorPos = selected\n ? start + before.length + selected.length + after.length\n : start + before.length;\n el.setSelectionRange(cursorPos, cursorPos);\n });\n};\n\nconst insertHeading = (level: number) => {\n const prefix = '#'.repeat(level) + ' ';\n const el = textareaRef.value;\n if (!el) return;\n\n const start = el.selectionStart;\n const text = stringValue.value;\n\n // Find start of current line\n const lineStart = text.lastIndexOf('\\n', start - 1) + 1;\n const lineEnd = text.indexOf('\\n', start);\n const actualEnd = lineEnd === -1 ? text.length : lineEnd;\n const line = text.slice(lineStart, actualEnd);\n\n // Strip existing heading markers\n const stripped = line.replace(/^#{1,6}\\s*/, '');\n const newLine = prefix + stripped;\n\n const newText = text.slice(0, lineStart) + newLine + text.slice(actualEnd);\n emit('update:modelValue', newText);\n\n nextTick(() => {\n el.focus();\n el.setSelectionRange(lineStart + newLine.length, lineStart + newLine.length);\n });\n};\n\nconst insertBold = () => insertAtCursor('**', '**');\nconst insertItalic = () => insertAtCursor('_', '_');\nconst insertCode = () => insertAtCursor('`', '`');\nconst insertCodeBlock = () => insertAtCursor('\\n```\\n', '\\n```\\n');\nconst insertLink = () => insertAtCursor('[', '](url)');\nconst insertList = () => insertAtCursor('\\n- ');\nconst insertOrderedList = () => insertAtCursor('\\n1. ');\nconst insertQuote = () => insertAtCursor('\\n> ');\nconst insertHr = () => insertAtCursor('\\n---\\n');\n\n/* ──────── Markdown → HTML rendering ──────── */\n\nconst renderedHtml = computed(() => {\n return markdownToHtml(stringValue.value);\n});\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\nfunction markdownToHtml(md: string): string {\n if (!md) return '';\n\n const lines = md.split('\\n');\n const html: string[] = [];\n let inCodeBlock = false;\n let inList = false;\n let inOrderedList = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Code blocks\n if (line.trim().startsWith('```')) {\n if (inCodeBlock) {\n html.push('</code></pre>');\n inCodeBlock = false;\n } else {\n inCodeBlock = true;\n html.push('<pre class=\"t-md-editor__code-block\"><code>');\n }\n continue;\n }\n\n if (inCodeBlock) {\n html.push(escapeHtml(line));\n html.push('\\n');\n continue;\n }\n\n // Close open lists if needed\n const isUnorderedListItem = /^[-*+]\\s/.test(line.trim());\n const isOrderedListItem = /^\\d+\\.\\s/.test(line.trim());\n\n if (inList && !isUnorderedListItem) {\n html.push('</ul>');\n inList = false;\n }\n if (inOrderedList && !isOrderedListItem) {\n html.push('</ol>');\n inOrderedList = false;\n }\n\n // Horizontal rule\n if (/^(-{3,}|_{3,}|\\*{3,})$/.test(line.trim())) {\n html.push('<hr class=\"t-md-editor__hr\" />');\n continue;\n }\n\n // Headings\n const headingMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (headingMatch) {\n const level = headingMatch[1].length;\n html.push(`<h${level} class=\"t-md-editor__heading t-md-editor__heading--${level}\">${inlineMarkdown(escapeHtml(headingMatch[2]))}</h${level}>`);\n continue;\n }\n\n // Blockquote\n if (line.trim().startsWith('> ')) {\n html.push(`<blockquote class=\"t-md-editor__blockquote\">${inlineMarkdown(escapeHtml(line.trim().slice(2)))}</blockquote>`);\n continue;\n }\n\n // Unordered list\n if (isUnorderedListItem) {\n if (!inList) {\n html.push('<ul class=\"t-md-editor__list\">');\n inList = true;\n }\n html.push(`<li>${inlineMarkdown(escapeHtml(line.trim().slice(2)))}</li>`);\n continue;\n }\n\n // Ordered list\n if (isOrderedListItem) {\n if (!inOrderedList) {\n html.push('<ol class=\"t-md-editor__list t-md-editor__list--ordered\">');\n inOrderedList = true;\n }\n const content = line.trim().replace(/^\\d+\\.\\s/, '');\n html.push(`<li>${inlineMarkdown(escapeHtml(content))}</li>`);\n continue;\n }\n\n // Empty line\n if (line.trim() === '') {\n html.push('<br />');\n continue;\n }\n\n // Paragraph\n html.push(`<p class=\"t-md-editor__paragraph\">${inlineMarkdown(escapeHtml(line))}</p>`);\n }\n\n // Close any open blocks\n if (inCodeBlock) html.push('</code></pre>');\n if (inList) html.push('</ul>');\n if (inOrderedList) html.push('</ol>');\n\n return html.join('\\n');\n}\n\nfunction inlineMarkdown(text: string): string {\n // Images: ![alt](url)\n text = text.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, '<img src=\"$2\" alt=\"$1\" class=\"t-md-editor__image\" loading=\"lazy\" />');\n // Links: [text](url)\n text = text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>');\n // Bold: **text**\n text = text.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');\n // Italic: _text_ or *text*\n text = text.replace(/_(.+?)_/g, '<em>$1</em>');\n text = text.replace(/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, '<em>$1</em>');\n // Inline code: `text`\n text = text.replace(/`(.+?)`/g, '<code class=\"t-md-editor__inline-code\">$1</code>');\n // Strikethrough: ~~text~~\n text = text.replace(/~~(.+?)~~/g, '<del>$1</del>');\n return text;\n}\n\n/* ──────── Image paste / drop handling ──────── */\n\nconst handlePaste = async (event: ClipboardEvent) => {\n if (props.disabled) return;\n\n const items = event.clipboardData?.items;\n if (!items) return;\n\n for (const item of items) {\n if (item.type.startsWith('image/')) {\n event.preventDefault();\n const file = item.getAsFile();\n if (file) await processImageUpload(file);\n return;\n }\n }\n};\n\nconst handleDrop = async (event: DragEvent) => {\n if (props.disabled) return;\n\n const files = event.dataTransfer?.files;\n if (!files) return;\n\n for (const file of files) {\n if (file.type.startsWith('image/')) {\n event.preventDefault();\n await processImageUpload(file);\n }\n }\n};\n\nconst handleDragOver = (event: DragEvent) => {\n if (props.disabled) return;\n event.preventDefault();\n};\n\nconst processImageUpload = async (file: File) => {\n if (!props.uploadImage) {\n // Fallback: insert a placeholder with the file name\n insertAtCursor(`![${file.name}]()`);\n return;\n }\n\n // Insert uploading placeholder\n const placeholder = `![Uploading ${file.name}...]()`;\n insertAtCursor(placeholder);\n isUploading.value = true;\n\n try {\n const url = props.uploadImage(file);\n const resolvedUrl = url instanceof Promise ? await url : url;\n\n // Replace placeholder with actual URL\n const currentValue = stringValue.value;\n const newValue = currentValue.replace(placeholder, `![${file.name}](${resolvedUrl})`);\n emit('update:modelValue', newValue);\n emit('image-upload', file, resolvedUrl);\n } catch (err) {\n // Remove placeholder on error\n const currentValue = stringValue.value;\n const newValue = currentValue.replace(placeholder, '');\n emit('update:modelValue', newValue);\n emit('image-upload-error', file, err instanceof Error ? err : new Error(String(err)));\n } finally {\n isUploading.value = false;\n }\n};\n\n/* ──────── Keyboard shortcuts ──────── */\n\nconst handleKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n const mod = event.metaKey || event.ctrlKey;\n if (!mod) return;\n\n switch (event.key) {\n case 'b':\n event.preventDefault();\n insertBold();\n break;\n case 'i':\n event.preventDefault();\n insertItalic();\n break;\n case 'k':\n event.preventDefault();\n insertLink();\n break;\n case 'e':\n event.preventDefault();\n insertCode();\n break;\n }\n};\n\n</script>\n\n<template>\n <div\n v-bind=\"editorAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <!-- Toolbar -->\n <div\n class=\"t-md-editor__toolbar\"\n role=\"toolbar\"\n aria-label=\"Markdown formatting\"\n >\n <div class=\"t-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Heading 1 (H1)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(1)\"\n >\n H1\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Heading 2 (H2)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(2)\"\n >\n H2\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Heading 3 (H3)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(3)\"\n >\n H3\n </button>\n </div>\n\n <div\n class=\"t-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"t-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Bold (Ctrl+B)\"\n :disabled=\"disabled\"\n @click=\"insertBold\"\n >\n <strong>B</strong>\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Italic (Ctrl+I)\"\n :disabled=\"disabled\"\n @click=\"insertItalic\"\n >\n <em>I</em>\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Strikethrough\"\n :disabled=\"disabled\"\n @click=\"insertAtCursor('~~', '~~')\"\n >\n <del>S</del>\n </button>\n </div>\n\n <div\n class=\"t-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"t-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Inline code (Ctrl+E)\"\n :disabled=\"disabled\"\n @click=\"insertCode\"\n >\n &lt;/&gt;\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Code block\"\n :disabled=\"disabled\"\n @click=\"insertCodeBlock\"\n >\n { }\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Link (Ctrl+K)\"\n :disabled=\"disabled\"\n @click=\"insertLink\"\n >\n 🔗\n </button>\n </div>\n\n <div\n class=\"t-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"t-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Unordered list\"\n :disabled=\"disabled\"\n @click=\"insertList\"\n >\n •&nbsp;List\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Ordered list\"\n :disabled=\"disabled\"\n @click=\"insertOrderedList\"\n >\n 1.&nbsp;List\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Blockquote\"\n :disabled=\"disabled\"\n @click=\"insertQuote\"\n >\n &gt;\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Horizontal rule\"\n :disabled=\"disabled\"\n @click=\"insertHr\"\n >\n ―\n </button>\n </div>\n\n <slot name=\"toolbar\" />\n </div>\n\n <!-- Editor body -->\n <div class=\"t-md-editor__body\">\n <!-- Write pane -->\n <div\n class=\"t-md-editor__pane t-md-editor__pane--write\"\n >\n <textarea\n ref=\"textareaRef\"\n class=\"t-md-editor__textarea\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-label=\"placeholder\"\n @input=\"onInput\"\n @paste=\"handlePaste\"\n @drop=\"handleDrop\"\n @dragover=\"handleDragOver\"\n @keydown=\"handleKeydown\"\n />\n </div>\n\n <!-- Preview pane -->\n <div\n class=\"t-md-editor__pane t-md-editor__pane--preview\"\n aria-label=\"Markdown preview\"\n >\n <!-- eslint-disable vue/no-v-html -->\n <div\n class=\"t-md-editor__preview\"\n v-html=\"renderedHtml\"\n />\n <!-- eslint-enable vue/no-v-html -->\n </div>\n </div>\n\n <!-- Upload indicator -->\n <div\n v-if=\"isUploading\"\n class=\"t-md-editor__upload-bar\"\n role=\"status\"\n aria-live=\"polite\"\n >\n Uploading image…\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs, nextTick } from 'vue';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n size?: TSize;\n disabled?: boolean;\n placeholder?: string;\n uploadImage?: (file: File) => Promise<string>;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n placeholder: 'Write your markdown here...',\n uploadImage: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'image-upload': [file: File, url: string];\n 'image-upload-error': [file: File, error: Error];\n}>();\n\ndefineSlots<{\n toolbar?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst textareaRef = ref<HTMLTextAreaElement | null>(null);\nconst isUploading = ref(false);\n\nconst rootClasses = computed(() => [\n 't-md-editor',\n `t-md-editor--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-uploading': isUploading.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst editorAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value);\n};\n\n/* ──────── Toolbar Actions ──────── */\n\nconst insertAtCursor = (before: string, after = '') => {\n const el = textareaRef.value;\n if (!el) return;\n\n const start = el.selectionStart;\n const end = el.selectionEnd;\n const text = stringValue.value;\n const selected = text.slice(start, end);\n\n const newText = text.slice(0, start) + before + selected + after + text.slice(end);\n emit('update:modelValue', newText);\n\n nextTick(() => {\n el.focus();\n const cursorPos = selected\n ? start + before.length + selected.length + after.length\n : start + before.length;\n el.setSelectionRange(cursorPos, cursorPos);\n });\n};\n\nconst insertHeading = (level: number) => {\n const prefix = '#'.repeat(level) + ' ';\n const el = textareaRef.value;\n if (!el) return;\n\n const start = el.selectionStart;\n const text = stringValue.value;\n\n // Find start of current line\n const lineStart = text.lastIndexOf('\\n', start - 1) + 1;\n const lineEnd = text.indexOf('\\n', start);\n const actualEnd = lineEnd === -1 ? text.length : lineEnd;\n const line = text.slice(lineStart, actualEnd);\n\n // Strip existing heading markers\n const stripped = line.replace(/^#{1,6}\\s*/, '');\n const newLine = prefix + stripped;\n\n const newText = text.slice(0, lineStart) + newLine + text.slice(actualEnd);\n emit('update:modelValue', newText);\n\n nextTick(() => {\n el.focus();\n el.setSelectionRange(lineStart + newLine.length, lineStart + newLine.length);\n });\n};\n\nconst insertBold = () => insertAtCursor('**', '**');\nconst insertItalic = () => insertAtCursor('_', '_');\nconst insertCode = () => insertAtCursor('`', '`');\nconst insertCodeBlock = () => insertAtCursor('\\n```\\n', '\\n```\\n');\nconst insertLink = () => insertAtCursor('[', '](url)');\nconst insertList = () => insertAtCursor('\\n- ');\nconst insertOrderedList = () => insertAtCursor('\\n1. ');\nconst insertQuote = () => insertAtCursor('\\n> ');\nconst insertHr = () => insertAtCursor('\\n---\\n');\n\n/* ──────── Markdown → HTML rendering ──────── */\n\nconst renderedHtml = computed(() => {\n return markdownToHtml(stringValue.value);\n});\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\nfunction markdownToHtml(md: string): string {\n if (!md) return '';\n\n const lines = md.split('\\n');\n const html: string[] = [];\n let inCodeBlock = false;\n let inList = false;\n let inOrderedList = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Code blocks\n if (line.trim().startsWith('```')) {\n if (inCodeBlock) {\n html.push('</code></pre>');\n inCodeBlock = false;\n } else {\n inCodeBlock = true;\n html.push('<pre class=\"t-md-editor__code-block\"><code>');\n }\n continue;\n }\n\n if (inCodeBlock) {\n html.push(escapeHtml(line));\n html.push('\\n');\n continue;\n }\n\n // Close open lists if needed\n const isUnorderedListItem = /^[-*+]\\s/.test(line.trim());\n const isOrderedListItem = /^\\d+\\.\\s/.test(line.trim());\n\n if (inList && !isUnorderedListItem) {\n html.push('</ul>');\n inList = false;\n }\n if (inOrderedList && !isOrderedListItem) {\n html.push('</ol>');\n inOrderedList = false;\n }\n\n // Horizontal rule\n if (/^(-{3,}|_{3,}|\\*{3,})$/.test(line.trim())) {\n html.push('<hr class=\"t-md-editor__hr\" />');\n continue;\n }\n\n // Headings\n const headingMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (headingMatch) {\n const level = headingMatch[1].length;\n html.push(`<h${level} class=\"t-md-editor__heading t-md-editor__heading--${level}\">${inlineMarkdown(escapeHtml(headingMatch[2]))}</h${level}>`);\n continue;\n }\n\n // Blockquote\n if (line.trim().startsWith('> ')) {\n html.push(`<blockquote class=\"t-md-editor__blockquote\">${inlineMarkdown(escapeHtml(line.trim().slice(2)))}</blockquote>`);\n continue;\n }\n\n // Unordered list\n if (isUnorderedListItem) {\n if (!inList) {\n html.push('<ul class=\"t-md-editor__list\">');\n inList = true;\n }\n html.push(`<li>${inlineMarkdown(escapeHtml(line.trim().slice(2)))}</li>`);\n continue;\n }\n\n // Ordered list\n if (isOrderedListItem) {\n if (!inOrderedList) {\n html.push('<ol class=\"t-md-editor__list t-md-editor__list--ordered\">');\n inOrderedList = true;\n }\n const content = line.trim().replace(/^\\d+\\.\\s/, '');\n html.push(`<li>${inlineMarkdown(escapeHtml(content))}</li>`);\n continue;\n }\n\n // Empty line\n if (line.trim() === '') {\n html.push('<br />');\n continue;\n }\n\n // Paragraph\n html.push(`<p class=\"t-md-editor__paragraph\">${inlineMarkdown(escapeHtml(line))}</p>`);\n }\n\n // Close any open blocks\n if (inCodeBlock) html.push('</code></pre>');\n if (inList) html.push('</ul>');\n if (inOrderedList) html.push('</ol>');\n\n return html.join('\\n');\n}\n\nfunction inlineMarkdown(text: string): string {\n // Images: ![alt](url)\n text = text.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, '<img src=\"$2\" alt=\"$1\" class=\"t-md-editor__image\" loading=\"lazy\" />');\n // Links: [text](url)\n text = text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>');\n // Bold: **text**\n text = text.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');\n // Italic: _text_ or *text*\n text = text.replace(/_(.+?)_/g, '<em>$1</em>');\n text = text.replace(/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, '<em>$1</em>');\n // Inline code: `text`\n text = text.replace(/`(.+?)`/g, '<code class=\"t-md-editor__inline-code\">$1</code>');\n // Strikethrough: ~~text~~\n text = text.replace(/~~(.+?)~~/g, '<del>$1</del>');\n return text;\n}\n\n/* ──────── Image paste / drop handling ──────── */\n\nconst handlePaste = async (event: ClipboardEvent) => {\n if (props.disabled) return;\n\n const items = event.clipboardData?.items;\n if (!items) return;\n\n for (const item of items) {\n if (item.type.startsWith('image/')) {\n event.preventDefault();\n const file = item.getAsFile();\n if (file) await processImageUpload(file);\n return;\n }\n }\n};\n\nconst handleDrop = async (event: DragEvent) => {\n if (props.disabled) return;\n\n const files = event.dataTransfer?.files;\n if (!files) return;\n\n for (const file of files) {\n if (file.type.startsWith('image/')) {\n event.preventDefault();\n await processImageUpload(file);\n }\n }\n};\n\nconst handleDragOver = (event: DragEvent) => {\n if (props.disabled) return;\n event.preventDefault();\n};\n\nconst processImageUpload = async (file: File) => {\n if (!props.uploadImage) {\n // Fallback: insert a placeholder with the file name\n insertAtCursor(`![${file.name}]()`);\n return;\n }\n\n // Insert uploading placeholder\n const placeholder = `![Uploading ${file.name}...]()`;\n insertAtCursor(placeholder);\n isUploading.value = true;\n\n try {\n const url = props.uploadImage(file);\n const resolvedUrl = url instanceof Promise ? await url : url;\n\n // Replace placeholder with actual URL\n const currentValue = stringValue.value;\n const newValue = currentValue.replace(placeholder, `![${file.name}](${resolvedUrl})`);\n emit('update:modelValue', newValue);\n emit('image-upload', file, resolvedUrl);\n } catch (err) {\n // Remove placeholder on error\n const currentValue = stringValue.value;\n const newValue = currentValue.replace(placeholder, '');\n emit('update:modelValue', newValue);\n emit('image-upload-error', file, err instanceof Error ? err : new Error(String(err)));\n } finally {\n isUploading.value = false;\n }\n};\n\n/* ──────── Keyboard shortcuts ──────── */\n\nconst handleKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n const mod = event.metaKey || event.ctrlKey;\n if (!mod) return;\n\n switch (event.key) {\n case 'b':\n event.preventDefault();\n insertBold();\n break;\n case 'i':\n event.preventDefault();\n insertItalic();\n break;\n case 'k':\n event.preventDefault();\n insertLink();\n break;\n case 'e':\n event.preventDefault();\n insertCode();\n break;\n }\n};\n\n</script>\n\n<template>\n <div\n v-bind=\"editorAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <!-- Toolbar -->\n <div\n class=\"t-md-editor__toolbar\"\n role=\"toolbar\"\n aria-label=\"Markdown formatting\"\n >\n <div class=\"t-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Heading 1 (H1)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(1)\"\n >\n H1\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Heading 2 (H2)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(2)\"\n >\n H2\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Heading 3 (H3)\"\n :disabled=\"disabled\"\n @click=\"insertHeading(3)\"\n >\n H3\n </button>\n </div>\n\n <div\n class=\"t-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"t-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Bold (Ctrl+B)\"\n :disabled=\"disabled\"\n @click=\"insertBold\"\n >\n <strong>B</strong>\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Italic (Ctrl+I)\"\n :disabled=\"disabled\"\n @click=\"insertItalic\"\n >\n <em>I</em>\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Strikethrough\"\n :disabled=\"disabled\"\n @click=\"insertAtCursor('~~', '~~')\"\n >\n <del>S</del>\n </button>\n </div>\n\n <div\n class=\"t-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"t-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Inline code (Ctrl+E)\"\n :disabled=\"disabled\"\n @click=\"insertCode\"\n >\n &lt;/&gt;\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Code block\"\n :disabled=\"disabled\"\n @click=\"insertCodeBlock\"\n >\n { }\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Link (Ctrl+K)\"\n :disabled=\"disabled\"\n @click=\"insertLink\"\n >\n 🔗\n </button>\n </div>\n\n <div\n class=\"t-md-editor__toolbar-divider\"\n role=\"separator\"\n />\n\n <div class=\"t-md-editor__toolbar-group\">\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Unordered list\"\n :disabled=\"disabled\"\n @click=\"insertList\"\n >\n •&nbsp;List\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Ordered list\"\n :disabled=\"disabled\"\n @click=\"insertOrderedList\"\n >\n 1.&nbsp;List\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Blockquote\"\n :disabled=\"disabled\"\n @click=\"insertQuote\"\n >\n &gt;\n </button>\n <button\n type=\"button\"\n class=\"t-md-editor__toolbar-btn\"\n title=\"Horizontal rule\"\n :disabled=\"disabled\"\n @click=\"insertHr\"\n >\n ―\n </button>\n </div>\n\n <slot name=\"toolbar\" />\n </div>\n\n <!-- Editor body -->\n <div class=\"t-md-editor__body\">\n <!-- Write pane -->\n <div\n class=\"t-md-editor__pane t-md-editor__pane--write\"\n >\n <textarea\n ref=\"textareaRef\"\n class=\"t-md-editor__textarea\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-label=\"placeholder\"\n @input=\"onInput\"\n @paste=\"handlePaste\"\n @drop=\"handleDrop\"\n @dragover=\"handleDragOver\"\n @keydown=\"handleKeydown\"\n />\n </div>\n\n <!-- Preview pane -->\n <div\n class=\"t-md-editor__pane t-md-editor__pane--preview\"\n aria-label=\"Markdown preview\"\n >\n <!-- eslint-disable vue/no-v-html -->\n <div\n class=\"t-md-editor__preview\"\n v-html=\"renderedHtml\"\n />\n <!-- eslint-enable vue/no-v-html -->\n </div>\n </div>\n\n <!-- Upload indicator -->\n <div\n v-if=\"isUploading\"\n class=\"t-md-editor__upload-bar\"\n role=\"status\"\n aria-live=\"polite\"\n >\n Uploading image…\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, type Component } from 'vue';\nimport { getTreeIcon, treeIconDefaults, type TIconName } from '@treeui/icons';\n\nconst props = withDefaults(\n defineProps<{\n name: TIconName;\n size?: number | string;\n strokeWidth?: number | string;\n absoluteStrokeWidth?: boolean;\n label?: string;\n }>(),\n {\n size: treeIconDefaults.size,\n strokeWidth: treeIconDefaults.strokeWidth,\n absoluteStrokeWidth: treeIconDefaults.absoluteStrokeWidth,\n label: undefined,\n },\n);\n\nconst iconComponent = computed(() => getTreeIcon(props.name) as Component);\n</script>\n\n<template>\n <component\n :is=\"iconComponent\"\n class=\"t-icon\"\n :size=\"size\"\n :stroke-width=\"strokeWidth\"\n :absolute-stroke-width=\"absoluteStrokeWidth\"\n :role=\"label ? 'img' : undefined\"\n :aria-label=\"label || undefined\"\n :aria-hidden=\"label ? undefined : 'true'\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, type Component } from 'vue';\nimport { getTreeIcon, treeIconDefaults, type TIconName } from '@treeui/icons';\n\nconst props = withDefaults(\n defineProps<{\n name: TIconName;\n size?: number | string;\n strokeWidth?: number | string;\n absoluteStrokeWidth?: boolean;\n label?: string;\n }>(),\n {\n size: treeIconDefaults.size,\n strokeWidth: treeIconDefaults.strokeWidth,\n absoluteStrokeWidth: treeIconDefaults.absoluteStrokeWidth,\n label: undefined,\n },\n);\n\nconst iconComponent = computed(() => getTreeIcon(props.name) as Component);\n</script>\n\n<template>\n <component\n :is=\"iconComponent\"\n class=\"t-icon\"\n :size=\"size\"\n :stroke-width=\"strokeWidth\"\n :absolute-stroke-width=\"absoluteStrokeWidth\"\n :role=\"label ? 'img' : undefined\"\n :aria-label=\"label || undefined\"\n :aria-hidden=\"label ? undefined : 'true'\"\n />\n</template>\n","import type { App, Plugin } from 'vue';\nimport {\n TAccordion,\n TAccordionItem,\n TAlert,\n TBadge,\n TBreadcrumb,\n TBreadcrumbItem,\n TButton,\n TCard,\n TCheckbox,\n TCombobox,\n TConfirmDialog,\n TContainer,\n TContextMenu,\n TDatePicker,\n TDateTimePicker,\n TDrawer,\n TDropdown,\n TEmptyState,\n TFileUpload,\n TFormField,\n TGrid,\n TAppBar,\n TInput,\n TLink,\n TNavMenu,\n TNavbar,\n TMultiSelect,\n TModal,\n TNumberInput,\n TPagination,\n TPopover,\n TProgress,\n TRadio,\n TRadioGroup,\n TSelectableList,\n TSelect,\n TSidebar,\n TSkeleton,\n TSpinner,\n TStack,\n TStat,\n TStepper,\n TSteps,\n TSwitch,\n TTextarea,\n TTabs,\n TTabList,\n TTab,\n TTabPanel,\n TToggleGroup,\n TToast,\n TToastProvider,\n TTooltip,\n TAvatar,\n TDivider,\n TTable,\n TTag,\n TTreeView,\n TTimeline,\n TPricing,\n TPricingCard,\n TMarkdownEditor,\n TIcon,\n} from './components';\n\nconst components = {\n TAccordion,\n TAccordionItem,\n TAlert,\n TBadge,\n TBreadcrumb,\n TBreadcrumbItem,\n TButton,\n TCard,\n TCheckbox,\n TCombobox,\n TConfirmDialog,\n TContainer,\n TContextMenu,\n TDatePicker,\n TDateTimePicker,\n TDrawer,\n TDropdown,\n TEmptyState,\n TFileUpload,\n TFormField,\n TGrid,\n TAppBar,\n TInput,\n TLink,\n TNavMenu,\n TNavbar,\n TMultiSelect,\n TModal,\n TNumberInput,\n TRadio,\n TRadioGroup,\n TSelectableList,\n TSelect,\n TSidebar,\n TSkeleton,\n TSpinner,\n TStack,\n TStat,\n TStepper,\n TSteps,\n TSwitch,\n TTextarea,\n TTabs,\n TTabList,\n TTab,\n TTabPanel,\n TToggleGroup,\n TToast,\n TToastProvider,\n TPagination,\n TPopover,\n TProgress,\n TTooltip,\n TAvatar,\n TDivider,\n TTable,\n TTag,\n TTreeView,\n TTimeline,\n TPricing,\n TPricingCard,\n TMarkdownEditor,\n TIcon,\n};\n\nexport const TreeUIPlugin: Plugin = {\n install(app: App) {\n Object.entries(components).forEach(([name, component]) => {\n app.component(name, component);\n });\n },\n};\n\nexport const install = TreeUIPlugin.install;\n","export const treeSizes = ['sm', 'md', 'lg'] as const;\nexport const treeVariants = ['solid', 'outline', 'ghost', 'soft', 'danger'] as const;\nexport const treeCardVariants = ['outline', 'soft', 'solid', 'inset'] as const;\nexport const treeTooltipSides = ['top', 'right', 'bottom', 'left'] as const;\nexport const treeDrawerSides = ['top', 'right', 'bottom', 'left'] as const;\n\nexport type TSize = (typeof treeSizes)[number];\nexport type TVariant = (typeof treeVariants)[number];\nexport type TCardVariant = (typeof treeCardVariants)[number];\nexport type TTooltipSide = (typeof treeTooltipSides)[number];\nexport type TDrawerSide = (typeof treeDrawerSides)[number];\n\n"],"mappings":"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"}